言語が混在するモノレポで「この関数はどこから呼ばれているのか」「もう誰も使っていないから消して安全か」を確かめようとすると、調査そのものに時間が溶けていきます。grep は文字列としての一致しか教えてくれず、呼び出し関係を数ホップ辿るには結局人間が読むしかありません。
AI コーディングエージェントに聞けば早いように思えますが、ここにも壁があります。リポジトリ全体を読ませればコンテキストが膨らみ、部分的に読ませれば「見えていない呼び出し元」を平気で見落とします。エージェントが返す「この関数はどこからも呼ばれていません」を、そのまま信じて削除できるチームは多くないはずです。
この問題に対して、コードの構造そのものをグラフとして永続化し、そこに問い合わせるという解き方を取るのが vitali87/code-graph-rag(製品表記は Code-Graph-RAG)です。Tree-sitter でソースコードを解析し、関数・クラス・モジュールとその関係をグラフデータベース Memgraph に構築します。LLM が担うのは自然言語からグラフクエリ言語 Cypher への変換と回答生成であり、構造の抽出自体は AST から決定的に行われます。
なお、GitHub 上のリポジトリ名と PyPI のパッケージ名は code-graph-rag、CLI コマンドは cgr です。本記事では製品名として言及するときは Code-Graph-RAG、コマンドやパッケージとして言及するときは code-graph-rag / cgr と表記を使い分けます。
本記事は公開されている README と公式ドキュメントを一次ソースとした読み解きであり、インストールや動作検証は行っていません。そのぶん「公式が何をどこまで保証しているか」「どこに明示的な制約があるか」を正確に拾うことに重点を置き、仕組み・グラフスキーマ・対応言語の階層・導入時の制約・類似 OSS との違いを整理します。自分のリポジトリに入れる価値があるかどうかを、読み終えた時点で判断できる状態を目指します。
- code-graph-ragとは|モノレポを知識グラフにするOSS
- code-graph-ragの仕組み:Tree-sitterで解析しMemgraphに知識グラフを作る
- 知識グラフのスキーマ:ノード種別とリレーションの設計
- 対応言語は3階層:フル対応13言語・構造対応8言語・ドキュメント階層
- code-graph-ragでできること:自然言語クエリ・デッドコード検出・データフロー追跡
- Claude Codeから使う:code-graph-ragのMCPサーバー
- 導入前に押さえるcode-graph-ragの制約とハマりどころ
- 類似OSSとの違い:serena・potpie・GraphRAGとの比較
- code-graph-ragが向くケース・向かないケース
- まとめ
code-graph-ragとは|モノレポを知識グラフにするOSS
Code-Graph-RAG は、マルチ言語のコードベースを Tree-sitter で解析し、その構造を Memgraph 上の知識グラフとして構築したうえで、自然言語でクエリ・編集・最適化できるようにする OSS です。README は「混在した言語のモノレポを、単一の統一されたグラフスキーマの下で扱える」ことを冒頭で掲げています(出典: vitali87/code-graph-rag)。
まず、採用判断の前提になる基本情報を押さえておきます。以下は 2026 年 8 月 26 日時点の GitHub API 取得値です。
項目 | 値 |
|---|---|
リポジトリ | vitali87/code-graph-rag |
スター数 | 4,819 |
フォーク数 | 638 |
主要言語 | Python |
ライセンス | MIT |
最終更新(push) | 2026-08-26 |
リポジトリの状態 | 公開・アーカイブされていない・フォークではない |
このリポジトリはアーカイブ済みではなく、他リポジトリのフォークでもない本家のリポジトリです。最終 push は調査当日で、README の「Latest News」にも Java のテイント追跡強化、C# のテイント伝播改善、Python 向けの in-process Jedi セマンティックフロントエンド追加、protobuf の正準インデックス導入、7 言語への構造 ast-grep 対応追加といった直近の変更が並んでいます。開発が止まっているプロジェクトではない、という点はまず確認できます。
README の「What It Does」が挙げる用途は次の 7 つです。
- コードベースについて自然言語で質問し、実構造に基づいた回答を得る
- 関数・クラス・メソッドのソースを、名前または意図から取得する
- AST ベースの外科的なパッチと差分プレビューを伴う、エージェント経由の編集
- 言語のベストプラクティスや自前のコーディング規約に対する最適化
- エントリポイントから呼び出し・参照エッジを辿ってデッドコードを検出する
- ast-grep により AST パターンで構造的に検索・書き換える
cgr traceでテスト実行や本番の eBPF プロファイルをトレースし、実行時に発生した呼び出しをグラフに統合して、静的解析では見えないディスパッチを可視化する
列挙するとかなり幅広く見えますが、すべてが「グラフがあるから解ける問い」に紐づいている点が特徴です。逆に言えば、グラフが持っていない情報については解けません。この線引きが導入判断の核心になるため、以降のセクションで仕組みとスキーマの側から掘り下げていきます。
code-graph-ragの仕組み:Tree-sitterで解析しMemgraphに知識グラフを作る

