程式碼圖
程式碼圖是一個 SQLite 資料庫 — .code-graph/graph.db — 記錄你儲存庫的結構關係。定義、呼叫、import、繼承、檔案對檔案的邊。AI 代理透過 MCP 工具查它,而不是為每個問題重新 grep。
圖裡有什麼
兩張表,就是 sqlite3 .code-graph/graph.db ".schema" 印出來的樣子:
CREATE TABLE nodes (
id TEXT PRIMARY KEY, -- content hash, not an autoincrement integer
kind TEXT NOT NULL, -- file | function | method | class | interface | enum | table
name TEXT NOT NULL,
file TEXT NOT NULL, -- repo-relative path
start_line INTEGER,
end_line INTEGER
);
CREATE INDEX idx_node_file ON nodes(file);
CREATE TABLE edges (
src TEXT NOT NULL, -- always a nodes.id
dst TEXT NOT NULL, -- a nodes.id, or a raw name (see below)
kind TEXT NOT NULL -- imports | contains | calls | inherits
-- | implements | depends_on | tests_for
);
CREATE UNIQUE INDEX uq_edges ON edges(src, dst, kind);
CREATE INDEX idx_edge_dst ON edges(dst);
沒有 language 欄位 — 語言在解析時從副檔名推斷,不存進資料庫。
dst 不一定是節點 id。 contains、tests_for 和 depends_on 能解析到 nodes 裡的一列。imports 和 inherits 存的是解析器看到的原始文字 — '../api/metricsClient'、'argparse'、一個基別名稱 — 因為把模組路徑解析成檔案需要解析器不跑的一套規則。前一組用 join,後一組用比對。下面的例子兩種各一個。
這些都能直接用 sqlite3 查。MCP 伺服器是同一個檔案之上帶型別的便利層。
語言
tree-sitter 解析器涵蓋:Python、TypeScript、JavaScript、Go、Rust、Java、C#、Ruby 等。沒有 tree-sitter 套件的語言會自動回退到 regex 解析器 — 覆蓋率較差,但建置不會失敗。
完整清單見 .github/code-graph/requirements.txt。
MCP 工具
MCP 伺服器把以下查詢開放給代理:
| 工具 | 用途 |
|---|---|
get_minimal_context(task) | 預設首呼。 把任務裡提到的符號解析到圖上,回傳 files_to_read:定義所在的檔案、它們依賴的檔案,再加一層依賴它們的檔案,排序後最多 6 個。同時還有圖的規模、未提交變更的風險,以及下一個該用的工具。控制在 ~150 token 以內,所以不帶逐檔案的 token 統計 — 需要就把 files_to_read 交給 get_review_context。空清單一定帶著 files_reason。 |
query_graph(pattern, node_name) | 具名模式:callers_of、callees_of、imports_of、importers_of、tests_for、file_summary。 |
get_impact_radius(files) | 傳入的是一組儲存庫相對路徑,不是符號。回傳從它們可達的檔案。 |
get_review_context(files, budget_tokens?) | 審查用:這些檔案加上直接鄰居,排序後依 token 預算裁剪。 |
find_large_functions(min_lines=50) | 超過 N 行的函式 — 找技術債。 |
detect_changes(base="HEAD") | 自指定 ref 以來 SHA-1 變動的檔案。 |
update_graph() | 對變動檔案做增量重新解析。 |
build_graph() | 從頭完整重建。 |
graph_stats() | 節點與邊數、上次更新時間、各語言檔案數。 |
visualize_graph() | 在 .code-graph/graph.html 渲染互動式 HTML 圖。 |
視覺化
uv run --with-requirements .github/code-graph/requirements.txt \
.github/code-graph/server.py --visualize
輸出 .code-graph/graph.html — 一個獨立的 D3 力導向視圖(不用啟伺服器)。任何瀏覽器開得起來。拖動節點、滑過看符號細節、依語言或種類過濾。用來檢查剛建好的圖、找孤立模組、給隊友看代理實際看到的東西。

為什麼用 SQLite
- 查詢零相依。 任何裝了
sqlite3的人不用啟 MCP 伺服器就能戳圖。 - 便宜。 五萬行程式碼庫的圖通常只有幾 MB。
- 跨機器穩定。 隊友從同一個 commit 重建,會拿到同一個資料庫 — 測試夾具等級的可重現性。
直接寫 SQL
如果 MCP 不可用,資料庫就是一個檔案:
# 一個檔案裡的所有定義,依原始碼順序
sqlite3 -header -column .code-graph/graph.db "
SELECT child.kind, child.name, child.start_line
FROM edges e
JOIN nodes parent ON parent.id = e.src
JOIN nodes child ON child.id = e.dst
WHERE parent.file = 'src/i18n/t.ts' AND e.kind = 'contains'
ORDER BY child.start_line;
"
kind name start_line
-------- ---------------------- ----------
function localizedPath 43
function detectLocaleFromHeader 49
因為 imports 的目標是原始字串,查「誰 import 了某模組」要用比對而不是 join:
sqlite3 -header -column .code-graph/graph.db "
SELECT DISTINCT n.file
FROM edges e
JOIN nodes n ON n.id = e.src
WHERE e.kind = 'imports' AND e.dst LIKE '%metricsClient'
ORDER BY n.file;
"
這是 MCP 伺服器沒註冊時的官方備援。Coograph 專案裡的代理知道先試 MCP,再退到 sqlite3,兩者都失敗才退到 grep。
自動更新
.github/code-graph/ 裡的 git 鉤子(post-commit、post-merge、post-rewrite)每次變動後呼叫 --update。只有內容 SHA-1 變動的檔案會重新解析。從變動檔案 import 的檔案也會重新解析,跨檔案的邊才會準。
限制
- 圖捕捉的是結構性關係,不是語意關係。它知道
place_order呼叫validate;但不知道加快取會影響下游計費。 - 覆蓋率取決於你語言的 tree-sitter 是否可用。回退的 regex 解析器找符號夠用,但會漏掉一些邊(例如動態派送)。
- 圖以檔案為粒度重建。如果你提交了上千個檔案的重構,增量更新就是 O(thousand-file)。