乐于分享
好东西不私藏

CodeGraph:为 AI 编程助手注入语义代码智能

CodeGraph:为 AI 编程助手注入语义代码智能

CodeGraph 是什么?

一句话:CodeGraph 是一个本地运行的代码知识图谱工具——它把你整个代码库解析成符号关系图存在本地 SQLite 里,再通过 MCP 协议让 Claude Code 这类 AI 编程助手"像查 IDE 一样"秒速理解项目。

为了让定义不抽象,先把"是什么"和"不是什么"拆开讲:

维度它是它不是
形态一个 npm 包 @colbymchenry/codegraphSaaS、云服务、IDE 插件
运行位置你的本地电脑,作为后台 stdio 子进程远程服务器
数据存储项目下的 .codegraph/codegraph.db(SQLite)上传到云端
使用者Claude Code 等支持 MCP 的 AI 客户端给人类直接看的可视化工具
核心能力提供 8 个语义化查询工具:搜符号、查调用、看影响、构建上下文……AI 模型,本身不生成代码
依赖只要 Node 18–24,零网络、零 API keyOpenAI 或任何外部 API

类比一下:IDE 的「跳转定义、查找引用」是给人用的;CodeGraph 把同样的静态索引能力以 AI 友好的接口暴露给 LLM。你装好它之后基本不会再手动打开它——Claude Code 会自动在后台调用,你只会感觉到「Claude 突然对这个项目熟悉多了」。

官方实测效果(6 个真实代码库 benchmark):

  • 工具调用次数 减少 92%
  • 探索速度 提升 71%
  • 0 次文件 Read——Claude 完全信任 CodeGraph 返回的结果

下面这篇文章会按以下顺序展开:从「为什么需要它」起步,依次讲清楚它的架构、工作原理、安装方式,以及它与 Claude Code 的具体交互方式。


为什么需要 CodeGraph

当 Claude Code(或任何 LLM 编程助手)面对一个陌生代码库被要求"实现用户认证"或"修复登录 bug"时,它的标准动作是派出 Explore agent,用 grepglobfindRead 在文件系统里盲扫——一遍遍读文件、找符号、追调用、回退、再扫。每一次工具调用都消耗 token、消耗时间,而其中绝大部分操作不过是在重建一个 IDE 早已具备的"项目索引"。

CodeGraph 的核心洞察非常朴素:

既然 IDE 通过静态索引就能秒级跳转定义、查找引用、构建调用图,那 AI 助手也应该有同样的预计算索引,而不是把每次提问都当作冷启动。

它做的事情可以用一句话概括——用 tree-sitter 把整个代码库解析为符号-边构成的知识图谱,存入本地 SQLite,再通过 MCP 协议把这个图谱的查询能力以一组结构化工具暴露给 AI。结果是:

指标没有 CodeGraph有 CodeGraph提升
VS Code (TypeScript, 4002 文件)52 次工具调用,1m 37s3 次调用,17s94% / 82%
Swift Compiler (Swift+C++, 25874 文件)37 次调用,2m 8s6 次调用,35s84% / 73%
Excalidraw47 次调用,1m 45s3 次调用,29s94% / 72%

这不是"AI 加速器"那种营销话术,而是把已经在 IDE 里被实践了几十年的静态索引技术,重新打包成 LLM 时代的一等公民


系统架构

CodeGraph 的设计哲学有四条贯穿始终的红线:

  1. Local-first:数据永远不离开机器,没有 API key、没有外部服务,只有项目根目录下的 .codegraph/ 文件夹。
  2. Headless library:CodeGraph 本身没有 UI,纯粹是一个 Node.js 库 + CLI + MCP server 的组合,可独立运行、可被嵌入 Electron、可作为 npm 依赖被任何工具调用。
  3. Deterministic extraction:所有抽取出来的节点和边都来自 tree-sitter AST 的确定性遍历,不依赖 LLM 生成摘要,因此结果稳定、可重现、可审计。
  4. Per-project isolation:每个项目一份独立的 SQLite 数据库和配置,互不干扰,可单独删除。

整体分层如下:

核心工作流

CodeGraph 的所有功能都建立在一条贯穿的核心管线上。理解了这条管线,就理解了 CodeGraph 的全部。

#文件扫描:git 优先,文件系统兜底