2つのコンポーネントと処理の流れ
README の「How It Works」によれば、システムは 2 つのコンポーネントで構成されています。
- マルチ言語パーサ: Tree-sitter ベースのパーサがコードベースを読み、関数・クラス・メソッド・モジュールとその関係を、言語非依存の単一スキーマとして Memgraph に取り込みます
- RAG システム(
codebase_rag/): 自然言語を Cypher クエリに変換し、該当するコードを取得して、AI による編集・最適化を駆動する対話型 CLI です
処理の流れは README 内に図として示されています。
Source Code -> Tree-sitter Parser -> AST Analysis -> Memgraph Knowledge Graph
|
User Query -> AI Model (Cypher Gen) -> Cypher Query -> Graph Results -> Response
図の上段と下段が分かれていることに注目してください。上段のグラフ構築パスに LLM は登場せず、下段のクエリパスで初めて AI モデルが Cypher を生成します。
LLMに任せる範囲と任せない範囲
「AI がコード構造を推測で組み立てているのではないか」という懸念は、この種のツールを初めて検討するときに真っ先に浮かぶものです。Code-Graph-RAG の設計上、その懸念は構造抽出の部分には当てはまりません。関数・クラス・import・継承といった関係は Tree-sitter の AST から決定的に導出され、LLM の推論は介在しないためです。LLM が担うのは、自然言語をグラフクエリに翻訳することと、返ってきた結果を文章にまとめることに限定されます。
この責務分割は、モデルの割り当てにも表れています。CLI リファレンスによれば cgr start は --orchestrator と --cypher で使用モデルを分けて指定でき、公式ドキュメントには anthropic:claude-sonnet-5、google:gemini-3.5-flash-lite、ollama:qwen2.5-coder といった指定例が挙げられています(出典: CLI Reference)。Cypher 生成のように定型性の高いタスクには小さいモデルやローカルモデルを割り当て、回答生成側に大きなモデルを使うといった構成が取れるということです。運用コストを見積もる際に効いてくる設計です。
主要な依存ライブラリからも、実装方針が読み取れます。アーキテクチャ概要には tree-sitter(言語非依存の AST 解析)、pymgclient(Memgraph アダプタ)、pydantic-ai(LLM 統合のエージェントフレームワーク)、mcp(Model Context Protocol SDK)に加えて、diff-match-patch(コードのパッチ適用)、watchdog(ファイルシステムイベント監視)、huggingface-hub(UniXcoder モデルのダウンロード)が挙げられています(出典: Architecture Overview)。ベクトル検索や差分適用の仕組みも併せ持っており、グラフ一本槍の構成ではないことが分かります。
知識グラフのスキーマ:ノード種別とリレーションの設計

