Graftでコーディングエージェントにコードマップを追加
Graftはtree-sitterでリポジトリを解析し、MCP経由で検索できるコードベースマップを生成します。毎セッションの構造再探索を減らす仕組みと使い方を解説します。
コーディングエージェント向けコードベースマップとは
コーディングエージェント向けのコードベースマップは、リポジトリの永続的なインデックスです。エージェントは新しいセッションのたびに最初から grep で調べ回るのではなく、このインデックスを参照します。Graft はこの考え方を実装したものの 1 つです。tree-sitter でコードを解析し、相互にリンクされた Markdown ノードのフォルダーと、シンボルごとの関連付けグラフを書き出します。さらに MCP(model context protocol。コーディングエージェントが外部ツールを呼び出すために使用する標準インターフェース)経由で検索ツールを提供します。
Graft はプロキシではなく、ゲートウェイでもありません。エージェントとモデル API の間に何かを置くことはありません。マップはディスク上のフォルダーであり、エージェントが読み取ります。この違いによって、解決する問題が決まります。セルフホスト型のトークンゲートウェイは、すでに送信しているリクエストのレートを制御し、経路を振り分けます。一方、マップは送信が必要なリクエスト自体の数を変えます。
この手法は Graft よりも前から存在し、Graft がなくなった後も利用されます。まず手法を理解し、その後で仕組みを学んでください。
コーディングエージェントが構造を再発見してコンテキストを消費する理由
すでに 50 回見ているリポジトリで、エージェントが作業を始める様子を考えてみてください。ディレクトリを一覧表示し、シンボルを grep で検索します。関数を定義しているファイルを特定するために 3 つのファイルを開き、さらにその関数の呼び出し元を確認するために 4 つ目のファイルを開きます。しかし、これは本来の作業ではありません。単なる状況把握であり、毎回のセッションで入力トークンを消費します。
原因は単純です。モデルはセッション間で記憶を保持しません。エージェントがレイアウトについて学習した内容は、セッション終了時に破棄されるコンテキストウィンドウ内にありました。そのため、同じ探索が毎回ゼロから、全コストをかけて繰り返されます。大規模なリポジトリでは、編集よりも状況把握のほうがコストが高くなります。コードの場所を特定するために 10 回ツールを呼び出し、変更には 1 回しか使わないこともあります。コストの半分が状況把握、残りの半分が編集になるため、エージェントに機能する最小限の変更を徹底させるスキルは、マップの代わりに選ぶのではなく、マップと組み合わせる価値があります。
マップを使うと、探索をモデルからディスクへ移して、このループを断ち切れます。パーサーがリポジトリを 1 回走査し、各シンボルがどこで定義され、どのシンボルを呼び出しているかを記録します。その後、コードの変更に合わせて記録を最新に保ちます。エージェントは 1 つ質問するだけで、ファイルと行番号付きの回答を得られます。繰り返し行っていた探索が、低コストの検索になります。
すでに、これより簡易な仕組みを使っています。規約を記載した AGENTS.mdがあれば、エージェントは毎回規約を再確認する必要がありません。生成されたマップがあれば、構造を再確認する必要がありません。違いは、誰が作成するかです。指示ファイルは手作業で記述するため、小規模に保てます。マップはパーサーが生成するため、1 万個のファイルにも対応できます。セッション内で実際に予算がどこに使われるかについては、Claude Code がコンテキストウィンドウをどのように消費するかで内訳を説明しています。
Graft が実際に構築するもの
リポジトリのルートにある 1 つの graft/ フォルダー配下に、2 種類の成果物を作成します。
1 つ目は、リンクされた Markdown として記述されたノードグラフです。ノードごとに 1 ファイルを使用します。各ノードには、平易な英語による概要、ソースから抜き出した重要なロジック行の「核心」、コンテンツハッシュ付きの正確なソースファイル、他のノードへの型付き Wiki リンク(depends_on、part_of、uses、implements)、そして再生成後も保持されるメモセクションが含まれます。メモには、パーサーが推測できないコンテキストを記録できます。
2 つ目は、tree-sitter が抽出するシンボル単位の構造グラフである graft/.graph/wiring.json です。定義、参照、それらの間の呼び出しエッジが含まれます。
この分割が重要なのは、モデルが必要なのは一方だけだからです。graft build は tree-sitter だけで処理され、LLM(大規模言語モデル)を呼び出しません。そのため、結果は決定的で、コストもかかりません。graft build --deep は記述式の概要とシンボル単位の核心を追加します。これらはモデル呼び出しであり、利用料金が発生します。
言語サポートには段階があり、その段階によってコールグラフをどこまで信頼できるかが決まります。TypeScript、JavaScript、Python、Go、Java では、スコープを認識したファイル間解決が行われます。Rust、C、C++、C#、Ruby、PHP、Kotlin、Scala、Swift、Elixir、Solidity、OCaml、Zig、Dart では、シンボルと汎用的な呼び出しエッジが取得されます。つまり、エッジが解決済みの参照ではなく、名前の一致を示す場合があります。コンパイラー相当のエッジは --lsp と、rust-analyzer または gopls などの言語サーバーを使用してオプトインできます。
Graft をインストールしてバージョンを固定する
Graft には Node.js 20 以降が必要で、MIT ライセンスで提供されています。2026 年 8 月時点の最新リリースは 0.10.1 で、最初に公開されたバージョン 0.1.0 の公開日は 2026 年 7 月です。まだ新しいソフトウェアとして扱ってください。
npm install -g @nanonets/graft@0.10.1
npm ls -g @nanonets/graftnpm ls -g は @nanonets/graft@0.10.1 を出力するはずです。そのバージョンを意図的に固定してください。単独の npm install -g @nanonets/graft は、実行時点の latest タグを解決します。1 か月に複数のマイナーリリースが公開されるプロジェクトでは、月曜日に同僚がインストールしたものと、火曜日に自分が実行したものが異なる可能性があります。バージョンを固定すると、全員で CLI のフラグとグラフ形式を同じにできます。アップグレードのタイミングも自分で決められます。
次に、自分が管理するリポジトリに組み込みます。
cd /path/to/your/repo
graft init --dry-run
graft initgraft init は、接続するコーディングエージェントを選択するよう求め、その後でグラフを構築します。最初に --dry-run を実行し、変更対象として表示されたファイルの一覧を確認してください。一部のファイルはリポジトリの外部にあるためです。graft init は冪等性があり、既存の設定を上書きしません。そのため、2 回目も安全に実行できます。
2026 年 8 月時点で、この組み込みは Claude Code、Cursor、Codex、GitHub Copilot、Google Gemini、Kiro、Windsurf、AdaL に対応しています。Claude Code との統合が最も深く、MCP サーバーのエントリ、グラフのサイズと古さを示す statusline、グラフを再構築する編集後フック、.claude/ 配下の skill ファイルが追加されます。その他のエージェントには、ツールが存在することを伝える instruction ファイルまたは rule ファイルが追加されます。したがって「対応」とは、Graft が組み込み設定を書き込むことを意味します。エージェントが独自の rules ファイルを読み込まなければ、マップも読み込みません。これは通常の エージェントが指示を無視する理由であり、ここでも同じです。
リポジトリに入るものと、git の管理対象外になるもの
graft initの後は、次の状態になります。
graft/: markdown ノードグラフとgraft/.graph/wiring.jsonです。.gitignoreに追加されます。.mcp.json: graft MCP server を登録する設定です。Claude Code が起動時にサーバーを開始します。.claude/settings.json: 既存の内容に統合され、statusline と post-edit hooks が追加されます。AGENTS.md、GEMINI.md、.github/copilot-instructions.md、.cursor/rules/graft.mdc、.kiro/steering/graft.md、.windsurf/rules/graft.md、.adal/skills/graft/SKILL.md: 選択した agents に対応するファイルに、marker-fenced sections として追加されます。~/.codex/config.toml、~/.codex/hooks.json、~/.codex/hooks/graft/graft-hooks.cjs: マシン全体に適用され、Codex を選択した場合のみ書き込まれます。graft init --no-globalはこれらを省略し、graft init --no-hooksは hook shim のみを省略します。
グラフは node_modules と同様にキャッシュです。コミットしないでください。コードから数秒で再生成でき、ほぼすべての編集で変更されます。コミットすると、1 行の修正が数百ファイルの差分になり、レビュー担当者が確認しない差分になります。代わりに、AGENTS.mdや .mcp.jsonなどの連携設定をコミットしてください。チームメンバーはリポジトリを clone し、graft buildを実行すれば、自分のローカルグラフを取得できます。
最初のコミットの前に、ignore ルールが追加されたことを確認してください。
grep -n graft .gitignore
git status --shortgrepは graft/を含む行を出力し、git status --shortは graft/配下を何も表示しないはずです。その出力に graft/配下のファイルが表示される場合、ignore エントリが不足しているか、別の場所で上書きされています。コミット前に修正してください。git は一度追加したファイルの追跡を継続するため、後から .gitignoreを編集しても追跡対象から外れません。
MCP server を手動で登録する場合や、インストールしたバージョンと同じバージョンに固定する場合は、次のように小さなエントリで済みます。
{
"mcpServers": {
"graft": {
"command": "npx",
"args": ["-y", "@nanonets/graft@0.10.1", "mcp"]
}
}
}grep の代わりにエージェントが呼び出す検索ツール
Graft は MCP 経由で6つのツールを提供します。graft_find_code はタスクの説明に基づいて、ファイルと行番号を含むランク付け済みのノードを返します。graft_file_api は、本文を除くファイル内のすべてのシグネチャを返します。graft_trace_calls は、呼び出し元または呼び出し先を複数の階層にわたってたどります。graft_find_all は、正規表現の一致結果をシンボル別にまとめて返します。graft_repo_map は、不慣れなリポジトリの全体像を最初に確認するための情報を返します。graft_check_freshness は、グラフが現在のコードと一致しているかを報告します。
各ツールには CLI 版もあります。実際にエージェントへ渡されている内容を確認する方法はこれです。
graft map .
graft ask "where do we validate the refresh token"
graft skeleton src/auth/session.ts
graft callers validateRefreshToken
graft callers validateRefreshToken --direction out
graft grep "refresh_token" --jsongraft ask はファイルの内容ではなく、file:line 参照を含むランク付け済みのノードを出力します。仕組みはこれだけです。エージェントは適切なファイルを探すために10個のファイルを読むのではなく、ポインターを受け取り、1つのファイルを開きます。graft viz を使うと、必要に応じて localhost 上でインタラクティブビューアーを開き、グラフを自分で確認できます。30秒で回答できる質問に対してgraft ask が有用な結果を返さない場合、グラフが古いか、使用している言語が広範なティアに属しています。その場合、マップはエージェントにも役立ちません。
見落としやすいコストが1つあります。6つのツール定義は、セッション全体を通じて毎回のリクエストの system prompt に注入されます。エージェントがマップを使うかどうかにかかわらず、この分のコストが発生します。コンテキストに収まるほど小さなリポジトリでは、固定コストが、削減できる探索コストを上回る場合があります。
コードが変更されたとき、グラフはどうなりますか
構造の更新は低コストで自動的に行われます。Graft は git ではなく作業ツリーを読み取るため、コミットしていない編集もステージング済みの編集も同じように認識します。クエリでは、stat が変更されたファイルだけを再解析します。プロジェクトのドキュメントでは、この処理のオーバーヘッドは約 3 ms とされています。ターン終了時の再構築では、コードが移動したファイルだけが処理されます。GRAFT_NO_REFRESH=1 を設定するか --no-refresh を渡すと、再解析せずにディスク上のグラフから回答します。--no-reuse を渡すと、すべてをコールド再解析します。これは Graft 自体をアップグレードした後に使用します。
モデルが生成する部分の動作は異なり、問題が静かに発生するのもこの部分です。要約と核心情報はキャッシュされます。各ノードはソースのコンテンツハッシュを記録しているため、ソースファイルが変更されると、ノードは最新として扱われず、古い状態としてマークされます。このフラグは、何らかの処理が行われる場合にのみ役立ちます。graft build --deep で更新すると、再びモデルのトークンを消費します。
古い状態を可視化します。
graft check .
echo $?終了ステータス 0 は、グラフとコードが一致していることを示します。終了ステータス 1 は、差異があることを示します。これを pre-push hook から実行するか、CI でブランチに対して実行してください。そうすれば、6 か月前に作成されたマップが、3 月に書き換えられたコードについて確信を持って回答することを防げます。
公開されたベンチマーク数値を慎重に確認する
Graft の主張の要点は、「最大で 4 倍安く、3 倍速く、正確性は向上するか、少なくとも低下しない」というものです。これらは、プロジェクト自身が実施し、README で公開しているベンチマークに基づいています。以下に、報告されている 2 つの実行結果を全文で示します。
The data behind this chart
[
{
"label": "Controlled sweep",
"run_count": 162,
"token_saving_pct": 42,
"tool_call_saving_pct": 46,
"correctness_pct": 93,
"baseline_correctness_pct": 93
},
{
"label": "SWE-bench Verified",
"run_count": 50,
"token_saving_pct": 23,
"tool_call_saving_pct": 25,
"correctness_pct": 66,
"baseline_correctness_pct": 54
}
]制御スイープは、2 つのリポジトリ(そのうち 1 つは Graft 自身)に対して、タスクごとに 3 回の試行を行う 162 回の実行です。トークンは 42% 少なく、ツール呼び出しは 46% 少ないと報告されています。SWE-bench Verified の実行は、両方の方式で同じモデルを使用した 50 件のインスタンスで、削減幅はより小さく、トークンは 23%、ツール呼び出しは 25% と報告されています。3 つ目の実行では、PocketBase のマージ済み pull request 5 件を再現し、コストはベースラインの 13.91 US dollars に対して 11.02 US dollars でした。
これらはすべて、ベンダーが実施したベンチマークとして扱ってください。ここから分かることには、2 つの制約があります。制御スイープには Graft 自身のリポジトリが含まれています。これは、作成者が調整を行った対象のコードベースです。SWE-bench Verified は、よく知られたオープンソースの Python プロジェクトから収集した課題の公開データセットです。意図的かどうかにかかわらず、ツールは公開データセットに対して最適化されます。どちらも、独自の命名規則と不要コードを持つ、あなたのプライベートなモノレポについての結果ではありません。
正確性については、もう一度確認する必要があります。制御スイープでは変化していません。map 使用時は 93%、未使用時は 93% です。54% から 66% への向上は、SWE-bench Verified でのみ確認されています。トークン料金を削減し、品質を維持できるツールであれば、それでも十分に有用です。ただし、SWE-bench の正確性結果をスイープのトークン結果にそのまま適用し、両方を 1 つの主張として引用しないでください。
自分のトークン差分を測定してから判断してください
重要なのは、リポジトリから得られた数値だけです。この方法は半日で実施できます。
完全に同じ手順を繰り返せるタスクを選びます。編集ではなく質問が適しています。編集を行うとリポジトリが変わり、2 回目の実行が同じ実験にならないためです。「ログインルートのレート制限を適用しているモジュールはどれか」という形式が適しています。
テレメトリを有効にし、自分のターミナルへ送信します。
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console
claudeコンソールエクスポーターは、収集したメトリクスレコードをそのまま出力します。確認するのは claude_code.token.usage です。このレコードには、type 属性として input、output、cacheRead、または cacheCreation が含まれます。ファイル内容が出力されるため、オリエンテーションは input と cacheRead に現れます。この 2 つを合計します。
マップを接続した状態で、タスクを新しいセッションごとに 3 回実行します。次に .mcp.json から graft エントリを削除し、さらに 3 回実行します。1 回の実行結果ではなく中央値を比較します。エージェントの実行結果には大きなばらつきがあり、たまたま不運な 1 回の実行によって、正反対の結論に至ることがあるためです。ツール呼び出し回数も記録します。ツール呼び出しは仕組みであり、トークンは結果です。そのため、ツール呼び出し回数が減っていないのにトークンだけが削減された場合は、別の要因が変化しています。
次に、ベンチマークに表示されないコストを差し引きます。graft build --deep は、完全な更新のたびにモデルのトークンを消費します。6 個のツールスキーマも、すべてのリクエストに含まれます。エージェントをレンタルしたサーバー上で実行している場合は、エージェントの支出に上限を設定することで、予期しない支出を予算として管理できます。また、エクスポーターを有効にした後にマシンから送信される情報については、コーディングエージェントのテレメトリが実際に報告する内容を参照してください。
コードベースのマップが役に立たなくなるのはどのような場合ですか?
- リポジトリがすでにコンテキストに収まる場合。 小規模な単一サービスにマップは不要です。リクエストごとに6つのツールスキーマのコストも発生します。エージェントが現在、1回か2回のツール呼び出しで必要なファイルを見つけられるなら、マップは使わないでください。
- 使用言語が広範な対応層にある場合。 一般的な呼び出しエッジでは、
graft callersが呼び出し元を見落としたり、名前の衝突によって誤った呼び出し元を生成したりする可能性があります。影響範囲を信頼する前に、graft grepで確認してください。 - グラフが古くなり、誰も気付いていない場合。
graft checkは差分があると終了コード1で終了します。ただし、何かが実行している場合にのみ有効です。習慣に頼るのではなく、フックまたは CI のステップとして実行してください。 - モノレポでスコープ指定が必要な場合。 単一の Git モノレポは、ワークスペースファイル、
go.mod、pyproject.toml、またはCargo.tomlによって自動的に分割され、graft ask "..." --in services/billing/でクエリを1つのサブプロジェクトに絞り込めます。パッケージごとにネストした AGENTS.md ファイルを配置するのと同じ考え方を、マップにも適用してください。 - エージェントが関連付けを無視する場合。 マップが使われていると判断する前に、実際のセッションでツール呼び出しを確認してください。エージェントが
grepを実行し続けているなら、ルールファイルを一度も読んでいないということです。
FAQ
graft/ フォルダーを git にコミットすべきですか?
いいえ。graft build は、グラフが node_modules と同様に再生成可能なキャッシュであるため、graft/ を .gitignore に自動的に追加します。ほぼすべての編集で内容が変わるため、コミットすると、生成ファイルが数百個作られ、実際の差分が埋もれます。マップの存在をエージェントに知らせる設定をコミットしてください。AGENTS.md と .mcp.json もその一部です。各チームメンバーは graft build をローカルで実行します。最初のコミット前に grep -n graft .gitignore と git status --short で確認してください。git は一度追加したファイルの追跡を続けるため、後から .gitignore を編集しても追跡は解除されません。
Graft の実行には費用がかかりますか?
構造解析部分にはかかりません。graft build、graft ask、graft check、および 6 個の MCP 取得ツールは tree-sitter の処理であり、モデルを呼び出しません。graft build --deep は有料部分です。LLM を使って平易な英語の要約とシンボルごとの要点を作成します。GRAFT_PROVIDER、GRAFT_API_KEY、GRAFT_MODEL で設定し、OpenAI 互換エンドポイントには GRAFT_BASE_URL も使用します。構造解析だけで Graft を実行し、グラフ自体にトークンを使わない構成も可能です。
コードベースのマップで、リポジトリのコストをどの程度削減できますか?
測定しなければ判断できません。プロジェクトの報告では、マップなしのベースラインと比較して、独自の 162 回の実行による調査でトークンが 42% 少なくなり、SWE-bench Verified では 23% 少なくなっています。いずれもベンダーのベンチマークです。一方は Graft 自身のリポジトリで一部実行されています。どちらも、非公開コードについては説明していません。再現可能な質問を 1 つ選び、マップありで 3 回、マップなしで 3 回実行してください。その際、CLAUDE_CODE_ENABLE_TELEMETRY=1 と OTEL_METRICS_EXPORTER=console を設定します。次に、input と cacheRead の種類について、claude_code.token.usage の中央値を比較してください。
リファクタリングするとグラフはどうなりますか?
構造は自動的に再解析されます。Graft は作業ツリーの状態を確認し、変更されたファイルだけを再解析します。そのため、名前変更は次のクエリで反映され、追加のオーバーヘッドはおよそ 3 ms です。また、git の履歴ではなくファイルを読み取るため、コミットしていない変更も認識します。古くなるのは、モデルが作成した要約です。各ノードにはソースのコンテンツハッシュが保存され、ソースが変更されると、ノードは書き換えられず stale としてマークされます。graft check . で差分を確認し、graft build --deep で記述部分を更新してください。
現在、どのコーディングエージェントが Graft を利用できますか?
2026 年 8 月時点で、graft init は Claude Code、Cursor、Codex、GitHub Copilot、Google Gemini、Kiro、Windsurf、AdaL を連携します。Claude Code の対応が最も充実しており、.mcp.json の MCP サーバーエントリ、ステータスライン、編集後フック、.claude/ の skill ファイルが提供されます。Codex には AGENTS.md セクションと、~/.codex/ のマシン全体のエントリが追加されます。ただし、graft init --no-global はそれをスキップします。その他のエージェントには、rules ファイルまたは steering ファイルが追加されます。その他の MCP クライアントでも、npx -y @nanonets/graft@0.10.1 mcp コマンドを登録すればサーバーを直接利用できます。