优先调用 git ls-files -c --recurse-submodules 拿到项目可见文件列表。这一步带来三个隐藏好处:

  • 自动遵守 .gitignore:所有层级的 .gitignore 规则被 git 原生兼容,不需要 CodeGraph 自己再实现一遍。
  • 子模块支持--recurse-submodules 解决了 monorepo 用子模块时主仓库索引只有 commit pointer、抽到 0 文件的著名问题(issue #147)。
  • untracked 文件也被纳入:未被 git 追踪、但又不在 .gitignore 里的新文件也会被 git ls-files -o --exclude-standard 抓到。

当项目不是 git 仓库时,scanDirectoryWalk() 会回退到递归 readdirSync,期间通过 realpath 检测符号链接循环、识别 .codegraphignore 标记文件、并按 config.exclude 的 glob 模式裁剪目录。

#多语言抽取:tree-sitter + WASM + worker 线程

CodeGraph 把所有 19+ 种语言的 grammar 编译成 WASM 后嵌入分发包。这带来两个工程性收益:

  • 零 native 编译依赖:用户安装时不需要 C 工具链。
  • 跨平台一致:Windows / macOS / Linux 跑同一份 WASM,行为可重现。

但 WASM 也带来一个棘手问题:WebAssembly 的线性内存只能涨不能降——tree-sitter 一旦在某个大文件上吃掉 200MB,剩余的解析任务也吃不回去。CodeGraph 的解法是把解析跑在独立 worker 线程里,每 250 个文件就把整个 worker 销毁重建一次,让 V8 isolate 连同 WASM 堆一起被 GC。

对于解析卡死的文件(典型场景:Swift 编译器测试集里 90% 是 CHECK 注释的怪异源文件),会触发三层降级

  1. 超时(默认 10s)→ 重启 worker 重试
  2. 重启后仍失败 → 用全新 worker 再试一次
  3. 还失败 → 把注释行替换为空行后再试(保持行号不变以维持节点位置正确)

这种"清理-重试-降级"循环让 CodeGraph 在 25,874 文件的 Swift 编译器源码上仍能跑完。

#节点与边:22 种 NodeKind × 12 种 EdgeKind

抽取阶段把每个源文件解析为两类对象写进 SQLite:

  • 节点(NodeKind):22 种,覆盖你能想到的所有代码符号——文件、类、接口、结构体、函数、方法、属性、字段、变量、常量、枚举、类型别名、命名空间、导入、导出、路由、组件……
  • 边(EdgeKind):12 种,描述符号之间的关系——contains(包含)、calls(调用)、imports(导入)、extends(继承)、implements(实现)、references(引用)、type_of(类型)、returns(返回)、instantiates(实例化)、overrides(覆盖)、decorates(装饰)。

每个节点都带有完整的位置(起止行/列)、签名、文档字符串、可见性、修饰符(async/static/abstract)、装饰器和泛型参数。节点的 id 是「文件路径 + 限定名」的哈希,保证跨索引会话稳定可比。

#引用解析:三层策略

抽取阶段会留下一批"暂时无法解析"的引用——比如 foo() 是哪个 fooimport { Bar } 中的 Bar 来自哪个文件?这些被批量写入 unresolved_refs 表,全索引完成后由 ReferenceResolver 统一处理。解析策略按优先级有三层:

  1. 框架识别src/resolution/frameworks/):自动识别 13 个框架——React、Express、Django、FastAPI、Laravel、Rails、Spring、Go (Gin/chi/gorilla/mux)、Axum/actix/Rocket、ASP.NET、Vapor、SvelteKit、Vue/Nuxt。识别后会注入对应的 route 节点和 references 边,把 URL 模式直接连到 handler。
  2. 导入解析import-resolver.ts):基于已经入库的 import 节点和 re-export 链,按文件路径推导符号定义位置。支持 tsconfig/jsconfig 的 paths 别名。
  3. 名字匹配name-matcher.ts):当前两种都失败时回退到限定名/全局名匹配,配合内置的 stdlib 黑名单(JS built-ins、Python built-ins、Go stdlib 等)排除噪音。

解析时大量使用了缓存(nodeCachefileCacheimportMappingCachereExportCache),并支持分批解析以避免大代码库 OOM——典型场景下解析十几万条 unresolved refs 的内存峰值能控制在 1GB 以内。