Code-Graph-RAG が他のツールと最も異なるのは、グラフスキーマそのものを公式ドキュメントとして公開している点です。自分のユースケースがこのスキーマで表現できるかどうかは、Cypher を書く前にドキュメントを読むだけで判断できます。ここが採用可否を分ける最大の材料になるため、少し丁寧に読み解いていきます。
主なノードとリレーション
グラフスキーマのドキュメントには、既定で 18 種類のノードが定義されています。Project / Package / Folder / File / Module / Class / Function / Method / Interface / Enum / Type / Union / ModuleInterface / ModuleImplementation / ExternalPackage / ExternalModule / Resource / Section の 18 種で、これに加えて後述する findings を有効にすると Pattern / CodeSmell / SecurityIssue の 3 種が生成されます。
代表的なノードとリレーションを整理すると次のようになります。
種別 | 名前 | 意味 |
|---|---|---|
ノード |
| 関数・メソッド・クラスの定義 |
ノード |
| リポジトリ外の import 対象(サードパーティ・標準ライブラリ) |
ノード |
| 外部 I/O の対象を表す合成ノード( |
ノード |
| Markdown の見出し(ドキュメント階層) |
リレーション |
| 関数・メソッドの呼び出し |
リレーション |
| 呼び出しではない言及 |
リレーション |
| クラスのインスタンス化 |
リレーション |
| 継承・インターフェース実装 |
リレーション |
| モジュール間の依存 |
リレーション |
| I/O とデータフロー( |
ここで実務上重要なのが CALLS と REFERENCES の区別です。公式ドキュメントは REFERENCES を「値として渡された関数や、辞書に格納されたコールバック」のような、呼び出しではない言及として定義しています。つまり CALLS だけを辿ると、コールバックとして登録された関数を取りこぼします。逆に REFERENCES まで含めれば、実行されるとは限らない言及も混ざります。どちらを辿るかはクエリの目的次第で、この選択を自分でコントロールできることがグラフを直接叩ける価値です。
もう一つ、Resource ノードには resource::<KIND>::<identity> という命名規則があります。KIND は FILE / NETWORK / DATABASE / STDIN / STDOUT / STDERR / ENV / SOCKET の 8 種で、識別子が静的に決まらない場合は <dynamic> が入ります。「環境変数を読んでいる関数を全部出す」といった問いが、この命名規則によってグラフ上の単純なパターンマッチに落ちます。
capture groupという「グラフを重くしない」設計
上の表で Resource と READS_FROM / WRITES_TO / FLOWS_TO に「io 有効時のみ」と付けたのには理由があります。Code-Graph-RAG は capture group という単位で、どこまでをグラフに取り込むかを切り替えられるようになっています。
- 既定で有効:
calls(CALLS/REFERENCES/INSTANTIATESを含む標準的なコード解析) - opt-in:
io(Resourceノードとデータフローエッジ) - opt-in:
findings(ast-grep によるPattern/CodeSmell/SecurityIssueの検出)
公式ドキュメントは、opt-in のグループを有効にしない限りエッジは一切生成されず、その分の処理も走らないと明記しています。グラフ DB は入れる情報を増やすほどインデックス時間もクエリ時間も膨らむため、「全部入りにしない」ことを設計として選んでいるわけです。
裏を返すと、データフロー解析や規約チェックを目的に導入を検討している場合、既定構成のまま評価を始めると「期待した機能が動かない」と結論づけてしまうリスクがあります。何を解きたいかを先に決め、それに必要な capture group を有効にしたうえで評価する、という順番が必要です。
同名定義・ネストした定義の扱い
グラフに載せるうえで厄介なのが、同じ名前の定義が複数存在するケースです。try/except ImportError によるフォールバック実装、typing.overload、if has_x(): ... else: ... のようなイディオムでは、同一モジュール内に同じ修飾名の定義が並びます。
Code-Graph-RAG は Function / Method / Class を qualified_name で一意に識別しますが、重複した場合は最初の定義がそのままの名前を保持し、2 つ目以降に @<開始行番号> を付けて別ノードとして残します。そして呼び出し側の CALLS エッジは、すべてのバリアントに接続されます。実行時にはどちらもターゲットになり得るためです。
「グラフ上で 1 つの関数に見えるものが、実は複数の実装かもしれない」という前提を持っておくと、クエリ結果の読み方を誤りません。
ネストした定義についても方針が明示されています。関数やメソッドの内部で定義された関数・クラス(クロージャや関数ローカルクラス)は Module に平坦化されず、囲みスコープに DEFINES で接続されます。関数本体の中で定義されたクラスのメソッドは、CGR_CAPTURE_LOCAL_DEFINITIONS が有効な場合にのみ捕捉され、この設定は既定で有効です。スコープの階層がグラフ上でも保たれるため、「この関数の中だけで使われているヘルパ」を切り分けることができます。
対応言語は3階層:フル対応13言語・構造対応8言語・ドキュメント階層

導入判断で最も直接的に効くのが、自分のリポジトリの構成言語がどの階層に入るかです。言語サポートのドキュメントは、対応を明確な階層として整理しています。
フル対応言語と構造対応言語の違い
階層 | 対象言語 | 生成されるもの |
|---|---|---|
フル対応(13 言語) | C / C# / C++ / Dart / Go / Java / JavaScript / Lua / PHP / Python / Rust / TypeScript / TSX | 関数・クラス・メソッド・モジュールと、 |
開発中 | Scala、SQL(PostgreSQL) | 順次拡充中 |
構造対応(ast-grep tier、8 言語) | Ruby / Kotlin / Swift / Elixir / Haskell / Solidity / Bash / Nix |
|
ドキュメント階層 | Markdown | 見出しごとの |
ここで見落とすと痛いのが、構造対応階層の制約です。公式ドキュメントは、この階層には「コールグラフ(CALLS)の解決がなく、デッドコード検出のようなコールグラフ解析はこれらのファイルをスキップする」と明記しています。加えて、名前はフラットに扱われ、ネストした名前空間による修飾は行われません。
つまり、Ruby や Kotlin が主体のリポジトリで「使われていないメソッドを洗い出したい」という目的なら、Code-Graph-RAG は目的を満たしません。構造対応階層は「ファイルとシンボルの一覧化・import の依存関係」までであり、呼び出し関係の解析はフル対応 13 言語の範囲内です。この線引きは、採用可否をほぼ決定づけます。
Markdown のドキュメント階層も同様で、Section ノードは持ちますが関数・クラス・呼び出しを持たないため、コールグラフ解析の対象外です。設計ドキュメントとコードを同じグラフ上で串刺しにできる、という価値の方が本筋になります。
C/C++・C#のハイブリッドフロントエンド
フル対応言語の中でも、C/C++ と C# は少し特殊な構成を取っています。
C/C++ の既定は CPP_FRONTEND=hybrid です。公式ドキュメントは「tree-sitter がバックボーンであり続け(すべてのファイルが tree-sitter による定義と呼び出しを得る。何もスキップされない)、libclang はマクロの Function ノードと #include の IMPORTS エッジのみを上乗せする」と説明しています。設定値としては libclang 単独や treesitter 単独も選べます。
C# の既定は CSHARP_FRONTEND=auto で、同様に tree-sitter がバックボーンとなり、同梱の Roslyn ツール(dotnet が必要)が位置情報をキーとしたセマンティックな事実を上乗せします。hybrid / roslyn / treesitter を明示指定することもできます。
ハイブリッド構成であるということは、前提となる依存(cpp extra、あるいは PATH 上の dotnet)が欠けている環境では、上乗せ部分が失われて tree-sitter のヒューリスティックに縮退するということでもあります。C# のオーバーロード解決や INHERITS と IMPLEMENTS の厳密な分類を期待している場合は、実行環境に dotnet があるかどうかまで確認しておく必要があります。
code-graph-ragでできること:自然言語クエリ・デッドコード検出・データフロー追跡
ここからは主要機能を、「グラフがあるから解ける問い」という軸で見ていきます。機能名を並べるより、それぞれが何を教えてくれて何は教えてくれないのかをセットで押さえる方が、導入後の期待値のズレを防げます。
自然言語でグラフに問い合わせる
基本的な流れは、Memgraph を含むスタックを起動し、リポジトリをグラフに取り込み、対話 CLI で問い合わせるという 3 ステップです。README の Quick Start は次のコマンドを示しています。
# Start the packaged Memgraph + Qdrant stack (no compose file needed)
cgr daemon up
# Parse a repository into the graph, then query it
cgr start --repo-path /path/to/repo --update-graph
cgr start --repo-path /path/to/repo
コメントにあるとおり、Memgraph と Qdrant のスタックはパッケージに同梱されており、compose ファイルを自前で用意する必要はありません。インデックス対象を増やしたい場合は、リポジトリごとに --update-graph 付きのコマンドを繰り返します。
CLI には対話クエリ以外にも cgr export(グラフのエクスポート)、cgr optimize <language>(規約に対する最適化)、cgr dead-code、cgr trace といったサブコマンドが用意されています(出典: CLI Reference)。
デッドコード検出とその読み方
cgr dead-code は、エントリポイントから CALLS と REFERENCES のエッジを辿り、到達しなかった関数・メソッドを列挙します。エントリポイントとして既定で扱われるのは、エクスポート済み・public のシンボル、テストコード、ルートやタスクや CLI コマンドといったデコレータ付きのハンドラ、dunder およびライフサイクルメソッド、JavaScript/TypeScript の well-known symbol プロパティです。
この機能で最も誤解されやすいのが結果の読み方ですが、デッドコード検出のドキュメントはその点を明示しています。結果は「レビューのための候補であって、削除して安全だと保証されたリストではない」とされ、動的ディスパッチ・リフレクション・文字列キーによる参照・静的グラフからは見えない外部フレームワーク経由の呼び出しでのみ到達するコードは、それでも報告されうると但し書きされています。
先ほど触れた構造対応階層の言語についても同様の注意があります。Ruby のようにコールグラフを持たない言語のシンボルは常に到達可能として扱われ、報告されません。「Ruby のデッドコードが 0 件だった」は「Ruby には不要コードがない」ではなく「そもそも判定対象外だった」ということです。
ノイズを抑えるためのオプションは 3 つあります。-e / --entry-point で修飾名のサフィックスを指定して到達可能なルートを追加し、--decorator-root で組み込み以外のデコレータをルート扱いに拡張し、--exclude でファイルパスの glob による絞り込みを行います。
--exclude には明確な注意点があります。glob は必ずクォートしてシェル展開を防ぎ、リポジトリルートからの相対パス全体にマッチさせる必要があります。ドキュメントは tests ではなく 'tests/*' と書くこと、そして * がディレクトリ区切りをまたぐため '*tests*' のようなパターンは意図しないファイルまで除外しうることを警告しています。
I/Oとデータフロー(opt-inのテイント解析)
READS_FROM / WRITES_TO / FLOWS_TO の 3 種は、先に触れたとおり io capture group の opt-in であり、既定のビルドでは一切生成されません。
設計はテイント解析の語彙を借りています。環境変数・ファイル・ネットワークからの読み取りを source として値に印を付け、代入・引数・戻り値を通じて伝播させ、標準出力・ファイル・ネットワークへの書き込みを sink として終端します。公式ドキュメントは、ここでの「テイント」に危険性などの含意はなく、値の出所を追跡しているだけだと補足しています(出典: I/O and Data-Flow Edges)。
READS_FROM / WRITES_TO は、呼び出し可能な単位と Resource を結びます。ドキュメントの例では os.getenv("K") が Function -READS_FROM-> Resource(ENV::K) に、print(x) が Function -WRITES_TO-> Resource(STDOUT::<dynamic>) になります。帰属先は直近の囲みスコープであり、ネストした関数での読み書きが外側のスコープに繰り上げられることはありません。
FLOWS_TO は kind プロパティで 3 形態に分かれます。
| 何をつなぐか |
|
|---|---|---|
| リソースからリソースへ(読み取った値が別のリソースへの書き込みに到達) | なし |
| 呼び出し元から呼び出し先へ(引数として渡る) |
|
| 呼び出し先から呼び出し元へ(戻り値として返る) | 常に |
同時に、現段階では意図的に保守的な実装であることも明記されています。関数本体内の追跡は経路感度のない単一の前方走査であり、引数のテイント伝播は当初 1 レベルの深さに限られ、戻り値のテイントは全ファイル解析後のワークリスト不動点によってファイル横断で推移的に合成されます。Parameter ノードや SSA レベルの精度は持ちません。
広く浅くノイズごと拾うのではなく、適用できる範囲で正確さと効率を優先する、という方針が公式に宣言されている形です。セキュリティ監査の代替として期待するのではなく、「環境変数がどこを経由して外部に出ていくか」の当たりをつける道具として位置づけるのが妥当でしょう。
静的解析の穴を実行時トレースで埋める
静的解析だけではどうしても見えない呼び出しがあります。レジストリ経由のディスパッチ、getattr による参照、フレームワークがルーティングするコールバック、モンキーパッチされたターゲットは、実行時にしか存在しません。
cgr trace は、実行時に観測した呼び出しをグラフに統合することでこの穴を埋めます。動的コールトレースのドキュメントによれば、対応は正確なトレーサ(Python 3.12+、Java/Scala、PHP、Lua、C/C++)とサンプリングプロファイラ(Node.js、.NET、Dart、Go、Rust)に分かれ、さらに本番環境向けには eBPF 継続プロファイラ(Parca、Pyroscope、OpenTelemetry、perf)の出力を pprof 形式経由で取り込めます。
取り込まれた情報は CALLS エッジのプロパティとして付与されます。dynamic: true(実行時に観測されたエッジ)、dynamic_call_count(呼び出し回数)、dynamic_workloads(そのエッジを通ったテスト ID)、dynamic_receiver_types(メソッドディスパッチ時の具体型)、dynamic_sampled(サンプリングか正確なカウントか)、そして static_missed: true(対応する静的エッジが存在しなかった)です。
この static_missed フラグは、そのまま「静的解析が取りこぼしていた呼び出しの一覧」になります。デッドコード検出の結果を精査するとき、トレース済みのエッジと突き合わせれば誤検出をかなり絞り込めるはずです。
パッケージには pytest プラグインが同梱されており、pytest --cgr-trace を実行すると cgr-trace.jsonl が出力されます。各テストのノード ID が呼び出しに紐づくため、「このエッジはどのテストが通っているか」を逆引きできます。
Claude Codeから使う:code-graph-ragのMCPサーバー
Code-Graph-RAG は MCP(Model Context Protocol)サーバーとしても動作し、Claude Code をはじめとする MCP クライアントから直接クエリ・編集ができます。既にコーディングエージェントを日常的に使っているチームにとっては、ここが「今の開発フローに差し込めるか」を判断する分岐点になります。
MCP サーバーガイドは、pip 経由でインストールした場合の追加コマンドを次のように示しています。
claude mcp add --transport stdio code-graph-rag \
--env TARGET_REPO_PATH=/absolute/path/to/your/project \
--env CYPHER_PROVIDER=openai \
--env CYPHER_MODEL=gpt-5.6-luna \
--env CYPHER_API_KEY=your-api-key \
-- code-graph-rag mcp-server
出典: MCP Server
環境変数として対象リポジトリの絶対パスと、Cypher 生成に使うモデルのプロバイダ・モデル名・API キーを渡す構成です。モデル名は公式ドキュメントの記載例をそのまま引用したもので、推奨構成を意味するものではありません。
提供されるツールには、プロジェクト管理系(list_projects / delete_project / wipe_database / index_repository / update_repository)、検索・取得系(query_code_graph / get_code_snippet / semantic_search / structural_search)、編集系(surgical_replace_code / structural_replace / read_file / write_file / list_directory)、そしてエージェント委譲(ask_agent)が並びます。
このうち、一般的なコーディングエージェントでは埋めにくい穴を突いているのが次の 3 つです。
flow_verdict は、source から sink への到達可能性に 3 値で答えます。FLOWS_TO のパスが存在すれば FOUND を修飾名とともに返し、パスが存在せずカバレッジも完全であれば NO_FLOW を返します。そしてパスが見つからないもののプロジェクトの一部モジュールがフロー解析の対象外である場合は UNKNOWN を返し、対象外のファイルを列挙します。ドキュメントは、カバレッジに欠損が残っている状態での「パスがない」を「検証済みの不在」と解釈してはならないと明確に警告しています。安全性の判断に使う以上、この 3 値の区別を潰さないことが決定的に重要です。
explain_traceback は、Python のトレースバックの各フレームを Function / Method / Module ノードに解決し、呼び出し元・呼び出し先・FLOWS_TO の供給元を含むグラフ近傍とともに返します。解決できなかったフレームについては、マッチしなかった理由も併せて返されます。
rank_root_causes は、失敗を説明しうる箇所を順位付けします。スコアリングは 3 つの加算シグナル、すなわち失敗フレームに値を供給する FLOWS_TO の供給元であること、クラッシュスタック上に存在すること、CALLS を経由して失敗フレームに到達すること(近い呼び出し元ほど高スコア)で構成されます。プロジェクトに FLOWS_TO エッジがない場合は CALLS のみの走査に縮退し、flow_used=false としてカバレッジの欠損が報告されます。
3 つ目の挙動は、io capture group を有効にしているかどうかで結果の質が変わることを意味します。ツールが黙って劣化するのではなく、flow_used=false という形で明示されるのは、判断材料として扱う側にとって重要な性質です。
なお、提供ツールの個数は公式サイトとドキュメントで数え方が異なるため、本記事では個数を断定せず、ドキュメントの一覧に基づいて代表的なものを紹介しています。
導入前に押さえるcode-graph-ragの制約とハマりどころ

機能の魅力よりも、ここに挙げる制約の方が採用判断には効きます。公式ドキュメントに明記されている範囲で、事故につながりやすい点を整理します。
前提環境とextrasの選び方
README は前提として、Python 3.12 以上、Docker(Memgraph 用)、cmake、ripgrep を挙げています。インストールコマンドは次のとおりです。
# with uv (recommended)
uv tool install "code-graph-rag[treesitter-full,semantic]"
# or with pipx
pipx install "code-graph-rag[treesitter-full,semantic]"
角括弧の中が extras で、treesitter-full が全言語対応、semantic がベクトル検索に対応します。加えて ast-grep 階層の言語を扱うには ast-grep、C/C++ のハイブリッドモードには cpp の extra が必要です。何を有効にするかによって使える機能が変わるため、評価を始める前に目的と extras を対応づけておくのが安全です。
ホイールは純粋な Python パッケージ(py3-none-any)であるため Python 3.12 以上の環境なら入りますが、依存側がプラットフォーム固有のホイールやビルドツール(pymgclient のための cmake など)を必要とする点は README にも注記されています。Docker を常駐させられない環境では、そもそも Memgraph を動かせないという前提条件にも留意が必要です。
バージョンラインの読み方
見落とされやすいのが、バージョンラインが 3 系統に分かれている点です。README は次の表で整理しています。
where | what it tracks |
|---|---|
git tags | every version, one per merge |
GitHub Releases (binaries, signatures) | every 50th version, plus any security fix |
PyPI | every 50th version, plus any security fix |
git のタグはマージごとに 1 つ付き、GitHub Releases と PyPI は 50 バージョンごと、加えてセキュリティ修正があればそのタイミングで公開されます。したがって main の最新タグは最新リリースより数十パッチ分先行しているのが通常の状態であり、README も「何かが詰まっているのではなく、意図的にケイデンスが異なる」と説明しています。
実務上の含意は 2 つあります。第一に、uv tool install や pipx install で入るのは最新の PyPI バージョン、つまり最新リリースであって最新タグではありません。リリースより新しいコードを使いたい場合は、README が示すとおり git から直接インストールします。第二に、セキュリティ修正はこのケイデンスを待たず即座にリリースと PyPI へのアップロードが行われます。「PyPI 版のバージョン番号がタグより古い」ことをメンテナンス停滞の兆候と読み違えないよう、この設計を知っておく価値があります。
共有グラフと破壊的操作の範囲
もう一つ、事故につながりやすい仕様があります。グラフは複数プロジェクトで共有されるという点です。
Quick Start は「グラフはプロジェクト間で共有されており、1 つを同期しても他のプロジェクトはそのまま残る」と説明しています。ここまでは直感どおりです。問題は --clean の挙動で、ドキュメントは「--clean は --repo-path で指定されたものだけでなく、共有グラフ内のすべてのプロジェクトを削除する」と明記しています。他のプロジェクトが失われる場合には確認を求めるプロンプトが出ますが、スクリプトや CI で自動化する際に --yes を渡すとこのプロンプトはスキップされます。
CI に組み込む場合、--clean --yes の組み合わせは共有グラフ全体を無警告で消し飛ばす操作になります。複数リポジトリを同一グラフにインデックスしている環境では、この一行が他チームの作業を巻き込む可能性があります。
ライセンスは MIT で、自社プロダクトへの組み込みや改変の自由度は高い部類です。加えて公式サイトでは、クラウドホスト型・オンプレミス/エアギャップ型のマネージド提供、カスタム開発、統合コンサルティング、サポート契約、チーム研修が案内されています(出典: Code-Graph-RAG Enterprise)。ソースコードを外部に出せない規制業種やデータ主権の要件がある場合、OSS 版の自前運用とマネージド提供のどちらを取るかを比較検討する余地があります。
類似OSSとの違い:serena・potpie・GraphRAGとの比較
「コードベースを AI に理解させる」という目的の OSS は複数あり、それぞれ解いている問題が微妙に違います。優劣ではなく「どの問いを解きたいときにどれを選ぶか」の軸で整理します。以下のスター数・ライセンスはいずれも 2026 年 8 月 26 日時点の値です。
リポジトリ | スター | ライセンス | 位置づけ |
|---|---|---|---|
vitali87/code-graph-rag | 4,819 | MIT | AST から決定的にコード構造のグラフを構築し Memgraph に永続化。Cypher・MCP・編集 |
28,492 | MIT | LSP ベースのセマンティック検索・編集を提供する MCP ツールキット | |
5,698 | Apache-2.0 | コードベースのコンテキストグラフ + 用途別エージェント群のプラットフォーム | |
35,678 | MIT | 文書向けの汎用 GraphRAG。LLM でエンティティを抽出してグラフ化 |
serena との違いは、解析結果の持ち方です。 serena は言語サーバ(LSP)に都度問い合わせてシンボルの定義・参照を解決します。インデックスを永続化しないぶん導入は軽く、単一リポジトリの局所的な参照解決と編集であれば十分に速いアプローチです。対して Code-Graph-RAG は解析結果を Memgraph 上のグラフとして保持するため、「エントリポイントから到達しない関数の列挙」「source から sink への到達可能性判定」のような、リポジトリ全体を横断する集合的な問いを Cypher 1 本で解けます。その代わり Docker と extras のセットアップという初期コストを払うことになります。局所的な編集支援が主目的なら serena、横断的な問いを繰り返し解きたいなら Code-Graph-RAG、という住み分けです。
potpie との違いは、プロダクトの重心です。 potpie もコードベースのコンテキストグラフを構築しますが、主眼は QA・デバッグ・統合テスト設計といった用途別エージェントを提供するプラットフォーム側にあります。既製のエージェントをそのまま使いたい場合はこちらが近道です。一方 Code-Graph-RAG はグラフスキーマ自体を公開ドキュメント化し、Cypher で直接叩ける形にしています。グラフの上に自前のツールやチェックを載せていきたい場合は、スキーマが公開されていること自体が価値になります。
graphrag との違いは、対象と抽出方法です。 microsoft/graphrag は自然言語文書を対象に、LLM でエンティティと関係を抽出してグラフを構築します。抽出が確率的であるぶん、仕様書や議事録のような散文に対して強みを発揮します。Code-Graph-RAG は Tree-sitter の AST から決定的にグラフを導出するため、関数・クラス・import・継承といった関係に LLM の推論が介在しません。ソースコードを対象にするなら後者、文書を対象にするなら前者、という選び分けになります。同じ「GraphRAG」という語で括られていても、前提がまったく異なる点は押さえておく価値があります。
code-graph-ragが向くケース・向かないケース
ここまでの内容を、採用判断のチェックリストとして整理します。
向いているケース
- 複数言語が混在するモノレポを扱っており、その大半がフル対応 13 言語に含まれる
- 「どこから呼ばれているか」「到達不能なコードはどれか」といった、リポジトリ全体を横断する集合的な問いを繰り返し解く必要がある
- グラフの上に自前のクエリやチェックを載せていきたい(スキーマが公開されていることを活かせる)
- Claude Code などの MCP クライアントを既に運用しており、そこにコード構造の問い合わせ手段を足したい
- Docker を常駐させられる開発環境があり、インデックス構築のコストを許容できる
向いていないケース
- 対象コードの大半が構造対応階層の言語(Ruby / Kotlin / Swift / Elixir / Haskell / Solidity / Bash / Nix)で、かつコールグラフ解析が目的である
- Docker や Memgraph を常駐させられない、あるいは運用を引き受けられる担当がいない
- 単一リポジトリの局所的な編集支援だけが目的で、横断的な問いを持っていない
- デッドコード検出の結果を、レビューを挟まずそのまま削除リストとして使いたい
- データフロー解析を厳密なセキュリティ監査の代替として使いたい(保守的な実装であることが公式に明示されている)
判断に迷う場合は、「自分たちが繰り返し困っている調査は何か」を先に 1 つ書き出し、それがグラフスキーマ上のどのノードとリレーションで表現できるかを確認するのが早道です。表現できるなら導入コストを払う価値があり、表現できないなら別の道具を探すべき、というシンプルな線引きになります。
まとめ
Code-Graph-RAG の設計を一言でまとめると、「構造は決定的に抽出し、重くなる部分は opt-in で広げる」という方針に集約されます。Tree-sitter の AST から導出される関数・クラス・呼び出しの関係に LLM の推論は介在せず、LLM の役割は自然言語から Cypher への変換と回答生成に限定されます。I/O やデータフロー、ast-grep による検出は capture group として明示的に有効化する仕組みになっており、必要な情報だけをグラフに載せられます。
同時に、公式ドキュメントは制約も正直に書いています。構造対応階層の 8 言語には CALLS の解決がないこと、デッドコード検出の結果はレビュー候補であって削除確定リストではないこと、flow_verdict の NO_FLOW をカバレッジ欠損のある状態で「検証済みの不在」と読んではならないこと、--clean が共有グラフの全プロジェクトを消すこと。採用判断に必要な情報は、ほぼすべて公開されています。
より詳しく確認する場合は、アーキテクチャ概要で全体構成を掴み、グラフスキーマで自分のユースケースが表現できるかを確かめ、言語サポートで対象リポジトリの構成言語がどの階層に入るかを確認する、という順序が効率的です。この 3 つを読めば、導入すべきかどうかの見当はつくはずです。
関連情報
既存コードベースの構造把握や、レガシーシステムの調査・改修をご検討中の方は、お問い合わせフォームからご相談ください。要件が固まっていない段階からのご相談にも対応しています。
よくある質問
- Rubyなど構造対応(ast-grep)階層の言語が中心のリポジトリでも、デッドコード検出に使えますか?
使えません。構造対応階層(Ruby / Kotlin / Swift / Elixir / Haskell / Solidity / Bash / Nix)は
CALLSエッジを持たず、これらの言語のシンボルは常に到達可能として扱われるため、デッドコード検出の判定対象から外れます。呼び出し解析が必要な場合はフル対応13言語向けの機能です。- cgr dead-codeが「未使用」と報告した関数は、そのまま削除してよいですか?
そのままの削除は避けてください。公式ドキュメントも明記する通り結果は削除候補の一覧にすぎず、動的ディスパッチやリフレクション経由でのみ呼ばれるコードも報告されうるため、削除前に個別レビューを挟む必要があります。
- I/Oやデータフロー(READS_FROM / WRITES_TO / FLOWS_TO)は、導入するだけで自動的に解析されますか?
されません。これらは
ioというcapture groupのopt-in機能で、既定構成では一切生成されません。環境変数の伝播経路などデータフロー追跡が目的の場合は、導入前にioを明示的に有効化しておく必要があります。- --cleanオプションを実行すると、どの範囲のデータが削除されますか?
指定したリポジトリだけでなく、共有グラフに登録された他の全プロジェクトも削除されます。複数リポジトリを同一グラフで運用している環境でCIに
--clean --yesを組み込むと、他チームの資産まで無警告で消える恐れがあるため注意が必要です。- Claude CodeからCode-Graph-RAGを使うには、何を用意すればよいですか?
MCPサーバーとして
claude mcp addでCLIを登録し、対象リポジトリの絶対パスとCypher生成用モデルのプロバイダ・モデル名・APIキーを環境変数で渡すだけです。登録後はquery_code_graphなどのツールをClaude Codeから直接呼び出せます。- すでにserenaを使っている場合、Code-Graph-RAGへの乗り換えは必要ですか?
目的次第です。単一リポジトリ内の局所的な参照解決・編集が中心ならserenaのままで十分です。「到達不能な関数の列挙」のようにリポジトリ全体を横断する問いを繰り返し解きたい場合に、グラフを永続化するCode-Graph-RAGの価値が出ます。



