程式碼圖
程式碼圖是一個 SQLite 資料庫 — .code-graph/graph.db — 記錄你儲存庫的結構關係。定義、呼叫、import、檔案對檔案的邊、語言中繼資料。AI 代理透過 MCP 工具查它,而不是為每個問題重新 grep。
圖裡有什麼
兩張表,純 SQL:
CREATE TABLE nodes (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
kind TEXT NOT NULL, -- 'function', 'class', 'method', 'file', 'module'
file_path TEXT NOT NULL,
line INTEGER,
language TEXT
);
CREATE TABLE edges (
src_id INTEGER NOT NULL REFERENCES nodes(id),
dst_id INTEGER NOT NULL REFERENCES nodes(id),
kind TEXT NOT NULL, -- 'calls', 'imports', 'defines', 'inherits'
PRIMARY KEY (src_id, dst_id, kind)
);
想直接用 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) | 針對任務描述回傳 4–6 個相關檔案。任何 read_file 之前的預設首呼。 |
query_graph(kind, target) | 通用圖查詢:callers_of、callees_of、imports_of 等。 |
get_impact_radius(symbol) | 變動某定義會影響到的檔案。 |
get_review_context(diff) | 審查用:diff 牽涉的檔案加上直接鄰居。 |
find_large_functions(threshold) | 超過 N 行的函式 — 找技術債。 |
detect_changes() | 自上次更新後 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 .code-graph/graph.db "
SELECT n2.file_path, n2.line, n2.name
FROM edges e
JOIN nodes n1 ON e.src_id = n1.id
JOIN nodes n2 ON e.dst_id = n2.id
WHERE n1.name = 'OrderService' AND e.kind = 'calls'
"
這是 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)。