#增量同步:git status 快路径

文件改动后不需要重建整个索引。sync() 优先调用 git status --porcelain --no-renames,只拿到 modified / added / deleted 三个名单,然后:

  • deleted:直接从 DB 删(ON DELETE CASCADE 级联清理 edges 和 unresolved_refs)。
  • modified:算 SHA-256 哈希对比 files.content_hash,没变就跳过,变了就重新抽取。
  • added:直接抽取入库。

由于解析范围被收窄到"git 实际改动的那几个文件",typical 单文件保存触发的增量同步通常在 50ms 内完成。无 git 仓库时回退到全量扫描,性能会差一些但功能正常。

#文件监听:原生 OS 事件 + 2 秒防抖

FileWatcher 用 fs.watch({ recursive: true })——背后是 macOS FSEvents、Windows ReadDirectoryChangesW、Linux inotify(Node 19+)。事件经过两层过滤:

  1. 忽略 .codegraph/ 内部写操作(避免自反馈循环)。
  2. shouldIncludeFile() 按 include/exclude 模式过滤。

之后用 2 秒滑动防抖窗口聚合多次保存,最后调用 sync()。这意味着你在编辑器里疯狂保存 10 次,CodeGraph 也只会在最后一次保存后 2 秒触发一次同步。

#上下文构建:5 步混合搜索

ContextBuilder.findRelevantContext() 是整个系统最精巧的部分。给定一个自然语言查询(例如 "how does collaborative editing work"),它会按如下顺序构建一个最相关子图:

  1. 符号抽取:用 6 种正则模式(CamelCase / snake_case / SCREAMING_SNAKE / ALL_CAPS / dot.notation / 普通小写词)从 query 中识别可能的代码符号,并用一份精心整理的"英文常用词黑名单"过滤掉 the/and/flow/level 这类噪声。
  2. 精确匹配:对抽取出的符号在 nodes.name 上做精确查询,命中后给"同一文件下多个符号同时命中"额外加分(co-location boost),因为这通常意味着用户找的就是那个文件。
  3. 前缀 / 词干匹配:把符号 title-case 后查找以它开头的类/接口名(比如 query 写了 "REST" 会匹到 RestController),并通过 getStemVariants 把 "caching" → "cache" 拓展。
  4. FTS5 全文搜索:对查询词单独走 FTS5 索引,对命中多个查询词的节点给"multi-term hit"加分。
  5. CamelCase 边界与复合匹配:用 LIKE 查询找出名字内部包含查询词的类(如 TransportSearchAction 内部的 Search),按多词共现做指数级加分。

得到搜索结果后再做三件事:

  • 测试文件降权(除非 query 本身是 "test/spec")
  • per-file diversity cap:任何一个文件最多占 20% 节点预算
  • import/export 解引用:搜到 import { TerminalPanel } 会自动追到 TerminalPanel 类定义本身

最后从这些 entry points 出发做 traverseBFS,遍历优先 contains > calls > 其它边,并自动展开类型层级(找父类、子类、兄弟类),构建出一个最多 maxNodes 节点的最小相关子图。buildContext() 在此基础上抽取 code blocks 并按 Markdown 或 JSON 格式输出。


关键功能

#8 个 MCP 工具——给 LLM 的"代码 API"

工具作用
codegraph_search按名字快速查符号(只返回位置)
codegraph_context主力工具:给一个任务描述,返回完整上下文
codegraph_callers谁调用了 X
codegraph_calleesX 调用了谁
codegraph_impact改 X 会影响哪些代码
codegraph_node单个符号详情(可选包含源码)
codegraph_explore深度探索:一次返回多文件源码 + 关系图
codegraph_status索引健康度与统计
codegraph_files项目文件树(比 Glob 快)

codegraph_explore 尤其值得注意:它会根据项目大小自动调整探索预算——500 文件以下只用 1 次调用,2 万 5 千文件以上最多 5 次。tool description 里还直接教 LLM 怎么写好 query:「Bad: 'how are agent prompts loaded' / Good: 'readAgentsFromDirectory createClaudeSession agents.ts'」——这个 prompt engineering 细节正是 benchmark 数据漂亮的关键。

#框架感知的路由识别

CodeGraph 不只是抽 AST,它能识别 web 框架的路由约定,并把 URL 模式作为一等公民的 route 节点纳入图谱:

