CodeGraph 深度解析:给 Claude Code / Cursor 一张”本地代码地图”
一、项目快照CodeGraphcolbymchenry/codegraph是 2026 年 1 月由独立开发者 Colby McHenry 创建的开源项目他在 Medium 个人介绍中自我描述为”15 年经验的自学软件工程师”。截至 2026 年 5 月 27 日仓库已经积累了约29.1k stars / 1.7k forks / 25 contributors5 月 23 日单日新增 2,434 star登上 GitHub Trending 第二位。技术栈非常简单TypeScript 94.8% / JavaScript 5.2%没有 Neo4j、没有向量数据库、没有外部 LLM API。LicenseMIT支持平台Windows / macOS / Linux要求 Node ≥18 250.9 起捆绑自己的 Node 运行时可裸机一键安装一句话定位给 Claude Code、Codex CLI、Cursor、OpenCode、Gemini CLI、Antigravity、Kiro、Hermes Agent 做”前置索引”的本地 MCP 服务器。二、它到底要解决什么问题任何用过 Claude Code 或 Cursor agent 模式的人都见过这一幕你问”用户认证流程是怎么走的”agent 立刻派出一个 Explore subagent开始grep -r→ls→Read file:1-200→Read file:201-400的循环。等它读完十几个文件几万 token 已经烧掉你的问题甚至还没真正开始回答。作者把这件事量化了。在 Medium 长文里他写道”我在自己的项目上计时——60 次 tool call、157,800 tokens、近 2 分钟的探索Claude 才真正开始处理我的请求。”CodeGraph 的核心立论是这种探索本质上是把”静态结构信息”用 LLM 的工作记忆反复重算。文件之间的调用、import、继承关系是确定性的、AST 可推导的没有任何理由每次会话都让 agent 用 grep 重新发现。提前算一次、放在本地 SQLite 里、通过 MCP 直接喂给 agent就够了。三、架构极其工程化的 tree-sitter SQLiteCodeGraph 的设计可以用一张图概括3.1 抽取tree-sitter而非 LSP这里介绍一下程序怎么理解代码和相关的工具tree-sitter 是什么tree-sitter 是 GitHub 在 2018 年开源的增量解析器生成器原本是为 Atom 编辑器做代码高亮做的。它的工作就一件事把源代码字符串变成一棵语法树AST。你给它一段 Pythondef add(a, b): return a b它返回一棵结构化的树function_definition ├── name: add ├── parameters: [a, b] └── body └── return_statement └── binary_expression () ├── left: a └── right: b三个让它特别受欢迎的特点增量解析——你改一行代码它只重算受影响的子树不重头扫整个文件。这是它原本叫这个名字的原因编辑器实时高亮全靠它。容错——代码语法错了它照样能解析给你尽量正确的树。LLM agent 写代码常常写到一半这点很关键。纯语法、不懂语义——它知道add(a, b)是个函数调用但不知道这个add到底定义在哪。它不做类型推断、不做跨文件引用解析。LSP 是什么LSP 全称Language Server Protocol语言服务器协议是微软在 2016 年为 VS Code 设计、后来变成业界标准的协议。它解决的问题是以前每个 IDE 都得为每种语言单独写一套代码智能跳转到定义、自动补全、找引用、重命名……。N 种 IDE × M 种语言 N×M 份重复工作。LSP 把这个矩阵拆成两半编辑器 (VS Code / Neovim / Cursor) ↕ LSP 协议 (JSON-RPC) 语言服务器 (rust-analyzer / pyright / tsserver / clangd) ↕ 你的代码语言服务器是真正懂这门语言的程序——它通常基于编译器本身rust-analyzer来自 Rust 编译器团队、pyright是微软的 Python 类型检查器、tsserver来自 TypeScript 团队。它能回答语义级问题光标下的validateToken跳转到哪里这个变量是什么类型谁调用了这个函数不是名字相同的是真正调用这个定义的把这个函数改名所有引用一起改LSP 跑得更准因为它真的理解类型系统、import resolution、泛型实例化——本质上它在脑子里维护了一份能编译的代码模型。两者的关键差异tree-sitterLSP语言服务器回答的问题语法这是个函数吗语义这个函数定义在哪需要编译吗不需要代码错了也能解析通常需要项目能编译/类型检查跨文件理解没有有每种语言一份 wasm小、统一一个独立的服务器进程重、各家实现差异大速度毫秒级编辑器实时用大项目首次加载几秒到几十秒典型用途语法高亮、代码折叠、批量符号抽取IDE 跳转、重命名、补全、类型检查CodeGraph 选 tree-sitter 而不是 LSP是一个明确的工程权衡它放弃了真正理解类型的精度比如obj.foo()里obj到底是什么类的实例tree-sitter 答不上来换来了三件事不用项目能编译agent 在写到一半的代码上也能工作、一份 wasm 覆盖所有平台部署极简、索引快到可以毫秒级响应文件保存CodeGraph 全部走 tree-sitter wasm对每种语言写一份 query 提取以下节点来自 CLAUDE.md 列出的 NodeKindfile, module, class, struct, interface, trait, protocol, function, method, property, field, variable, constant, enum, enum_member, type_alias, namespace, parameter, import, export, route, component和以下边EdgeKindcontains, calls, imports, exports, extends, implements, references, type_of, returns, instantiates, overrides, decorates这是关键的技术权衡tree-sitter 比 LSP 弱没有真正的类型推断、没有跨包符号表但它有三个决定性优势(1) 不需要项目能编译(2) 一份 wasm 二进制覆盖所有平台(3) 增量解析快到可以毫秒级响应文件保存。对一个面向 agent 的”探索性查询”工具这个折中是合理的。支持的语言现在已扩展到 21 种TypeScript / JavaScript / Python / Go / Rust / Java / C# / PHP / Ruby / C / C / Swift / Kotlin / Scala / Dart / Svelte含 Svelte 5 runes 和 SvelteKit 路由/ Vue含 Nuxt/ LiquidShopify 主题/ Pascal-Delphi含 DFM/FMX 表单文件/ Lua / LuauRoblox。3.2 存储SQLite FTS5没有图数据库这是 CodeGraph 和友商最大的体系差异之一。看 schema来自 IMPLEMENTATION_PLAN.md就知道作者在追求什么nodes(id, kind, name, qualified_name, file_path, start_line, end_line, language, signature, docstring, code_snippet, code_hash, metadata) edges(source_id, target_id, kind, resolved, target_name, line_number) files(path, content_hash, language, last_indexed, node_count) unresolved_refs(...) nodes_fts USING fts5(...) -- 全文搜索节点 ID 就是字符串路径如func:src/auth.ts:validateToken:45。SQLite 在 WAL 模式下并发读写不阻塞再加上为每种查询模式都准备好索引BFS/DFS 在 10 万节点级别仍然亚毫秒。值得注意的是仓库早期的设计里有vectors/模块基于xenova/transformers跑 ONNX存 384 维 nomic-embed-text-v1.5 embeddingsSQLite vss 索引但在某次提交中被整个移除了——issue #87 里有中国用户 zzqq131 直接问”为什么把整个向量搜索和 embedding 模块删掉”。这个决策意味深长作者用实测发现对”找调用链、找定义、找路由”这类问题符号名 FTS5 图遍历就足够了向量检索引入的延迟和不确定性反而是负担。3.3 引用解析手写而非 LLM 总结resolution/模块做三件事Imports → 文件识别 tsconfig path alias、Cargo workspace、Python packageCalls → 定义先用 import 表过滤候选再做 name matchingInheritanceextends/implements双向边特殊的是dynamic-dispatch 桥接synthesizers识别 callback/observer 注册、EventEmitter、ReactsetState → render、JSXrender → child component、Django ORM descriptors 等模式给图加一条provenance: heuristic的合成边。这是让 trace 工具能跨”事件分发、回调、运行时绑定”这些 grep 永远穿不过的边界的关键。3.4 暴露给 agent 的 10 个 MCP tool按文档语义分两类。重型工具agent 主力main session 应避免直接调用codegraph_context— 给定一个任务/特性描述组合 search node callers callees一次返回”涉及到的入口和上下文”codegraph_trace— “X 是怎么调到 Y 的”每一跳的函数体内联返回跨动态分发一次 trace 调用就结束流程探索codegraph_explore— 一次返回若干相关符号的源码按文件分组 关系图轻型工具main session 可直接用用于做改动前的精准查询codegraph_search按名字找符号只返位置codegraph_callers/codegraph_callees调用链codegraph_impact改动影响半径codegraph_node单个符号详情可附源码codegraph_files项目文件树比文件系统扫描快codegraph_status索引健康度CLAUDE.md里有一段工程笔记值得 agent 开发者借鉴”CodeGraph 影响 agent 行为的渠道是低显著性的——只有 MCP initialize instructions 和 tool descriptions。改 wording 并不能可靠地改变 agent 的 tool 选择风格。真正起作用的是让工具本身一次性给够让 agent 没有理由 fallback 去 Read。“3.5 框架感知路由extraction/frameworks/识别 14 类 web 框架的路由声明把它们也变成图节点kind: routeDjango (path/re_path/url/include)、Flask、FastAPI、Express、NestJS含 GraphQL/WebSocket、Laravel、Drupal*.routing.yml hook_*、Rails、SpringGetMapping等、Gin/chi/gorilla/mux、Axum/actix/Rocket、ASP.NET[HttpGet]、Vapor、React Router/SvelteKit这意味着你可以让 agent 问”POST /api/users这个接口的实现在哪影响哪些下游”——一次codegraph_impact直接出结果。3.6 自动同步sync/用原生 OS 事件 (FSEvents / inotify / ReadDirectoryChangesW)2 秒静默窗口debounce只过滤源码文件做增量 reparse。结果是你 Cmd-S 保存代码再问 agent 时图已经更新。四、横向对比code RAG 这个赛道分几派我把目前面向 AI agent 做代码上下文的工具按”如何表示代码”分了五派。CodeGraph 处在”图派 本地优先”那一格相对位置很清楚工具核心表示索引位置给 agent 的接口主要场景CodeGraphtree-sitter AST → SQLite 图 FTS5本地MCP10 个工具Claude Code/Cursor/Codex 等 agent 的探索加速Aider repo maptree-sitter tags PageRank本地拼到 prompt 里Aider 终端 pair programmingCursor 内建索引文件分块 → embedding远端 Turbopuffer Merkle 树同步CodebaseCursor IDE 内Continue.devtree-sitter 分块 embedding FTS本地 ~/.continue/indexCodebase / FolderContinue IDE 插件Sourcegraph CodySCIPLSIF 后继 embedding远端 Sourcegraph 实例内建 MCP server企业代码搜索Augment Code语义索引专有 Context Engine远端MCP远端 HTTPS企业级 agent跨仓Potpie.aiNeo4j 属性图服务端自托管或 SaaSFastAPI 专用 agent企业 spec-driven 大代码库Greptile仓库依赖图远端 SaaSPR review agentAI code reviewBloop语义搜索桌面/远端桌面 UI自然语言代码搜索Repomix / Code2Prompt / yek整库拼成大文本本地复制粘贴 / MCP给长上下文 LLM 做一次性 dumpCodeQL数据流控制流 facts → Datalog本地QL 查询安全分析 / variant analysisGlean (Meta)通用代码事实库 SCIP 输入服务端Glass APIMeta 内部 IDE / RAG4.1 对比Aider 的 repo map相似目标不同形态Aider 是这条思路的开山者。它同样用 tree-sitter 抽 tags但用 PageRank 给整个 repo 的符号排序再在一个 token budget 里塞最重要的 N 个 tags 进 prompt。对比 CodeGraphAider 是”预算化的单次上下文“——Aider 官方文档明确写道这个 token 预算受--map-tokens参数控制默认 1k tokens。Aider 会根据对话的当前状态动态调整 repo map 的大小。默认 1k tokens 的 repo map 跟着每次对话发可动态扩展CodeGraph 是”按需图查询“——agent 自己决定问哪一片每次只取相关子图。对 Aider 这种”一次会话改几个文件”的 pair programming 模式PageRank 静态摘要足够好。对 Claude Code 这种”先 explore subagent 摸清架构”的 agent 流水线CodeGraph 的按需查询更省 token。4.2 对比Cursor / Continueembedding 派和图派的根本差异Cursor 的做法是教科书级的 RAG且公开的工程细节最完整根据 Cursor 官方博客cursor.com/blog/secure-codebase-indexing和 turbopuffer 的客户案例页面Cursor 用一棵Merkle 树来构建对代码库的初始视图……每个代码库实例在 turbopuffer 里都是一个独立的命名空间namespace。turbopuffer 为 Cursor 提供代码检索能力——在合适的时机把代码搜索的结果填充进上下文窗口。。流程是本地按 tree-sitter 切块 → 上传 Cursor 服务器 → 算 embedding → 存进 Turbopuffer 向量库 → 本地用 Merkle 树同步差异。Continue.dev 类似但 embedding 在本地用 transformers.js 算索引落盘到~/.continue/index。Embedding 派的强项语义模糊查询好”哪里在处理用户限流”这种问得到答案。短板精确的”谁调用了validateToken“是不可靠的因为相似度排序会把名字相近但无关的函数排上来。CodeGraph 反过来结构化关系是精确的模糊语义靠不上。问”日志系统在哪里实现”CodeGraph 不一定胜过 embedding但问”Session.request()一路调到URLSession.dataTask()经过哪 9 个函数”——README 里那个 Alamofire 基准测试给出了答案一次 trace 调用depth 3完整 9 跳链路。这种 call chain 是 embedding 路线几乎不可能做到的。4.3 对比Sourcegraph Cody精确性维度类似部署模型相反Cody 用 SCIPSourcegraph Code Intelligence ProtocolLSIF 的后继协议——通过scip-typescript、scip-java、rust-analyzer等真正的编译器/类型检查器精确抽取符号。这比 tree-sitter 更准懂泛型实例化、懂 import resolution 的所有边角代价是每种语言都要一个专门的 indexer要能编译。部署上Cody 中心化数据上传 Sourcegraph 实例CodeGraph 本地化.codegraph/codegraph.db文件不离开你的机器。对个人开发者和不愿外传源码的团队CodeGraph 的”无 API key、无外部服务”是硬性优势。对需要跨百仓库导航的大型组织Sourcegraph 仍然是天花板。4.4 对比Potpie.ai同样图派不同重量级Potpie 也是知识图谱路线但走的是重型路线用 Neo4j 存属性图、FastAPI 服务层、Celery 任务队列、CrewAI 编排的 RAG agent。根据 http://itbrief.asia 的融资公告Potpie 的目标客户是百万行代码量级起步的大型企业……目前 Potpie 已经在为财富 500 强企业、以及医疗健康、保险科技等受监管行业的上市公司提供服务。Potpie 于 2026 年 3 月完成 220 万美元 Pre-Seed 融资由 Emergent Ventures 领投All In Capital、DeVC 和 Point One Capital 跟投。CodeGraph 是轻型路线一个 npm 包、一个 SQLite 文件、一个 MCP server目标用户是”用 Claude Code 在自己项目里写代码的个人开发者和小团队”。Potpie 的图比 CodeGraph 更”语义化”——每个函数都有 LLM 生成的 docstring 写进图。CodeGraph 坚持”extraction 是确定性的源自 AST不被 LLM 总结“CLAUDE.md 原话——这让索引完全可复现、无 LLM 调用成本但也意味着图本身不携带语义注解。4.5 对比Augment Code商业 Context EngineAugment 把”context engine”做成卖点但其定位明确不是”百万 token 暴力填充派”——其官方博客标题就是 “Context Window Wars: 200k vs 1M Token Strategies”主打200K 上下文 智能检索索引能力上限按官方页面是 ”up to 500,000 files simultaneously across dozens of repositories”。Augment 的 MCP server 也可以接到 Claude Code/Cursor 上用。对企业Augment 的合规SOC 2 Type II、ISO/IEC 42001、单租户、BYOK 是 CodeGraph 没有的。对独立开发者Augment 的远端架构和按 credits 计费是负担——Augment 官方文档docs.augmentcode.com/context-services/mcp/overview明确说Context Engine MCP 按查询计费每次查询消耗的 credits 数量不同——具体取决于底层成本和检索量。根据我们的实际数据平均每次查询消耗40–70 credits。4.6 对比repomix / code2prompt / yek完全不同的哲学这一派是”把整个 repo 拼成一个大文件“。在 Gemini 2.5 Pro 这种百万 token 模型上塞得下时管用对大型 repo 几乎瞬间失效——Next.js repo 单纯文本就 5600 万 tokens。yek 用 git history 做优先级排序部分缓解了这个问题。哲学差异他们假设模型能在长上下文里自己挑相关内容CodeGraph 假设 agent 应该被引导只看相关子图。后者在 Claude Opus 4.7 这种 1M 上下文模型上仍然有意义因为”应付得了”和”花得起钱”是两回事。4.7 对比CodeQL / Glean不同层次的目标CodeQLGitHub和 GleanMeta 开源也都把代码变成可查询的事实库但目标是精确语义分析——CodeQL 用 QL 语言查数据流污点分析、Glean 用 Datalog 风格的 Angle 查 facts。表达力远超 CodeGraph但学习曲线陡、面向静态分析工程师而非 LLM agent。CodeGraph 是把”图查询”包装成 agent 友好的高层意图”找谁调用了 X”不是给人写复杂查询用的。五、上手三条命令# 一次性安装自动检测并配置已安装的 agent curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh # 或npx colbymchenry/codegraph # 在项目里初始化 索引 cd your-project codegraph init -i # 启动 MCP 服务agent 会自己拉起来通常不用手动跑 codegraph serve --mcpCLI 还包括codegraph index、codegraph sync增量更新、codegraph query name、codegraph context task、codegraph impact symbol和一个有趣的codegraph affected——基于图反向追踪”我改了src/auth.ts哪些测试文件会被影响”可以塞进 CI 只跑相关测试git diff --name-only HEAD | codegraph affected --stdin --quiet | xargs vitest run作为库使用TypeScriptimport CodeGraph from colbymchenry/codegraph; const cg await CodeGraph.init(/path/to/project); await cg.indexAll(); 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(); // 自动同步六、实测结果作者基准README 里有两组数字——这里我把它们都列出来因为方法论不同早期 READMEClaude Opus 4.6单次运行每个 repo 一个 Explore agentVS Code (TS, 4002 文件, 59377 节点) → 3 calls 17s vs 52 calls 97s94% 更少 · 82% 更快Swift Compiler (25,874 文件, 272,898 节点) → 6 calls 35s vs 37 calls 128s索引耗时 4 分钟平均92% fewer tool calls, 71% fasterv0.9.4 (2026-05-24) 重新验证Claude Opus 4.7、claude -pheadless、--strict-mcp-config、每组 4 次取中位数——更严谨的方法论给出更保守的数字平均 35% 更便宜 · 57% fewer tokens · 46% faster · 71% fewer tool calls横跨 7 个真实开源项目第二组数字更可信作者自己也写明大型 repo 收益更明显像 Gin约 150 个文件这种小项目”native search 已经够便宜差距被压缩”。七、结论与建议以下情况考虑用 CodeGraph 主力 agent 是 Claude Code / Codex CLI / Cursor agent 模式且经常在 1 万文件以上的项目里工作不能或不想把源码上传到 SaaS合规、隐私、纯偏好均算看重”调用链、影响分析、impact radius”这类精确结构化问题胜过”语义模糊匹配”想要零配置——codegraph init一条命令就完事没有 embedding 模型选型、没有向量库、没有 API key以下情况不建议用 CodeGraph需要跨多仓推理——CodeGraph 是单仓本地索引不做 cross-repo主要场景是”我不记得这段逻辑在哪、按语义找一下”——纯 embedding 工具Cursor 内建、Continue在这类查询上更稳是企业需要 SOC 2 / 单租户 / BYOK / 跨百仓——Sourcegraph、Augment、Potpie 是更合适的天花板需要真正的类型推断和泛型解析做安全分析——SCIP/CodeQL 路线更准一个值得借鉴的工程教训CodeGraph 的演化过程本身比代码更有启发——作者最初设计了向量搜索 embedding 模块IMPLEMENTATION_PLAN.md 里有完整 384 维 sqlite-vss 设计但在生产实测后删掉了整个模块。理由很简单对 agent 的探索性查询”按名字 结构边 FTS5”已经把 95% 的问题解决了引入 embedding 增加的延迟和不确定性反而把好不容易省下的 tool call 又花了回去。这给所有 AI agent 工程师一个提醒code RAG ≠ document RAG。代码有 AST有调用图有静态可推导的关系——把这些先吃掉再考虑用 embedding 补语义层。CodeGraph 选了相反的优先级并且效果不错。