代码图谱
本地代码知识图谱 MCP 服务,为 AI 编程助手省 token、减工具调用
CodeGraph
🎉 1.0 发布!
已经安装了?运行 codegraph upgrade
在X上关注 @getcodegraph 获取更新。
用语义代码智能增强 Claude Code、Cursor、Codex、OpenCode、Hermes Agent、Gemini、Antigravity 和 Kiro
精确上下文 · 更少的工具调用 · 更快的答案 · 100% 本地
文档与网站 →
CodeGraph 平台即将到来——对于每个 PR,确切知道要测试什么、哪些可能出错、哪些流程受影响以及业务逻辑是否受损。
获取托管产品的早期 beta 访问· getcodegraph.com
目录
- 开始使用
- 语言支持
- 为什么选择 CodeGraph?
- 关键特性
- 框架感知路由
- 混合 iOS / React Native / Expo 桥接
- 快速入门
- 工作原理
- CLI 参考
- MCP 工具
- 库使用
- 配置
- 遥测
- 支持平台
- 支持代理
- 支持语言
- 测量的跨文件覆盖率
- 故障排除
- Star 历史
- 许可证
开始使用
1. 安装 CLI
无需 Node.js — 一个命令获取适用于你操作系统的正确构建版本:
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh
# Windows (PowerShell)
irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex
已经安装了 Node?改用 npm(适用于任何版本)
npm i -g @colbymchenry/codegraph
CodeGraph 捆绑了自己的运行时——无需编译,无原生构建,在任何地方都能同样工作。安装程序会将 codegraph 添加到 PATH 中,但不会更改你当前的 shell——在下一步之前打开一个新终端,以便命令能够解析。
随时升级使用 codegraph upgrade — 它会检测你的安装方式(bundle、npm 或 npx)并原地更新。添加 --check 查看是否有可用更新,或使用 codegraph upgrade <version> 锁定特定版本。
2. 连接你的代理
在一个新终端中,运行安装程序以将 CodeGraph 连接到您使用的代理:
codegraph install
检测并自动配置 Claude Code、Cursor、Codex CLI、opencode、Hermes Agent、Gemini CLI、Antigravity IDE 和 Kiro——将 CodeGraph MCP 服务器接入每个代理。这是将 CodeGraph 连接到您的代理的步骤; 第 1 步中安装 CLI 不会自动完成。它只连接您的代理——它不会索引任何代码;构建每个项目的图是第 3 步中单独的 codegraph init。(快捷方式:npx @colbymchenry/codegraph 可以一次性下载并运行。)
3. 初始化每个项目
cd your-project
codegraph init
codegraph init 创建本地 .codegraph/ 目录,并在同一步骤中构建完整图——一个命令,搞定。
4. 无需再同步!
默认启用自动同步。CodeGraph 会监视项目,并在每次文件更改时更新图——当您的代理编辑代码,或您添加、修改或删除文件时。索引永不陈旧,无需重新运行。
卸载
改变主意了?一个命令即可从每个已配置的代理中移除 CodeGraph 以及 CLI 本身——它会发现所有安装(独立 bundle、npm 全局包、启动器链接),并在删除任何内容之前向你显示:
codegraph uninstall
传递 --keep-cli 仅移除代理配置并保留已安装的 CLI。
逆转安装程序——从每个已配置的代理中剥离 CodeGraph 的 MCP 服务器配置、说明和权限。你的项目索引(.codegraph/)保持不变;使用 codegraph uninit 逐个项目移除。使用 --target 从特定代理移除,或使用 --yes 以非交互方式运行。
语言支持
下面每种语言都获得相同处理——完整结构提取和跨文件解析为一个图,无需每种语言单独设置:
每种语言的详细信息(扩展、框架以及具体提取内容)见支持的语言。
为什么选择 CodeGraph?
当 AI 代理需要理解代码(回答问题或进行修改)时,它会通过低效的方式发现结构:grep、glob 和 Read,一次一个文件,手动重建调用路径和依赖关系。在开始真正工作之前,这已经是一堆工具调用和往返。
CodeGraph 在一次调用中就将代理需要的精确代码交给它。 它是一个预构建的知识图谱,包含代码库中每个符号、调用边和依赖关系——因此,代理无需爬取文件,只需问一个问题,就能获得相关源代码、这些符号之间的调用路径(包括 grep 无法追踪的动态分发跳转)以及变更的影响范围。精确的上下文,而不是逐文件搜索——这意味着无论代码库大小如何,工具调用更少,回答更快。
关于成本的说明: CodeGraph 在每个代码库上的优势是精确性和速度——更少的工具调用,更快的回答。它也能降低 token 和美元成本,但这些节省是规模相关的:在中等规模的代码库上微小且不显著,只有当仓库庞大且复杂时——例如 Google 或 Microsoft 的单一仓库规模,再乘以整个团队日常代理使用量——这些节省才会累积成真正的成本项。对于一个 500 文件的项目,为速度采用 CodeGraph;当代码库(和团队)变大时,成本节省才会显现。
基准测试结果
在 7 个真实世界的开源代码库(涵盖 7 种语言)上进行了测试,比较了代理(Claude Code,无头模式)在使用和未使用 CodeGraph 的情况下回答一个架构问题,取每支 4 次运行的中位数。在 Opus 4.8(2026-06-02)上,使用当前构建版本(以 codegraph_explore 为主要工具)重新验证。
普遍性优势——每个仓库,任何规模:工具调用减少 58% · 速度提升 22% · 文件读取降至接近零。
稳定且普遍的回报是精确上下文和速度:CodeGraph 将代理的 grep/find/Read 爬取压缩为几次直接查询——即使你询问的精确方法隐藏在数千行的文件中,也能返回结果——因此代理以近乎零文件读取的方式回答,而未使用 CodeGraph 的代理则将其预算花费在发现上。Tokens 和 Cost 列也是真实的,但——如上所述——它们是规模相关的:每次查询微小且不显著,只有在大型代码库、高使用量规模下才会累积成实际成本。
| 代码库 | 语言 | 工具调用 | 时间 | 文件读取 | Tokens | 成本 |
|---|---|---|---|---|---|---|
| VS Code | TypeScript · ~10k 文件 | 减少 81% | 快 11% | 0 vs 9 | 减少 64% | 便宜 18% |
| Excalidraw | TypeScript · ~640 | 减少 40% | 快 27% | 0 vs 7 | 减少 25% | 持平 |
| Django | Python · ~3k | 减少 77% | 快 13% | 0 vs 9 | 减少 60% | 便宜 8% |
| Tokio | Rust · ~790 | 减少 57% | 快 18% | 0 vs 8 | 减少 38% | 持平 |
| OkHttp | Java · ~645 | 减少 50% | 快 31% | 0 vs 4 | 减少 54% | 便宜 25% |
| Gin | Go · ~110 | 减少 44% | 快 24% | 1 vs 6 | 减少 23% | 便宜 19% |
| Alamofire | Swift · ~110 | 减少 58% | 快 33% | 0 vs 9 | 减少 64% | 便宜 40% |
文件读取 = 代理使用与未使用 CodeGraph 时打开文件的中位数——这是精确上下文优势在一列中的体现。Tokens 和 Cost 是相同的有/无增量;它们具有方向性(随运行而变化),并且每次查询在绝对值上很小——这就是为什么它们只有在规模下才成为成本项。此外,codegraph_explore 还会将冗余的可互换实现折叠为签名,因此响应的大小取决于答案而非文件数量。
按仓库细分——使用 vs 未使用(4 组中位数)
VS Code · ~10k 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 59秒 | 2分 13秒 | 快 11% |
| 文件读取 | 0 | 9 | −9 |
| Grep/Bash | 0 | 11 | −11 |
| 工具调用 | 4 | 21 | 减少 81% |
| 总 tokens | 640k | 1.79M | 减少 64% |
| 成本 | $0.68 | $0.83 | 便宜 18% |
Excalidraw · ~640 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 32秒 | 2分 6秒 | 快 27% |
| 文件读取 | 0 | 7 | −7 |
| Grep/Bash | 1 | 8 | −7 |
| 工具调用 | 9 | 15 | 减少 40% |
| 总 tokens | 1.27M | 1.69M | 减少 25% |
| 成本 | $0.78 | $0.78 | 持平 |
Django · ~3k 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 43秒 | 1分 58秒 | 快 13% |
| 文件读取 | 0 | 9 | −9 |
| Grep/Bash | 0 | 5 | −5 |
| 工具调用 | 3 | 13 | 减少 77% |
| 总 tokens | 559k | 1.41M | 减少 60% |
| 成本 | $0.57 | $0.62 | 便宜 8% |
Tokio · ~790 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 55秒 | 2分 20秒 | 快 18% |
| 文件读取 | 0 | 8 | −8 |
| Grep/Bash | 0 | 6 | −6 |
| 工具调用 | 6 | 14 | 减少 57% |
| 总 tokens | 1.08M | 1.73M | 减少 38% |
| 成本 | $0.82 | $0.82 | 持平 |
OkHttp · ~645 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 1秒 | 1分 29秒 | 快 31% |
| 文件读取 | 0 | 4 | −4 |
| Grep/Bash | 2 | 6 | −4 |
| 工具调用 | 5 | 10 | 减少 50% |
| 总 tokens | 502k | 1.10M | 减少 54% |
| 成本 | $0.41 | $0.55 | 便宜 25% |
Gin · ~110 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 14秒 | 1分 37秒 | 快 24% |
| 文件读取 | 1 | 6 | −5 |
| Grep/Bash | 1 | 2 | −1 |
| 工具调用 | 5 | 9 | 减少 44% |
| 总 tokens | 651k | 847k | 减少 23% |
| 成本 | $0.46 | $0.57 | 便宜 19% |
Alamofire · ~110 文件
| 指标 | 使用 cg | 未使用 cg | 差值 |
|---|---|---|---|
| 时间 | 1分 35秒 | 2分 21秒 | 快 33% |
| 文件读取 | 0 | 9 | −9 |
| Grep/Bash | 0 | 4 | −4 |
| 工具调用 | 5 | 12 | 减少 58% |
| 总 tokens | 766k | 2.10M | 减少 64% |
| 成本 | $0.57 | $0.95 | 便宜 40% |
完整基准测试详情
方法论。 每支使用 claude -p(Claude Opus 4.8)以无头模式运行,仓库使用 --strict-mcp-config:使用 = 启用 CodeGraph 的 MCP 服务器,未使用 = 空白 MCP 配置。内置的 Read/Grep/Bash 两者均可使用。每个仓库相同的问题,每支 4 次运行,报告中间值。成本 = 运行中的 total_cost_usd;Tokens = 处理的 token 总数(包括缓存的输入 + 输出);时间 = 挂钟时间;工具调用 = 每次工具调用,包括模型生成的所有子代理中的调用。仓库以 --depth 1 克隆,并使用相同的 CodeGraph 构建版本索引。于 2026-06-02 在当前构建版本上重新验证。这些数字低于之前的 Opus 4.7 验证——不是 CodeGraph 的回退,而是更强的原生基线:Opus 4.8 在主线程上高效执行 grep/read,而不是分散到大型 Explore 子代理扫描中,因此未使用 CodeGraph 的支线比以前更精简。每个仓库的数字会随运行而变化,取决于未使用支线的波动程度(4 次的中位数平滑了波动,但尾部仍然存在——例如 Django 的未使用支线在某批次中达到了 $2.71/14 分钟)。
Queries:
| Codebase | Query |
|---|---|
| VS Code | ”How does the extension host communicate with the main process?” |
| Excalidraw | ”How does Excalidraw render and update canvas elements?” |
| Django | ”How does Django’s ORM build and execute a query from a QuerySet?” |
| Tokio | ”How does tokio schedule and run async tasks on its runtime?” |
| OkHttp | ”How does OkHttp process a request through its interceptor chain?” |
| Gin | ”How does gin route requests through its middleware chain?” |
| Alamofire | ”How does Alamofire build, send, and validate a request?” |
为何 CodeGraph 胜出:有了索引,智能体可以直接回答——通常一次 codegraph_explore 就能返回相关源码并停止,几乎不需读取文件。没有索引时,智能体在读取正确代码前,大部分预算都花在探索(find/ls/grep)上。CodeGraph 仅在直接查询时才起作用,因此其指令引导智能体直接回答,而不是将探索委托给文件读取子智能体——否则子智能体无论如何都会读取文件,CodeGraph 反而成了开销。
关键特性
| 精准上下文 | 一次工具调用即可返回入口点、相关符号和代码片段——无需缓慢的逐文件探索 |
| 全文搜索 | 借助 FTS5 在代码库中按名称即时查找代码 |
| 影响分析 | 在修改前追踪任何符号的调用者、被调用者以及完整影响范围 |
| 始终最新 | 文件监视器使用原生 OS 事件(FSEvents/inotify/ReadDirectoryChangesW),通过防抖自动同步——图形随代码编写保持最新,零配置 |
| 20+ 语言 | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi |
| 框架感知路由 | 识别 Web 框架路由文件,并将 URL 模式关联到其处理程序(覆盖 17 个框架) |
| 混合 iOS / React Native / Expo | 弥合静态解析忽略的跨语言流程:Swift ↔ ObjC 桥接、React Native 传统桥接 + TurboModules + Fabric 视图组件、原生 → JS 事件发射器、Expo Modules |
| 100% 本地 | 无数据离开您的机器。无需 API 密钥。无需外部服务。仅使用 SQLite 数据库 |
自动同步如何工作——以及为何您无需手动运行 codegraph sync
当您的智能体(Claude Code, Cursor, Codex, opencode)启动 codegraph serve --mcp 时,三层机制使索引与代码保持同步——并确保智能体在编辑到下次同步的短暂窗口期内不会得到沉默的错误答案:
-
带防抖自动同步的文件监视器。 原生的 FSEvents / inotify / ReadDirectoryChangesW 监视器捕获每个源文件的创建/修改/删除,并在防抖窗口(默认
2000ms,可通过CODEGRAPH_WATCH_DEBOUNCE_MS调整,限制在[100ms, 60s])后触发重新索引。编辑爆发会合并为一次同步。 -
每个文件的过时提示横幅。 在短暂的防抖窗口期间,如果 MCP 工具响应可能引用仍待处理的文件,则会在响应前添加一个
⚠️横幅,指明该文件并告诉智能体直接Read该文件。未被响应引用的待处理文件作为小脚注显示。无论哪种方式,智能体都会收到明确的信号——已在 Claude Code 中验证,智能体会在打开文件前明确说出“Reading the file directly for the live content”。 -
连接时的追赶。 当 MCP 服务器(重)连接时,codegraph 在回答第一个查询前,先对工作树进行快速的
(size, mtime)+ 内容哈希比对——这样,在无 MCP 服务器运行时(终端中的git pull、其他编辑器的修改、之前已退出的智能体会话)产生的编辑,会在下一次会话的第一次工具调用时被吸收。
智能体写入 src/Widget.ts
→ 监视器触发(<100ms)
→ 防抖(默认 2s)
→ 同步;Widget.ts 进入索引
→ 下次智能体查询时可见
随时验证:使用 codegraph status(CLI)。如有待处理项,将看到 ### Pending sync: 部分,列出文件及其编辑时间。
少数仍需要手动执行 codegraph sync 的情况:监视器被禁用(沙盒环境或设置了 CODEGRAPH_NO_DAEMON=1),或者您在智能体会话之外对索引进行脚本化操作,并希望在脚本开始时进行一次预同步。
→ 完整深入介绍见 Guides → Indexing a Project。
框架感知路由
CodeGraph 检测 Web 框架的路由文件,生成通过 references 边连接到其处理程序类或函数的 route 节点。查询视图/控制器的调用者时,现在会显示绑定它的 URL 模式。
| 框架 | 识别的形态 |
|---|---|
| Django | path(), re_path(), url(), include() in urls.py (CBV .as_view(), dotted paths) |
| Flask | @app.route('/path', methods=[...]), blueprint routes |
| FastAPI | @app.get(...), @router.post(...), all standard methods |
| Express | app.get(...), router.post(...) with middleware chains |
| NestJS | @Controller + @Get/@Post/..., GraphQL @Resolver + @Query/@Mutation, @MessagePattern/@EventPattern, @SubscribeMessage |
| Laravel | Route::get(), Route::resource(), Controller@action, tuple syntax |
| Drupal | *.routing.yml routes (_controller, _form, entity handlers); hook_* implementations in .module/.theme/.install/.inc |
| Rails | get '/x', to: 'users#index', hash-rocket => syntax |
| Spring | @GetMapping, @PostMapping, @RequestMapping on methods |
| Play | GET/POST/… verb routes in conf/routes → Controller.method actions (Scala + Java) |
| Gin / chi / gorilla / mux | r.GET(...), router.HandleFunc(...) |
| Axum / actix / Rocket | .route("/x", get(handler)) |
| ASP.NET | [HttpGet("/x")] attributes on action methods |
| Vapor | app.get("x", use: handler) |
| React Router / SvelteKit | Route component nodes |
| Vue Router / Nuxt | pages/ file-based routes, server/api/ endpoints, route middleware |
| Astro | src/pages/ file-based routes (.astro pages + .ts endpoints, [param]/[...rest] syntax) |
混合 iOS / React Native / Expo 桥接
真实的 iOS 和 React Native 代码库跨越多种语言——Swift 调用者调用一个已自动桥接的 Objective-C 选择器,JS 文件通过 React Native 桥接调用原生模块,JSX 组件委托给原生视图管理器。静态 tree-sitter 提取在每个语言边界处停止。CodeGraph 将它们桥接起来,使得 codegraph_explore 能够端到端地跨越间隙连接流程——调用路径和影响范围可以跨越边界,而不是在边界处停止。
| 边界 | JS/Swift 端 | 原生端 | 方式 |
|---|---|---|---|---|
| Swift → ObjC | Swift obj.foo(bar:) | ObjC 选择子 -fooWithBar: | @objc 自动桥接规则(包括 init/property/protocol 形式)+ Cocoa 介词前缀(With/For/By/In/On/At/…) |
| ObjC → Swift | ObjC [obj fooWithBar:] | Swift @objc func foo(bar:) | 反向桥接名称候选;验证源端的 @objc 暴露声明 |
| React Native 传统桥接 | JS NativeModules.X.fn(...) | ObjC RCT_EXPORT_METHOD / RCT_REMAP_METHOD · Java/Kotlin @ReactMethod | 解析宏/注解声明,构建 JS 名称 → 原生方法映射 |
| React Native TurboModules | JS import M from './NativeM'; M.fn(...) | 匹配 Codegen 规范的原生实现 | 将 Native<X>.ts 规范接口视为事实来源 |
| RN 原生 → JS 事件 | JS new NativeEventEmitter(...).addListener('e', cb) | ObjC [self sendEventWithName:@"e" body:...] · Swift sendEvent(withName: "e", ...) · Java/Kotlin .emit("e", ...) | 以字面事件名键控的合成跨语言事件通道 |
| Expo Modules | JS requireNativeModule('X').fn(...) | Swift / Kotlin Module { Name("X"); AsyncFunction("fn") { ... } } | 解析 Expo DSL 字面量;合成方法节点通过现有名称匹配进行解析 |
| Fabric 视图组件 | JSX <MyView prop={v}/> | TS Codegen 规范 + 原生实现类 | 规范 → component 节点;基于约定的名称+后缀查找(View/ComponentView/Manager/ViewManager)桥接到原生 |
| 传统 Paper 视图管理器 | JSX <MyView prop={v}/> | ObjC RCT_EXPORT_VIEW_PROPERTY · Java/Kotlin @ReactProp | 与 Fabric 相同 — Paper 时代的声明也会生成 component + property 节点 |
已在真实代码库上验证(每个桥接的小型/中型/大型示例):
| 桥接 | 小型 | 中型 | 大型 |
|---|---|---|---|
| Swift ↔ ObjC | Charts | realm-swift | Wikipedia-iOS |
| RN 传统桥接 | AsyncStorage | react-native-svg | react-native-firebase |
| RN 原生 → JS 事件 | RNGeolocation | — | react-native-firebase |
| Expo Modules | expo-haptics | expo-camera | Expo SDK 扫描(7 个包) |
| Fabric / Paper 视图 | react-native-segmented-control | react-native-screens | react-native-skia |
每个桥接发出的边都带有 provenance:'heuristic' 标签和 metadata.synthesizedBy:(设置为稳定的通道名称,例如 swift-objc-bridge、rn-event-channel、fabric-native-impl、expo-module-extract),因此代理可以一眼看出跳转到图中的来源。
快速开始
1. 运行安装程序
npx @colbymchenry/codegraph
安装程序会:
- 询问要配置哪些代理 — 自动检测已安装的:Claude Code、Cursor、Codex CLI、opencode、Hermes Agent、Gemini CLI、Antigravity IDE、Kiro
- 提示将
codegraph安装到 PATH(以便代理可以启动 MCP 服务器) - 询问配置是否适用于所有项目还是仅当前项目
- 为每个选中的代理写入 MCP 服务器配置,并在代理的指令文件(
CLAUDE.md/AGENTS.md/GEMINI.md)中添加一个带标记的 CodeGraph 段落 — 这样子代理和非 MCP 代理就能了解codegraph explore命令,因为 MCP 服务器自身的指导仅能到达主代理。通过codegraph uninstall可干净移除。 - 当以 Claude Code 为目标时,设置自动允许权限
安装程序仅配置您的代理 — 不会索引您的代码。 完成后,请自行使用 codegraph init(步骤 3)构建每个项目的图。一次全局 codegraph install 覆盖所有项目;每个项目运行一次 codegraph init。
非交互式(脚本 / CI):
codegraph install --yes # 自动检测代理,全局安装
codegraph install --target=cursor,claude --yes # 显式指定目标列表
codegraph install --target=auto --location=local # 检测到的代理,项目本地
codegraph install --print-config codex # 打印代码片段,不写入文件
| 标志 | 值 | 默认值 |
|---|---|---|
--target | auto、all、none 或 CSV 列表(claude,cursor,...) | 每次步骤提示 |
--location | global、local | 每次步骤提示 |
--yes | (布尔值) | 每次步骤均提示 |
--no-permissions | (布尔值)跳过 Claude 自动允许列表 | 权限开启 |
--print-config <id> | 转储单个代理的代码片段并退出 | — |
2. 重启您的代理
重启您的代理(Claude Code / Cursor / Codex CLI / opencode / Hermes Agent / Gemini CLI / Antigravity IDE / Kiro)以加载 MCP 服务器。
3. 初始化项目
cd your-project
codegraph init
构建每个项目知识图谱索引,之后会在每次文件更改时自动同步。一次全局 codegraph install 即可在您打开的所有项目中工作 — 无需为每个项目重新运行安装程序。
就这样 — 如果存在 .codegraph/ 目录,您的代理将自动使用 CodeGraph 工具。
手动设置(备选)
全局安装:
npm install -g @colbymchenry/codegraph
添加到 ~/.claude.json:
{
"mcpServers": {
"codegraph": {
"type": "stdio",
"command": "codegraph",
"args": ["serve", "--mcp"]
}
}
}
(可选)添加到 ~/.claude/settings.json 以实现自动允许:
{
"permissions": {
"allow": [
"mcp__codegraph__*"
]
}
}
一个通配符自动批准所有 CodeGraph 工具 — 默认仅列出 codegraph_explore,但如果您通过 CODEGRAPH_MCP_TOOLS 重新启用其他工具,它们已被允许,无需提示。
代理工具指导
CodeGraph 的 MCP 服务器会在 MCP initialize 响应中自动将其使用指导传递给您的代理。简而言之,它告诉代理:
- 直接使用 CodeGraph 回答结构性问题 — 它本身就是预构建的索引,grep/read 循环只会重复它已完成的工作。将返回的源代码视为已读取。
- 对于几乎所有事情都使用
codegraph_explore— “X 如何工作”、某个流程/“X 如何到达 Y”,或调查某个区域。一次调用即可返回按文件分组的相关源代码原样、它们之间的调用路径(包括动态派发跳转),以及影响范围摘要。在查询中指定文件或符号名称,即可读取其当前带行号的源代码。 - 信任结果 — 不要用 grep 重新验证,并在编辑后检查过时提示。
- 每个项目独立工作:通过传递
projectPath来查询任何拥有.codegraph/索引的项目 — 因此一个仅部分服务被索引的 monorepo 或另一个仓库可以在同一会话中工作。没有索引的路径会返回清晰的指导,建议使用内置工具;索引决策仍由您决定。
确切的文本是 src/mcp/server-instructions.ts —— 主代理的唯一真实来源。因为子代理和非 MCP 工具永远看不到 MCP 指南,安装程序还会在代理的指令文件中写入一个简短的标记围栏部分,指向对应的 codegraph explore CLI 命令。
工作原理
┌───────────────────────────────────────────────────────────────────┐
│ Claude Code │
│ │
│ "How does a request reach the database?" │
│ calls CodeGraph tools directly — no Explore sub-agent │
│ │ │
└─────────────────────────────────┬─────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ CodeGraph MCP Server │
│ │
│ explore · one call → verbatim source + call flow + blast radius │
│ │ │
│ ▼ │
│ SQLite knowledge graph │
│ symbols · edges · files · FTS5 full-text search │
└───────────────────────────────────────────────────────────────────┘
-
提取 — tree-sitter 将源代码解析为 AST。语言特定的查询提取节点(函数、类、方法)和边(调用、导入、继承、实现)。
-
存储 — 所有内容进入本地 SQLite 数据库(
.codegraph/codegraph.db),支持 FTS5 全文搜索。 -
解析 — 提取后,引用被解析:函数调用 → 定义,导入 → 源文件,类继承,以及框架特定的模式。
-
自动同步 — MCP 服务器使用原生操作系统文件事件监控你的项目。变更会进行防抖处理(2 秒静默窗口),仅过滤源文件,并进行增量同步。图表在你编码时保持最新 —— 无需配置。
CLI 参考
codegraph # 运行交互式安装程序
codegraph install # 运行安装程序(显式)
codegraph uninstall # 从代理和 CLI 中移除 CodeGraph(--keep-cli 仅保留配置)
codegraph init [path] # 初始化项目并构建其图表(一步完成)
codegraph uninit [path] # 从项目中移除 CodeGraph(--force 跳过确认)
codegraph index [path] # 完整索引(--force 重新索引,--quiet 减少输出)
codegraph sync [path] # 增量更新
codegraph status [path] # 显示统计信息
codegraph unlock [path] # 移除阻塞索引的过期锁文件
codegraph query <search> # 搜索符号(--kind, --limit, --json)
codegraph explore <query> # 相关符号的源代码 + 调用路径一次返回(与 codegraph_explore MCP 工具输出相同)
codegraph node <symbol|file> # 一个符号的源代码 + 调用者,或带行号读取文件(与 codegraph_node 输出相同)
codegraph files [path] # 显示文件结构(--format, --filter, --max-depth, --json)
codegraph callers <symbol> # 查找哪些代码调用了某个函数/方法(--limit, --json)
codegraph callees <symbol> # 查找某个函数/方法调用了哪些代码(--limit, --json)
codegraph impact <symbol> # 分析更改一个符号会影响哪些代码(--depth, --json)
codegraph affected [files...] # 查找受变更影响的测试文件(见下文)
codegraph daemon # 管理后台守护进程 —— 选择一个停止(别名:daemons)
codegraph telemetry [on|off] # 显示或更改匿名使用遥测
codegraph upgrade [version] # 更新到最新版本(--check, --force)
codegraph version # 打印已安装版本(也支持 -v, --version)
codegraph help [command] # 显示帮助,可选针对某个命令
codegraph affected
传递性地追踪导入依赖,以查找受变更源文件影响的测试文件。
codegraph affected src/utils.ts src/api.ts # 将文件作为参数传递
git diff --name-only | codegraph affected --stdin # 从 git diff 管道输入
codegraph affected src/auth.ts --filter "e2e/*" # 自定义测试文件模式
| 选项 | 描述 | 默认值 |
|---|---|---|
--stdin | 从标准输入读取文件列表 | false |
-d, --depth <n> | 最大依赖遍历深度 | 5 |
-f, --filter <glob> | 用于识别测试文件的自定义 glob | 自动检测 |
-j, --json | 以 JSON 格式输出 | false |
-q, --quiet | 仅输出文件路径 | false |
CI/hook 示例:
#!/usr/bin/env bash
AFFECTED=$(git diff --name-only HEAD | codegraph affected --stdin --quiet)
if [ -n "$AFFECTED" ]; then
npx vitest run $AFFECTED
fi
MCP 工具
以 MCP 服务器运行时,CodeGraph 暴露一个单一工具——codegraph_explore。实测代理行为表明,一个强大的工具比一组较窄的工具能更好地引导代理——更少误选,并且每次会话节省上下文:
| 工具 | 用途 |
|---|---|
codegraph_explore | 一次调用回答几乎任何问题——“X 如何工作”、一个流程(“X 如何到达 Y”),或者调查一个区域——返回相关符号的逐文件原文源代码,以及它们之间的调用路径和影响范围摘要。它揭示了 grep 无法追踪的动态分发跳跃(回调、React 重新渲染、接口→实现)。在查询中命名一个文件或符号,可以读取其当前带行号的源代码,与 Read 工具返回的格式相同。 |
其他工具(codegraph_node、codegraph_search、codegraph_callers、codegraph_callees、codegraph_impact、codegraph_files、codegraph_status)保持完全功能,但默认不列出——它们返回的所有内容已经在 codegraph_explore 中内联呈现(其影响范围部分、关系地图、符号的主体作为被调用者列表)。使用 CODEGRAPH_MCP_TOOLS 环境变量(例如 CODEGRAPH_MCP_TOOLS=explore,node,search,callers)可以为 MCP 表面重新启用其中任何一个,或者使用它们的 CLI 等价命令(codegraph node / query / callers / callees / impact / files / status)。
即使服务器自身的根目录没有 .codegraph/ 索引,工具仍然可用:传递 projectPath 可以查询任何已索引的项目——单体仓库中的子服务,或另一个仓库——在同一个会话中。没有索引的路径会返回清晰的提示,建议改用内置工具,因此不会出现严重错误,并且索引仍由你决定。
库使用方法
CodeGraph 可以直接嵌入。npm 包重新导出了其编程 API,因此 import 和 require 都可以在你的进程中解析 CodeGraph 类——方便将其嵌入到应用程序中(例如 Electron 主进程)。
import CodeGraph from '@colbymchenry/codegraph';
// CommonJS works too:
// const { CodeGraph } = require('@colbymchenry/codegraph');
const cg = await CodeGraph.init('/path/to/project');
// Or: const cg = await CodeGraph.open('/path/to/project');
await cg.indexAll({
onProgress: (p) => console.log(`${p.phase}: ${p.current}/${p.total}`)
});
const results = cg.searchNodes('UserService');
const callers = cg.getCallers(results[0].node.id);
const context = await cg.buildContext('fix login bug', { maxNodes: 20, includeCode: true, format: 'markdown' });
const impact = cg.getImpactRadius(results[0].node.id, 2);
cg.watch(); // auto-sync on file changes
cg.unwatch(); // stop watching
cg.close();
从同一入口点还导出了更底层的构建模块,供直接驱动图的调用者使用:DatabaseConnection、QueryBuilder、getDatabasePath、initGrammars / loadGrammarsForLanguages 以及 FileLock。
嵌入需求
- 通过 npm (
npm i @colbymchenry/codegraph) 安装,以便匹配的按平台分发包(包含编译后的库及其依赖)与 shim 一同获取。 - API 运行在你的运行时上,因此需要 Node 22.5+ 以使用内置的
node:sqlite(当 Electron 的捆绑 Node 版本为 22.5+ 时也适用)。CLI 和 MCP 服务器不受影响——它们运行在自包含的捆绑运行时上。 - TypeScript 类型随包一起提供。与任何面向 Node 的库一样,请确保
@types/node可用,并设置skipLibCheck: true(常见默认值)。
配置
几乎不需要配置 —— CodeGraph 默认零配置,无需编写或维护任何文件即可开始使用。语言支持根据文件扩展名自动生效,无需为每种语言进行单独配置。唯一的可选文件用于映射自定义文件扩展名。
默认情况下跳过的内容:
- 依赖、构建和缓存目录 —— 所有支持的栈中的
node_modules、vendor、dist、build、target、.venv、Pods、.next等目录,因此图中的内容是你的代码,而非第三方噪音。即使没有.gitignore也是如此。 .gitignore中的任何内容 —— 在 git 仓库中通过 git 生效;在非 git 项目中则直接读取.gitignore(根目录和嵌套)。- 大于 1 MB 的文件 —— 生成的 bundle、压缩后的 JS、第三方 blob。
若要排除其他内容,请将其添加到 .gitignore。若要重新包含某个默认排除的目录(例如,你确实希望索引一个第三方依赖),请添加否定模式 —— !vendor/。默认设置统一适用,因此提交依赖或构建目录不会强制其进入图;.gitignore 否定模式是显式的选择加入。
不过,.gitignore 无法取消已提交的目录。对于已检入仓库的第三方主题或 SDK(例如 static/ 下的 Metronic 主题),请在 codegraph.json 的 exclude 下列出它们 —— 使用 gitignore 风格的模式,相对于仓库根目录匹配,并在索引、同步和监视时生效:
{
"exclude": ["static/", "**/vendor/**"]
}
相反,当真实源代码被故意 gitignored 时(例如,一个项目使用了第二种版本控制系统(SVN、Perforce),.gitignore 了其自己的源代码以防止进入 Git),使用 include 强制重新包含它(与 exclude 相反;includeIgnored 仅恢复嵌入的 git 仓库,而非普通源代码):
{
"include": ["Tools/", "Local/typescript/"]
}
CodeGraph 在索引、同步和监视时从磁盘发现这些文件,覆盖 .gitignore。显式的 exclude 仍然优先,内置跳过的内容(node_modules、dist、.git)永远不会被重新包含。
自定义文件扩展名
如果你的项目对支持的语言使用了非标准扩展名 —— 例如 .dota_lua 表示 Lua,或 .tpl 表示 PHP —— 这些文件默认会被跳过,因为扩展名不是 CodeGraph 识别的。通过项目根目录下的可选 codegraph.json 映射它们:
{
"extensions": {
".dota_lua": "lua",
".tpl": "php"
}
}
每个值都是一个支持的语言标识符。映射会合并到内置默认值之上,并在冲突时获胜,因此你也可以重新映射内置扩展(例如 ".h": "cpp")。提交该文件以与团队成员共享映射。如果语言拼写错误或文件格式错误,会发出警告并跳过 —— 绝不会破坏索引 —— 没有 codegraph.json 的项目行为与之前完全一致。添加或更改映射后,请重新索引(codegraph index)。
遥测
CodeGraph 收集匿名使用统计信息 —— 哪些工具和命令被使用、哪些语言被索引 —— 以指导语言和代理支持工作的方向。绝不收集任何代码、路径、文件或符号名称、查询或 IP 地址;使用情况在本地聚合为每日总量后才发送,摄取端点是本仓库的公开代码,该代码强制执行文档中列出的字段清单。安装时会提前询问;随时关闭:
codegraph telemetry off # 或:CODEGRAPH_TELEMETRY=0,或 DO_NOT_TRACK=1
TELEMETRY.md 列出了每个字段、关闭开关以及完整的数据处理说明。
支持的平台
每个版本都会为所有三大桌面操作系统(Intel/AMD x64 和 ARM arm64)发布一个自包含的构建(捆绑了 Node 运行时 —— 无需编译):
| 平台 | 架构 | 安装方式 |
|---|---|---|
| Windows | x64, arm64 | PowerShell 安装程序 或 npm |
| macOS | x64, arm64 | shell 安装程序 或 npm |
| Linux | x64, arm64 | shell 安装程序 或 npm |
参见 开始入门 了解一键安装命令。
支持的代理
交互式安装程序会自动检测并配置以下每种代理 —— 配置好 MCP 服务器(它会提供自己的使用指南,因此不会写入指令文件):
- Claude Code
- Cursor
- Codex CLI
- opencode
- Hermes Agent
- Gemini CLI
- Antigravity IDE
- Kiro
支持的语言
| 语言 | 扩展名 | 状态 |
|---|---|---|
| TypeScript | .ts, .tsx | 完全支持 |
| JavaScript | .js, .jsx, .mjs | 完全支持 |
| ArkTS (HarmonyOS) | .ets | 完全支持(包含 TypeScript 的所有功能,以及 @Component/@ComponentV2 结构体及其 ArkUI 装饰器(@State/@Prop/@Link/@Local/@Builder/…)、build() 视图树 —— 父→子组件边、链接到 @Extend/@Styles 函数的链式属性、.onClick(this.handler) 事件绑定 —— 状态→build() 重新渲染的动态分发桥、@ohos.events.emitter 发射→订阅者对(仅静态事件键)、以及 router.pushUrl 的字面 URL → 目标页面结构体;ohpm 工作区模块通过 oh-package.json5 的 file: 依赖解析裸 import { X } from "data",并尊重每个模块的 main 入口) |
| Python | .py | 完全支持 |
| Go | .go | 完全支持 |
| Rust | .rs | 完全支持 |
| Java | .java | 完全支持 |
| C# | .cs | 完全支持 |
| PHP | .php | 完全支持 |
| Ruby | .rb | 完全支持 |
| C | .c, .h | 完全支持 |
| C++ | .cpp, .hpp, .cc | 完全支持 |
| Objective-C | .m, .mm, .h | 部分支持(类、协议、方法、@property、#import、消息发送;.mm ObjC++ 可能解析不完整) |
| Metal | .metal | 完全支持(顶点/片段/核函数、结构体、类型别名、调用边 —— MSL 解析为 C++,并处理 [[attribute]] 注解) |
| CUDA | .cu, .cuh | 完全支持(核函数和设备/主机函数、结构体、类、通过 <<<grid, block>>> 启动语法的主机→核函数调用边 —— 包括模板启动、函数指针启动(auto kernel = &fn<...>)、dim3{...} 配置以及宏定义的核函数;处理了 __global__/__device__/__launch_bounds__ 说明符;通过内容识别普通 .h/.hpp 头文件中的 CUDA) |
| Swift | .swift | 完全支持 |
| Kotlin | .kt, .kts | 完全支持 |
| Scala | .scala, .sc | 完全支持(类、特质、方法、类型别名、Scala 3 枚举) |
| Dart | .dart | 完全支持 |
| Svelte | .svelte | 完全支持(脚本提取、Svelte 5 rune、SvelteKit 路由) |
| Vue | .vue | 完全支持(脚本 + script-setup 提取、Nuxt 页面/API/中间件路由) |
| Astro | .astro | 完全支持(frontmatter + 脚本提取、模板组件/调用引用、src/pages/ 路由) |
| Liquid | .liquid | 完全支持 |
| Pascal / Delphi | .pas, .dpr, .dpk, .lpr | 完全支持(类、记录、接口、枚举、DFM/FMX 表单文件) |
| Lua | .lua | 完全支持(函数、带接收器的方法、局部变量、require 导入、调用边) |
| R | .R .r | 完全支持(所有赋值形式的函数、S4/R5/R6 类及其方法、library/require 导入、source() 文件引用、调用边) |
| Luau | .luau | 完全支持(Lua 的所有功能,外加 type/export type 别名、类型化签名以及 Roblox 实例路径 require) |
| CFML | .cfc, .cfm, .cfs | 完全支持(基于标签的 <cfcomponent>/<cffunction> 和裸脚本 component { ... } 风格、extends/implements、嵌入的 <cfscript> 委托、调用边) |
| COBOL | .cbl, .cob, .cpy | 完全支持(程序、带有 PERFORM/GO TO 调用边的节/段落、CALL ‘literal’ 跨程序调用、COPY copybook 导入 —— 包括独立的 .cpy 文件 —— DATA DIVISION 记录/字段/88 级别、EXEC CICS LINK/XCTL 和 EXEC SQL INCLUDE 目标;固定格式和自由格式) |
| Visual Basic .NET | .vb | 完全支持(类、模块、接口、结构体、枚举、属性、事件、Declare P/Invoke、Handles/WithEvents、Inherits/Implements 边、通过 VB 的调用/索引括号歧义的调用边、As New 实例化、插值字符串、LINQ、Unicode 标识符) |
| Erlang | .erl, .hrl, .escript, .app.src, .app | 完全支持(带有多个子句/多元数分组的函数、-spec 签名、带字段的记录、-type/-opaque 别名、-define 宏、-include/-include_lib/-import 边、本地和 mod:fn 远程调用边、fun name/arity 引用、spawn/apply/proc_lib/timer/rpc MFA 参数调用边、gen_server:call/cast(?MODULE) → 自身 handle_call/handle_cast 链接、-behaviour 链接、基于 -export 的可见性) |
| Solidity | .sol | 完全支持(合约、库、接口、结构体、枚举、修饰符、事件、错误、状态变量、import/using 指令、emit/revert 调用) |
| Terraform / OpenTofu | .tf, .tfvars, .tofu | 完全支持(资源、数据源、模块、变量、输出、包括别名的提供者、locals;带有 Terraform 每个目录作用域强制的 var./local./module./资源引用;跨边界桥接的模块调用 —— 输入到子模块变量、module.M.out 到子模块输出、source 到模块文件;cloudposse/atmos remote-state 跨组件接线(当组件静态命名时);向上解析模块树的 provider = aws.east 选择;moved/import/removed/check 块引用;链接到其所设置变量的 .tfvars 赋值) |
| Nix | .nix | 完全支持(具有简单/解构/柯里化参数的函数、let/attrset 绑定、inherit、import ./path 文件边 —— ./dir 通过 default.nix 解析 —— 以及 NixOS 模块 imports = [ ./x.nix ] 列表和 callPackage ./pkg.nix 文件边;调用边;模块系统选项接线 —— 例如 launchd.user.agents.x = { ... } 这样的配置写入链接到声明 options.launchd.user.agents 的模块,因此选项流跨模块追踪) |
实测交叉文件覆盖率
影响范围和爆炸半径查询的效果完全取决于其背后的依赖图,因此覆盖率是实际测得的而非假设的。公平覆盖率 = 在每种语言的真实基准仓库中,至少有一个已解析的跨文件依赖项(即导入、调用、引用或通过框架约定路由到它的依赖项)的符号承载源文件所占比例。剩余部分始终是真正的静态分析边界(运行时动态派发、反射/DI容器、框架约定入口点、供应商第三方代码),绝不会通过操控分母来隐藏。
| 语言 | 基准仓库 | 覆盖率 |
|---|---|---|
| TypeScript / JavaScript | this repo | 95.8% |
| Python | psf/requests | 100% |
| Go | gin-gonic/gin | 96.6% |
| Rust | BurntSushi/ripgrep | 86.7% |
| Java | google/gson | 93.3% |
| C# | jbogard/MediatR | 85.2% |
| PHP | guzzle/guzzle | 100% |
| Ruby | sidekiq/sidekiq | 100% |
| C | redis/redis | 92.2% |
| C++ | google/leveldb | 94.8% |
| Objective-C | SDWebImage | 91.6% |
| Swift | Alamofire | 95.3% |
| Kotlin | square/okhttp | 96.2% |
| Scala | gatling/gatling | 91.2% |
| Dart | flutter/packages | 92.4% |
| Svelte / SvelteKit | sveltejs/realworld | 100% |
| Vue / Nuxt | nuxt/movies | 93.5% |
| Astro | xingwangzhe/stalux | 93.0% |
| Lua | nvim-telescope/telescope.nvim | 84.2% |
| Luau | dphfox/Fusion | 92.2% |
| Liquid | Shopify/dawn | 73.8% |
| Pascal / Delphi | PascalCoin | 77.4% |
框架路由的验证方式相同,基于每个框架的规范示例应用:Express 100%、FastAPI 98%、Flask 100%、NestJS 96.8%、Gin 96.5%、Axum 100%、Rocket 93.8%、Vapor 100%、Laravel 92%、Rails 89.6%、React Router 100%——而那些约定/反射密集型的框架则处于其诚实的静态分析上限:ASP.NET 83.9%、Spring 83.3%、Drupal 78.9%、Play 76.3%、Django 74.1%。SvelteKit、Vue/Nuxt 和 Astro 使用基于文件的路由,因此其页面/端点覆盖率即为上表中 Svelte/SvelteKit(100%)、Vue/Nuxt(93.5%)和 Astro(93.0%——每个 src/pages/ 文件都映射到两个验证仓库上的一个路由节点)的数据。
故障排除
“CodeGraph not initialized” —— 先在项目目录中运行 codegraph init。
索引速度慢 —— 检查 node_modules 和其他大型目录是否已排除。使用 --quiet 减少输出开销。
MCP 提示 database is locked —— 当前版本不应出现此问题:CodeGraph 自带 Node 运行时,并使用 Node 内置的 node:sqlite,以 WAL 模式运行,其中并发读取不会阻塞写入操作。如果仍然遇到此问题:
- 你使用的是旧版本(0.9 之前)的安装。 重新安装以获取捆绑的运行环境 —
curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh(macOS/Linux),irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex(Windows),或npm i -g @colbymchenry/codegraph@latest。 codegraph status显示Journal:不是wal—— 在此文件系统上无法启用 WAL(常见于网络共享和 WSL2 的/mnt),因此读取操作可能会阻塞写入操作。将项目(及其.codegraph/文件夹)移动到本地磁盘。
MCP 服务器无法连接 —— 你的代理会自动启动服务器,因此无需手动启动。确保项目已初始化并建立了索引(codegraph status),并且 MCP 配置中的路径正确。如果仍无法连接,重新运行 codegraph install 以重写配置。
MCP 工具调用失败并显示 Transport closed,但 codegraph status/sync 正常 —— 这几乎总是出现在 WSL2 中项目位于 Windows 驱动器(/mnt/c 或 /mnt/d 路径)上的情况,此时 CodeGraph 用于跨会话共享后台服务器的本地套接字不可靠。CodeGraph 现在会回退到在进程内提供会话服务,而不是断开连接,但如果仍然遇到此问题,请在 MCP 服务器的环境中设置 CODEGRAPH_NO_DAEMON=1 以完全跳过共享服务器(每个会话在独立进程中运行)。将项目移动到 Linux 原生文件系统(例如放在 ~/ 下而不是 /mnt/ 下)可恢复共享服务器。
缺少符号 —— MCP 服务器会在保存时自动同步(等待几秒)。如有需要,手动运行 codegraph sync。检查文件的语言是否受支持,且文件不在 .gitignore 或默认排除的目录(如 node_modules、dist)内。
在 Windows 和 WSL 之间共享同一个检出目录 —— 不要将两者指向同一个 .codegraph/:后台服务器的锁定和 SQLite 索引与创建它们的操作系统绑定,且跨 WSL2/Windows 文件系统边界的 SQLite 锁定不可靠。通过在其中一个系统上设置 CODEGRAPH_DIR 为不同的名称,使双方在同一目录树中拥有各自的索引——例如,在 Windows 上设置 CODEGRAPH_DIR=.codegraph-win,WSL 保持默认的 .codegraph。CodeGraph 在索引和监视时会跳过任何兄弟目录 .codegraph-*,因此两者不会相互干扰。
Star 历史
许可证
MIT