框架识别形式
Djangopath()re_path()url(),CBV .as_view(),dotted path
Flask / FastAPI@app.route() / @router.get()
Expressapp.get()router.post() 含中间件链
LaravelRoute::get()Route::resource()Controller@action
Railsget '/x', to: 'users#index'
Spring@GetMapping@RequestMapping
Go (gin/chi/mux)r.GET()router.HandleFunc()
Rust (axum/actix/Rocket).route("/x", get(handler))
ASP.NET[HttpGet("/x")]
Vaporapp.get("x", use: handler)
SvelteKit / Vue/Nuxt基于文件名约定的页面/API 路由

这让你问 LLM "这个 URL 哪个 controller 处理" 时,它能一步走到正确文件。

#codegraph affected —— 给 CI 用的 test impact analysis

git diff --name-only | codegraph affected --stdin --quiet

这条命令传递性追踪 import 依赖,从改动文件出发反向找出受影响的测试文件。配 CI hook 用就是一个本地版的 [Nx affected]:

#!/usr/bin/env bashAFFECTED=$(git diff --name-only HEAD | codegraph affected --stdin --quiet)if [ -n "$AFFECTED" ]; then  npx vitest run $AFFECTEDfi

#双 SQLite 后端 + 性能可观测性

CodeGraph 把 better-sqlite3(native)声明为 optionalDependencies,并自带 node-sqlite3-wasm 作为回退后端。当 native 模块装不上(缺 C 工具链、Node 升级后 ABI 不匹配)时自动切到 WASM——但 WASM 慢 5-10 倍且使用让 writer 阻塞 reader 的 journal mode。CodeGraph 在 codegraph status 命令里直接告诉你当前用的是哪一个,并附上修复 recipe:

Backend: wasm     ← 慢路径xcode-select --install         # macOSsudo apt install build-essential python3 make  # Linuxnpm rebuild better-sqlite3

这种"不假装正常、显式暴露降级状态"的工程纪律在开发者工具里很罕见、也很好用。

#文件锁 + 进程内互斥

CodeGraph 实例同时持有两把锁:

  • indexMutex:进程内 mutex,防止同一个 CodeGraph 实例并发索引。
  • fileLock.codegraph/codegraph.lock 文件锁,防止 CLI、MCP server、git hook 三个进程同时写 DB。

这是为什么你可以在 MCP server 正在自动 sync 时手动运行 codegraph index 而不损坏数据库——它会显式失败并报告"另一个进程正在索引"。


安装与使用

CodeGraph 的安装策略分两层:机器级别一次性配置项目级别按需初始化

#一键交互安装

npx @colbymchenry/codegraph

交互式 installer(基于 @clack/prompts)会引导你完成:

  1. 全局安装
    @colbymchenry/codegraph(MCP server 需要全局命令)。
  2. 配置 MCP server:写入 ~/.claude.json 或当前项目的 .claude.json
  3. 设置自动允许权限:把 mcp__codegraph__* 系列工具加入 ~/.claude/settings.json 的 allow 列表,免去每次工具调用都弹权限确认。
  4. 写入全局 CLAUDE.md 指令:告诉 Claude Code 在 .codegraph/ 存在时优先用 MCP 工具,不存在时主动询问用户是否初始化。
  5. 可选:立即在当前目录运行 codegraph init

#手动安装(适合 CI/不喜欢交互的场景)

npm install -g @colbymchenry/codegraph

~/.claude.json 加上:

{"mcpServers":{"codegraph":{"type":"stdio","command":"codegraph","args":["serve","--mcp"]}}}

如果不想每次工具调用都弹权限确认,在 ~/.claude/settings.json 的 permissions.allow 数组里加入所有 mcp__codegraph__* 工具即可(或直接用交互式 installer 自动处理)。

#项目初始化

cd your-projectcodegraph init -i      # -i 表示初始化后立即跑一次全量索引

初始化会创建:

your-project/└── .codegraph/    ├── config.json       # 配置(include/exclude/maxFileSize ...)    ├── codegraph.db      # 主数据库(SQLite)    └── codegraph.lock    # 跨进程文件锁

之后只要在 Claude Code 里打开这个项目,MCP server 会自动检测到 .codegraph/ 并加载,无需重启。


Coding Agent 如何使用 CodeGraph 获取项目代码信息

一个关键的问题:Claude Code(或任何 coding agent)实际在跑任务时,是怎么通过 CodeGraph 把代码信息"喂"进自己的推理链路的? 这一节把整个交互链路拆开看。

#通信链路:MCP 子进程 + stdio JSON-RPC

整个交互发生在 AI 客户端和 CodeGraph 的一个本地 stdio 子进程之间,没有任何网络流量

Claude Code 主进程  ←——— JSON-RPC over stdio ———→  codegraph MCP 子进程                                                          │                                                          ▼                                                .codegraph/codegraph.db

启动时 MCP 服务端会像 git 找 .git 一样向上查找最近的 .codegraph/ 目录,找到就打开并启动文件监听。几个让体验顺滑的细节:

  • 延迟初始化:服务端先开始监听消息再尝试打开数据库。如果项目还没 init,也不会退出——每次工具调用都会重试一次。你在 IDE 里现场跑 codegraph init 之后不需要重启 MCP server
  • 自动监听:启动时就开启了 2 秒防抖的文件监听;每次同步完成把日志写到 stderr,不污染 JSON-RPC 通道。
  • 跨项目缓存:当 AI 工具调用里传 projectPath 指向另一个仓库,首次打开后会缓存连接,后续查询直接命中。
  • 优雅退出:监听 stdin 关闭,父进程关闭时自动清理资源,不留孤儿进程。

#工具语义:8 个工具按意图分工

服务端在 initialize 响应里返回一段 instructions 字段,MCP 客户端会自动把它注入 agent 的 system prompt,所以 AI 一上来就知道每个工具该用在什么场景:

AI 的意图调用的工具返回的数据
"X 这个符号是什么?"codegraph_search名字、kind、文件位置、签名(不含源码
"帮我理解这个任务/功能/区域"codegraph_context ★ 主力入口符号 + 关键源码片段 + 关系总结
"谁调用了 X?"codegraph_callers入边 calls 列表
"X 又调用了谁?"codegraph_callees出边 calls 列表
"改 X 会破坏什么?"codegraph_impact影响半径子图(默认 depth=2)
"看 X 的源码/签名/docstring"codegraph_node单符号详情(includeCode 默认 false)
"调研一个我陌生的模块/模式"codegraph_explore ★ 深挖多文件源码块 + 关系图(一次性给够)
"X 目录里都有什么?"codegraph_files文件树(比 Glob 快)
"索引健康吗?"codegraph_status统计 + backend(native/wasm) + lastUpdated

每个工具调用的入口是 MCPServer.handleToolsCall → ToolHandler.execute(toolName, args),按工具名分发到对应的 CodeGraph 实例方法(searchNodes / getCallers / buildContext 等)。

#关键纪律:主会话 vs Explore subagent

这是 CodeGraph 让"工具调用次数从 50 降到 3"的真正秘诀,写在全局 CLAUDE.md 模板里:

主会话(context 寸土寸金)   │   ├─ 只允许用「轻量工具」:search / callers / callees / impact / node   │     ↓ 每次调用返回 < 1000 token   │     ↓ 用于"编辑前的快速体检"   │   └─ 探索类问题 → 派出 Explore subagent            │            └─ Explore agent 在隔离的 context 里                 ↓ 调用「重型工具」:context / explore                 ↓ 单次返回 10+ 文件源码 + 关系图(万级 token)                 ↓ 在 subagent 内部读完、推理完、生成总结                 ↓ 只把精炼答案(~500 token)回传主会话

为什么这么分?因为 codegraph_explore 一次返回 6000-10000 token 的源码块——如果在主会话直接调,后面所有编辑、规划、测试任务都得背着这块上下文跑,等同于把 IDE 的 minimap 永久贴在屏幕上。把它隔离在 subagent 里,主会话只接收"提炼后的结论"。

codegraph_explore 的 tool description 里还做了 prompt engineering,直接教 AI 怎么写 query

Bad: "how are agent prompts loaded and passed to the CLI"Good: "readAgentsFromDirectory createClaudeSession chat-manager agents.ts"

这把 AI 引导到"先用 codegraph_search 找几个符号名 → 再把这些名字喂给 explore"的最优路径。

错误的反模式是:

主会话 → 自己直接调 codegraph_explore       → 返回 8000 token 源码塞进主会话上下文       → 后续每一个 prompt 都背着这 8000 token 跑

#一次真实任务跑下来是什么样子

"这个项目的认证系统是怎么实现的?"

[主会话]  1. 识别为探索类问题 → spawn Explore subagent[Explore subagent]  2. 调 codegraph_search("auth")           → 拿到 AuthService、SessionManager 等符号名  3. 调 codegraph_explore(                   一次返回:       "AuthService SessionManager           ├─ auth/service.ts 相关段        loginUser signIn session.ts")        ├─ auth/middleware.ts 相关段                                             ├─ session/manager.ts 相关段                                             ├─ types/user.ts 类型定义                                             └─ 调用关系图(谁调谁、谁继承谁)  4. 直接基于返回的源码答题,不再 Read 文件  5. 回传主会话一段 300 字总结 + 关键文件清单[主会话]  6. 收到精炼总结,开始 plan/edit

3 次工具调用、0 次 Read、约 17 秒——而没有 CodeGraph 时同样问题要 50+ 次 grep/glob/Read、1m37s。

#主会话直接做轻量查询的时机

不是所有情况都要派 subagent。当 AI 写代码、即将做一次具体编辑时,会直接在主会话里调轻量工具:

[主会话写到一半]  我要给 UserService.updateProfile 增加一个参数    ↓  先调 codegraph_callers("updateProfile")          ← 看谁会被影响    ↓  再调 codegraph_impact("updateProfile", depth=2)  ← 看影响半径    ↓  确认 5 个调用点都在 src/users/ 下 → 编辑

这种"编辑前体检"只花几百 token,但能避免破坏式改动——它替代了"先 grep updateProfile 再 read 10 个文件"的老路。

#自动新鲜度:AI 不需要操心同步

整个过程中 AI 不需要管索引是否最新——Watch 在 MCP server 启动时就开启了

你保存 user.ts  → fs.watch 触发 → 2 秒防抖 → git status 找到变更文件  → 重新解析、更新数据库  → 下一轮 AI 调工具时拿到新数据

唯一的限制——MCP server instructions 里直接告诉了 AI:刚编辑完文件就立即查询可能拿到旧数据,等下一轮再查。这是因为 500ms 防抖窗口里同步还没完成。这种"把已知限制写进 AI 的 system prompt"是个非常聪明的做法——不要指望 AI 自己发现 race condition,告诉它就好了。

#总的来说

Coding agent 把 CodeGraph 当作一个"装在本地的 IDE 服务"使用——通过 MCP 协议拿到 8 个语义化工具,按"重 → subagent / 轻 → 主会话"的分工原则调用,背后由 fs.watch 自动同步保证数据始终新鲜。AI 不需要知道 SQLite、tree-sitter、FTS5 的存在;它看到的只是"问一个问题,得到一份结构化答案"。

这就是 CodeGraph 与传统 LSP / IDE 索引的本质差别:LSP 是给人用的,CodeGraph 是给 AI 用的——同样是静态索引,但接口语义、返回格式、token 预算、调用纪律全部按 LLM 的工作模式重新设计过。


深度使用

 CodeGraph 的进阶用法。

#CLI 速查表

codegraph                         # 跑交互式安装器codegraph init [path]             # 初始化(--index 立即全量索引)codegraph uninit [path]           # 移除(--force 跳过确认)codegraph index [path]            # 全量索引(--force 强制重建、--quiet 静默)codegraph sync [path]             # 增量同步(git 快路径)codegraph status [path]           # 显示统计 + backend(native|wasm)codegraph query <search>          # 按名搜符号(--kind / --limit / --json)codegraph files [path]            # 显示文件树(--format tree|flat|grouped)codegraph context <task>          # 构建任务上下文(--format / --max-nodes)codegraph affected [files...]     # 求改动影响的测试集codegraph serve --mcp             # 启动 MCP server(供 Claude Code 调用)

#用作 Node.js 库

CodeGraph 是纯 headless 库,可以直接在你自己的脚本里 import 使用,几行就能跑起来:

importCodeGraphfrom'@colbymchenry/codegraph';const cg = awaitCodeGraph.init('/path/to/project');await cg.indexAll();const ctx = await cg.buildContext('fix login bug', { format'markdown' });console.log(ctx);cg.close();

主要 API 包括 searchNodes / getCallers / getCallees / getImpactRadius / buildContext / watch,名字基本自解释。详细签名见 types.d.ts[1]

#高级配置

.codegraph/config.json 控制索引行为,常用字段就是 include / exclude(glob 列表)、languages(语言白名单,留空自动检测)、maxFileSize(默认 1MB)。三条实战建议:

  • 巨型仓库maxFileSize 别放大,否则 WASM 堆会爆。
  • monorepo:用 .codegraphignore 文件(在子目录里放一个空文件即可)排除单个目录,比改 config 更轻量。
  • 多语言混合:让 languages 留空自动检测,比手写白名单稳。

#CI 集成:只跑受影响的测试

CodeGraph 最被低估的特性之一是 codegraph affected。把它装进 pre-push 钩子或 GitHub Actions:

# .github/workflows/test.yml-name:Findaffectedtestsid:affectedrun:|    AFFECTED=$(git diff --name-only origin/main...HEAD \      | codegraph affected --stdin --quiet --depth 5)    echo "tests=$AFFECTED" >> $GITHUB_OUTPUT-name:Runonlyaffectedtestsif:steps.affected.outputs.tests!=''run:npxvitestrun${{steps.affected.outputs.tests}}

对于动辄上千测试的项目,这个优化能把 PR 验证时间从十分钟压缩到一分钟。

#跨项目查询

每个 MCP 工具都支持可选的 projectPath 参数,指向另一个已 init 过 CodeGraph 的项目:

codegraph_search({ query: "DatabasePool", projectPath: "/Volumes/code/other-service" })

ToolHandler 内部维护一个 LRU 风格的项目连接池(projectCache),首次访问会 CodeGraph.openSync,之后命中缓存。这让你可以在主项目里追问"我们的另一个服务里同名类怎么实现的",而不需要切换工作目录。

#故障排查

  • 索引超慢且 status 显示 Backend: wasm → 没装 native sqlite。按上文 5 节修复。
  • MCP server 连不上 → 命令行先单独跑 codegraph serve --mcp,看是否报错;再检查 ~/.claude.json 的路径与权限。
  • 缺符号 → MCP server 保存后会自动 sync(2 秒防抖)。若手动 codegraph sync 也不出现,确认文件语言在支持列表里、且未被 exclude 命中。
  • database is locked → 通常是 WASM backend 在跑大索引时阻塞读,等几秒重试即可;长期方案还是修 native sqlite。
  • 节点数明显偏少 → 大概率是文件超过 maxFileSize 被静默跳过。检查 codegraph status 的 errors 列表。

#你也可以用 CodeGraph 做的事

CodeGraph 不只是给 Claude Code 用的:

  • 新人 onboarding 工具:内部脚本调 cg.buildContext("我们的支付系统") 直接生成 onboarding 文档。
  • 代码评审辅助:CI 在 PR 上跑 cg.getImpactRadius(changedNode, 3),把可能被影响的下游代码贴到 PR 评论里。
  • 死代码扫描cg.findDeadCode() 找出 0 引用的导出符号。
  • 循环依赖检测cg.findCircularDependencies() 返回所有文件级依赖环。
  • 复杂度审计cg.getNodeMetrics(id) 给出节点的入边/出边/调用次数/被调次数。

最后

CodeGraph 之所以能跑出 92% 工具调用减少的成绩,根本原因不在于"用了 tree-sitter"或"用了 SQLite"——这些技术早就存在。真正的差别在于它把已经被证明可行的静态索引技术,重新打包为 LLM 的工具调用接口,并且把每一个工程细节做到位

CodeGraph 的本质是给 AI 编程助手装上一双"IDE 的眼睛"——它让 LLM 不再是在文件系统里盲扫的考古学家,而是站在一个完整代码地图上的城市规划师。

代码不再是 LLM 一次次重新发现的混沌,而是被 tree-sitter 解析、被 SQLite 索引、被 BFS 遍历、被 FTS5 检索的、结构化的、可查询的、永远 fresh 的知识图谱。

94% 工具调用减少不是魔法。是把已经被 IDE 实践了几十年的事情,做了一遍给 LLM 用。

如果你看到这里,那这篇文章对你还是有点帮助的,希望得到你的关注,获取更多有见解的内容,你的点赞,收藏,转发是我坚持的动力。