首页
/ CodeGraph 实战指南:为 AI 编程 Agent 构建预索引代码知识图谱的架构、CLI 与配置全景

CodeGraph 实战指南:为 AI 编程 Agent 构建预索引代码知识图谱的架构、CLI 与配置全景

2026-09-06 13:30:42作者:史锋燃Gardner

CodeGraph 是一个 100% 本地运行的代码知识图谱引擎:它把整个代码库的符号、调用边和依赖预先解析成 SQLite 图,再通过 MCP 协议把"外科手术式上下文"一次性交给 Claude Code、Cursor、Codex 等 AI 编程 Agent。本文基于仓库根目录的 README.md 展开,覆盖安装接线、索引与自动同步机制、Rust 内核、30 余种语言支持、框架路由识别、CLI/MCP 完整参考与 codegraph.json 配置体系,并结合 src/db/schema.sqlsrc/project-config.ts 等源码印证关键设计。

一、它解决什么问题:Agent 的"结构发现"成本

当 AI Agent 需要理解代码(回答架构问题或实施修改)时,默认路径是 grep、glob、逐文件 Read,再手工重建调用链与依赖——在真正动手之前就要消耗大量工具调用与往返。

CodeGraph 的做法相反:它是代码库中每个符号、每条调用边、每个依赖的预构建知识图谱。Agent 只需问一个问题,就能拿到相关源码原文、符号之间的调用路径(包括 grep 无法跟随的动态分派跳转),以及改动的爆炸半径(blast radius)。结果是更少的工具调用、更快的回答,且全程 100% 本地——数据不出机器,无 API key,无外部服务,只依赖一个本地 SQLite 数据库。

二、三步上手:安装、接线、初始化

1. 安装 CLI(无需 Node.js)

CodeGraph 的发布构建自带 Node 运行时(self-contained bundle),一行命令即可获取匹配操作系统的构建。仓库根目录提供两个官方安装脚本:

  • macOS / Linux:install.shcurl -fsSL <install.sh 地址> | sh
  • Windows PowerShell:install.ps1irm <install.ps1 地址> | iex

如果本机已有 Node 环境,也可以直接走 npm:

npm i -g @colbymchenry/codegraph

两条路径的行为一致:无需编译、无原生构建,行为跨平台相同。安装器会把 codegraph 放到 PATH 上,但不会改变当前 shell——下一步请打开新终端再执行。

随时可以用 codegraph upgrade 升级:它会自动识别你当初的安装方式(bundle / npm / npx)并原地更新;--check 查看是否有新版本,codegraph upgrade <version> 可锁定指定版本。

2. 接线 Agent:codegraph install

在新终端中运行安装器,把 CodeGraph 接入你实际使用的 Agent:

codegraph install

它会自动检测并配置以下 Agent,把 CodeGraph 的 MCP server 写入各自的配置:Claude Code、Cursor、Codex CLI、opencode、Hermes Agent、Gemini CLI、Antigravity IDE、Kiro,以及 GitHub Copilot 的三个形态(VS Code 的 Copilot Chat、Copilot CLI、JetBrains IDE 插件)。

关键认知:这一步只接线,不索引。CLI 安装与 Agent 接线都不会分析任何代码;构建每个项目的图谱是第三步独立的 codegraph init

安装器同时会做几件容易被忽略的事(见 src/installer/ 下的目标实现,如 claude.tsregistry.ts):

  • 写入各 Agent 的 MCP server 配置;
  • 在 Agent 的指令文件(CLAUDE.md / AGENTS.md / GEMINI.md)中写入一段带标记围栏的 CodeGraph 小节——因为 MCP server 自带的指引只到达主 Agent,子 Agent 与非 MCP 环境需要靠这段文字学会 codegraph explore 命令;该小节可被 codegraph uninstall 干净移除;
  • 若目标是 Claude Code,则配置 auto-allow 权限。

一个全局 codegraph install 覆盖你打开的所有项目;每个项目只需单独执行一次 codegraph init

3. 初始化项目:codegraph init

cd your-project
codegraph init

codegraph init 在同一步骤中创建本地 .codegraph/ 目录并构建完整图谱——一条命令,一步完成。

4. 之后无需再手动同步

自动同步默认开启:CodeGraph 监视项目,任何文件的增、改、删都会触发图谱增量更新——无论是 Agent 在改代码,还是你手动操作。索引永不陈旧,无需重跑任何命令。

卸载

codegraph uninstall

一条命令从所有已配置的 Agent 中移除 CodeGraph,并移除 CLI 本身(所有安装形态:独立 bundle、npm 全局包、launcher 链接),删除前会先展示。--keep-cli 只移除 Agent 配置、保留 CLI。该命令反向执行安装器——剥离每个 Agent 中的 MCP 配置、指令小节与权限;项目索引 .codegraph/ 不受影响,按项目用 codegraph uninit 清理。--target 指定特定 Agent,--yes 非交互执行。

三、工作原理:抽取、存储、解析、自动同步

┌───────────────────────────────────────────────────────────────────┐
│                            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          │
└───────────────────────────────────────────────────────────────────┘

四个阶段:

  1. Extraction(抽取)——原生 Rust 内核用内置的 tree-sitter 语法解析源码,为 20 种语言抽取节点(函数、类、方法)与边(调用、导入、继承、实现);其余语言及按文件回退时使用可移植引擎执行同一套抽取逻辑,产出的图完全一致。
  2. Storage(存储)——全部进入本地 SQLite 数据库(.codegraph/codegraph.db),并启用 FTS5 全文检索。
  3. Resolution(解析)——抽取之后解析引用:函数调用 → 定义、import → 源文件、类继承,以及框架特定模式。
  4. Auto-Sync(自动同步)——MCP server 通过原生 OS 文件事件监视项目,变更经去抖(2 秒静默窗口)、过滤到源码文件后增量同步,无需任何配置。

底层数据模型(源码佐证)

README.md 描述的"SQLite 知识图谱"在 src/db/schema.sql 中落成四张核心表:

  • nodes——代码符号(函数、类、变量等):含 kindnamequalified_namefile_pathlanguage、起止行列、docstring、签名、可见性、is_exported/is_async/is_static/is_abstract 标志、装饰器与类型参数(JSON 数组)。
  • edges——节点间关系:source/target 外键、kindmetadata(JSON)、line/colprovenance(合成边的来源标记)。边有唯一性约束 idx_edges_identity ON edges(source, target, kind, IFNULL(line,-1), IFNULL(col,-1))——schema 注释说明这是为了防止多轮抽取产生字节级重复边而虚增 callers/impact 计数。
  • files——被跟踪的源文件:content_hashlanguagesizemodified_at,以及 generated 列——索引期判定文件是否为生成物(文件名约定如 *.pb.go,或文件头生成横幅),schema 注释解释了为何 Go 的生成约定是内容标记Code generated by ...),仅靠路径判断会漏判。
  • unresolved_refs——全量索引后待解析的引用,带 pending → failed 生命周期:解析失败的行被保留,等后续同步中某次文件变更引入可满足它的符号时重试(注释引用的 issue #1240)。

检索侧配套了三组索引设计:nodes_fts(FTS5 虚表,对 name/qualified_name/docstring/signature 建全文索引,由触发器与 nodes 表保持同步);name_segment_vocab(把符号名拆成小写词段,"OrderStateMachine" → order/state/machine,用于把自然语言提示词与图内符号做匹配);以及 (source, kind) / (target, kind) 复合索引——schema 注释特别指出刻意不建单独的 source/target 索引,因为复合索引的左前缀扫描已覆盖,窄索引只是写入负担。

四、Rust 内核与自适应资源调度

CodeGraph 的解析引擎是原生 Rust 内核(codegraph-kernel/ 目录,含 src/lib.rs 及各语言抽取模块如 tsjs/extractors.rsdart.rskotlin.rs):20 种语言——TypeScript、JavaScript、Java、Python、Go、C、C++、Rust、C#、Ruby、PHP、Swift、Kotlin、Scala、Dart、R、Lua、Luau(Metal 与 CUDA 走 C++ 路径)——在编译后的代码中解析,每个文件只有一次边界穿越。每种语言上线的前提是其在真实仓库上的图与参考引擎逐字节一致,从小型库到 Linux 内核;无预构建二进制的平台、含语法错误的文件会自动按文件回退,图结果相同。仓库内 scripts/kernel-parity.mjs__tests__/kernel-*-parity.test.ts 系列(如 kernel-csharp-parity.test.tskernel-dart-parity.test.ts)即对应这套一致性验证。

内核按所在机器自适应伸缩:worker 池、并行解析、分析缓存的大小来自系统的真实资源——真实核心数(容器/cgroup 感知,VPS 授予 2 核就按 2 核而非宿主 64 核调度)、macOS/Linux 上如实测量的可用内存,以及你的项目的解析成本实测值:

  • 工作站:完整并行管线——原生解析 worker、一旦划算就投入的多 worker 解析池、内存门控的分析缓存。Swift 编译器仓库(27k 个 Swift/C++ 文件)全量索引约 100 秒;单文件编辑重同步约 4 秒。
  • 2 核 / 6GB VPS:同一张图,来自一条以"完成"为目标的调优管线。Linux 内核(70k 文件、2M 符号、6.4M 关系)在 12 分钟内索引完成——而内存优先的设计跑不到 1% 就耗尽内存。
  • 第一天之后:保存文件到图谱更新远小于 1 秒——watcher 在单次保存后 300ms 触发,只同步变化的部分(4400 文件项目约 0.3s,27000 文件的 Swift 编译器仓库约 0.4s),从不重扫整棵树。

五、Benchmark:带图 vs 不带图的 Agent

README 的基准测试在 7 个真实开源代码库(跨 7 种语言)上,对比 Claude Code(headless)在 CodeGraph 时回答同一个架构问题,取每组 4 次运行的中位数。2026-08-05 在 Claude Opus 4.8 上用当前构建复测,且 harness 在两臂中都封锁 codegraph CLI(0/28 次对照组污染):

普适性收益——每个仓库、每个规模:工具调用少 88% · 快 53% · token 少 62% · 成本降 44% · 七个仓库文件读取全部归零。

代码库 语言 工具调用 耗时 文件读取 Token 成本
VS Code TypeScript · ~11k 文件 2 vs 28 2.2× 快(58s vs 2m10s) 0 vs 12 少 77% 省 71%
Excalidraw TypeScript · ~640 2 vs 43 3.6× 快(45s vs 2m42s) 0 vs 18 少 84% 省 78%
Django Python · ~3k 3 vs 14 快 35%(54s vs 1m23s) 0 vs 8.5 少 41% 省 13%¹
Tokio Rust · ~790 3 vs 29 2.6× 快(1m3s vs 2m43s) 0 vs 19 少 65% 省 64%
OkHttp Java · ~645 1 vs 6 快 43%(33s vs 58s) 0 vs 2 少 54% 省 21%
Gin Go · ~110 1 vs 7 快 39%(28s vs 46s) 0 vs 4 少 52% ≈持平¹
Alamofire Swift · ~110 4 vs 33 2.6× 快(54s vs 2m22s) 0 vs 16.5 少 59% 省 57%

¹ 成本跟随的是"问题需要多少发现工作"而非仓库大小:无图臂需要 28–43 次工具调用的仓库省 57–78%,而 14/7 次就到达答案的 Django/Gin 只省 13%/持平。有图臂在全部七个仓库上以 1–4 次 codegraph_explore 作答、零文件读取。

方法学要点(复现细节见 docs/benchmarks/,如 residual-context-occupancy.mdcodegraph-ab-matrix.md):

  • 每臂为 claude -p headless 运行,--strict-mcp-config:WITH = 启用 CodeGraph MCP server,WITHOUT = 空 MCP 配置;两臂都保留内置 Read/Grep/Bash;每仓库同一问题,每臂 4 次取中位。
  • 两臂均封锁 codegraph CLI(净化 PATH + PreToolUse hook 拒绝 Bash 调用该 CLI)。未封锁时对照组会经 Bash 摸到 CLI(28 次中 26 次),对照就失真了——CLI 调用不计为工具调用,其输出仍进入上下文。
  • 各仓库的问题均为架构类:"How does the extension host communicate with the main process?"(VS Code)、"How does Django's ORM build and execute a query from a QuerySet?"(Django)等。
  • README 同时诚实地标注了代价面:这些数字衡量的是吞吐(处理 token、工具调用、成本);在"会话结束后仍驻留上下文窗口的检索内容"这个维度上,CodeGraph 反而更多——多轮会话结束时约比读文件 Agent 多驻留 80%(VS Code 场景 67k vs 18k token)。机制相同:CodeGraph 一次返回稠密原文并留在窗口里,而 grep-read Agent 不断翻过小结果并被驱逐。小窗口长会话需为此预留预算。

六、语言支持:30+ 种,同一套完整待遇

每种受支持语言都获得同等处理——完整的结构化抽取与跨文件解析进入同一张图,无按语言单独配置。支持列表(扩展名 → 语言):

语言 扩展名 状态
TypeScript .ts, .tsx 完整支持
JavaScript .js, .jsx, .mjs 完整支持
ArkTS (HarmonyOS) .ets 完整支持:@Component/@ComponentV2 struct 与 ArkUI 装饰器(@State/@Prop/@Link/@Local/@Builder…)、build() 视图树(父→子组件边、链式属性到 @Extend/@Styles 的链接、.onClick(this.handler) 事件绑定)、状态→build() 重渲染的动态分派桥、@ohos.events.emitter emit→订阅配对(仅静态事件键)、router.pushUrl 字面 URL → 目标页 struct、ohpm 工作区裸导入解析
Python / Go / Rust / Java / C# / PHP / Ruby / C / C++ / Swift / Kotlin / Dart 各自标准扩展名 完整支持
Objective-C .m, .mm, .h 部分支持(类、协议、方法、@property#import、消息发送;.mm ObjC++ 可能解析不完整)
Metal .metal 完整支持(vertex/fragment/kernel 函数、struct、类型别名、调用边——MSL 按 C++ 解析,[[attribute]] 已处理)
CUDA .cu, .cuh 完整支持(<<<grid, block>>> 启动语法、模板启动、函数指针启动、dim3{...}、宏定义 kernel;CUDA in .h/.hpp 按内容识别)
Scala .scala, .sc 完整支持(类、trait、方法、类型别名、Scala 3 enum)
Svelte .svelte 完整支持(脚本抽取、Svelte 5 runes、SvelteKit 路由)
Vue .vue 完整支持(<script> + <script setup> 抽取、Nuxt 页面/API/中间件路由)
Astro .astro 完整支持(frontmatter + 脚本抽取、模板组件/调用引用、src/pages/ 路由)
Liquid .liquid 完整支持
Pascal / Delphi .pas, .dpr, .dpk, .lpr 完整支持(类、record、接口、enum、DFM/FMX 表单文件)
Lua / Luau .lua / .luau 完整支持(函数、receiver 方法、local 变量、require 导入、调用边;Luau 另有 type/export type 别名、类型签名、Roblox 实例路径 require
R .R, .r 完整支持(各种赋值形式的函数、S4/R5/R6 类、library/require 导入、source() 文件引用、调用边)
CFML .cfc, .cfm, .cfs 完整支持(<cfcomponent>/<cffunction> 标签式与裸脚本式组件、extends/implements<cfscript> 委托)
COBOL .cbl, .cob, .cpy 完整支持(program、section/paragraph 及 PERFORM/GO TO 边、CALL 'literal' 跨程序调用、COPY 副本(含独立 .cpy)、DATA DIVISION 记录/字段/88 级、EXEC CICS LINK/XCTL 与 EXEC SQL INCLUDE 目标;定长与自由格式)
Visual Basic .NET .vb 完整支持(类、Module、接口、结构、enum、属性、事件、Declare P/Invoke、Handles/WithEventsInherits/Implements 边、As New 实例化、LINQ、Unicode 标识符)
Erlang .erl, .hrl, .escript, .app.src, .app 完整支持(多子句/多 arity 函数、-spec、record、-type/-opaque-define-include/-import 边、本地与 mod:fn 远程调用、fun name/arity 引用、spawn/apply/proc_lib/timer/rpc 的 MFA 参数调用边、gen_server:call/cast(?MODULE) → 自身 handle_call/handle_cast 链接、-behaviour 链接)
Solidity .sol 完整支持(合约、库、接口、struct、enum、modifier、event、error、状态变量、import/usingemit/revert 调用)
Terraform / OpenTofu .tf, .tfvars, .tofu 完整支持(resource、data source、module、变量、输出、provider(含别名)、localsvar./local./module./资源引用并强制 Terraform 的按目录作用域;模块调用跨边界桥接;cloudposse/atmos 静态命名的 remote-state 跨组件接线;provider = aws.east 沿模块树向上解析;moved/import/removed/check 块引用)
Nix .nix 完整支持(简单/解构/柯里化参数函数、let/attrset 绑定、inheritimport ./path 文件边(./dirdefault.nix 解析)、NixOS 模块 imports 列表与 callPackage 文件边、NixOS 模块系统 option 接线——配置写入可链接到声明该 option 的模块)

语言抽取器实现在 src/extraction/languages/(每个语言一个文件,如 arkts.tscobol.ts),扩展名到语言的内置映射在 src/extraction/grammars.ts

实测跨文件覆盖率

Impact 与爆炸半径查询的质量取决于背后的依赖图,因此覆盖率是测量出来的:Fair coverage = 至少有一个已解析的跨文件依赖者(import、call、reference 或框架约定路由)的"含符号源文件"占比,逐语言在一个真实基准仓库上测得:

语言 基准仓库 覆盖率
TypeScript / JavaScript 本仓库 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%。残余永远是真实的静态分析前沿(运行时动态分派、反射/DI 容器、框架约定入口、vendored 三方代码),不以操纵分母方式掩盖。

七、框架感知路由(Framework-aware Routes)

CodeGraph 识别 Web 框架路由文件,发出 route 节点并经 references 边链接到处理函数/类——查询某个 view/controller 的调用者时,绑定它的 URL 模式会一并浮现。实现在 src/resolution/frameworks/(如 laravel.tsnestjs.tsdrupal.ts):

框架 识别形态
Django urls.py 中的 path()/re_path()/url()/include()(CBV .as_view()、点分路径)
Flask @app.route('/path', methods=[...])、蓝图路由
FastAPI @app.get(...)@router.post(...),所有标准方法
Express app.get(...)router.post(...) 及中间件链
NestJS @Controller + @Get/@Post/...、GraphQL @Resolver + @Query/@Mutation@MessagePattern/@EventPattern@SubscribeMessage
Laravel Route::get()Route::resource()Controller@action、元组语法
Drupal *.routing.yml 路由(_controller_form、实体处理器);.module/.theme/.install/.inc 中的 hook_*
Rails get '/x', to: 'users#index'、hash-rocket => 语法
Spring 方法上的 @GetMapping@PostMapping@RequestMapping
Play conf/routes 中的 GET/POST/… 动词路由 → Controller.method action(Scala + Java)
Gin / chi / gorilla / mux r.GET(...)router.HandleFunc(...)
Axum / actix / Rocket .route("/x", get(handler))
ASP.NET action 方法上的 [HttpGet("/x")] 特性
Vapor app.get("x", use: handler)
React Router / SvelteKit 路由组件节点
Vue Router / Nuxt pages/ 文件式路由、server/api/ 端点、路由中间件
Astro src/pages/ 文件式路由(.astro 页面 + .ts 端点,[param]/[...rest] 语法)

八、混合 iOS / React Native / Expo 的跨语言桥接

真实 iOS 与 React Native 代码库横跨多种语言:Swift 调用者发起一个被自动桥接的 ObjC selector,JS 文件经 React Native 桥调用原生模块,JSX 组件委托给原生 view manager。纯静态 tree-sitter 抽取会在每个语言边界停下。CodeGraph 把这些边界桥接起来,让 codegraph_explore 的调用路径与爆炸半径跨过边界而不是终止于边界:

边界 JS / Swift 侧 原生侧 机制
Swift → ObjC Swift obj.foo(bar:) ObjC selector -fooWithBar: @objc 自动桥接规则(含 init/property/protocol 形态)+ Cocoa 前置词前缀(With/For/By/In/On/At/…)
ObjC → Swift ObjC [obj fooWithBar:] Swift @objc func foo(bar:) 反向桥接名候选;从源码验证 @objc 暴露
RN legacy bridge JS NativeModules.X.fn(...) ObjC RCT_EXPORT_METHOD/RCT_REMAP_METHOD · Java/Kotlin @ReactMethod 解析宏/注解声明构建 JS 名 → 原生方法映射
RN TurboModules JS import M from './NativeM'; M.fn(...) 匹配 Codegen spec 的原生实现 Native<X>.ts spec 接口为 ground truth
RN native → 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 view 组件 JSX <MyView prop={v}/> TS Codegen spec + 原生实现类 spec → component 节点;约定式名称+后缀查找(View/ComponentView/Manager/ViewManager)桥到原生
Legacy Paper view manager JSX <MyView prop={v}/> ObjC RCT_EXPORT_VIEW_PROPERTY · Java/Kotlin @ReactProp 同 Fabric——Paper 时代声明同样产出 component + property 节点

每个桥发出的边都带 provenance:'heuristic' 标签与 metadata.synthesizedBy: 稳定通道名(如 swift-objc-bridgern-event-channelfabric-native-implexpo-module-extract),Agent 一眼就能看出某次跳转是怎么进入图的。edges 表中的 provenance 列与 idx_edges_provenance 索引(见 src/db/schema.sql)即承载这一机制;桥接实现位于 src/resolution/swift-objc-bridge.tssrc/resolution/frameworks/expo-modules.tssrc/resolution/frameworks/react-native.ts 等,测试见 swift-objc-bridge.test.tsrn-event-channel.test.ts

九、CLI 完整参考

codegraph                         # 运行交互安装器
codegraph install                 # 运行安装器(显式)
codegraph uninstall               # 从 Agent 移除 CodeGraph 并移除 CLI(--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                    # 管理后台 daemon——选一个停止(别名 daemons)
codegraph telemetry [on|off]      # 查看或修改匿名使用遥测
codegraph upgrade [version]       # 更新到最新发行版(--check, --force)
codegraph version                 # 打印已安装版本(-v, --version)
codegraph help [command]          # 显示帮助,可针对单个命令

codegraph affected

沿 import 依赖传递地追踪,找出被修改的源文件会影响哪些测试文件:

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 从 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

install 命令的脚本化参数:

codegraph install --yes                              # 自动检测 Agent,全局安装
codegraph install --yes --init                       # 同左,接线后顺带构建当前项目索引(一次性引导)
codegraph install --target=cursor,claude --yes       # 显式目标列表
codegraph install --target=auto --location=local     # 检测到的 Agent,项目本地
codegraph install --target=copilot-vscode,copilot-cli,copilot-jetbrains --yes  # Copilot 全形态
codegraph install --print-config codex               # 只打印配置片段,不写文件
codegraph install --print-config copilot-vscode      # 同上,VS Code Copilot
Flag 取值 默认
--target autoallnone 或 csv(claude,cursor,... 提示
--location globallocal 提示
--yes (布尔) 每步提示
--init (布尔)接线后在当前目录跑 codegraph init
--no-permissions (布尔)跳过 Claude 自动允许列表 开启权限
--print-config <id> 打印单个 Agent 的配置片段并退出

十、MCP 工具:单工具设计

作为 MCP server 运行时,CodeGraph 只暴露一个工具——codegraph_explore。实测的 Agent 行为表明:一个强工具比一组窄工具的引导效果更好——更少误选,且每个会话都省上下文。

工具 用途
codegraph_explore 一次调用回答几乎任何问题——"how does X work"、一条流("how does X reach Y")、或巡视一个区域——返回相关符号按文件分组的逐字源码,加上它们之间的调用路径与爆炸半径摘要。浮现 grep 无法跟随的动态分派跳转(回调、React 重渲染、接口→实现)。在查询中指明文件或符号名,即可读取其当前带行号源码——与 Read 工具相同的形状。

其余工具(codegraph_nodecodegraph_searchcodegraph_callerscodegraph_calleescodegraph_impactcodegraph_filescodegraph_status)保持完全可用但默认不列出——它们返回的一切已经内联在 codegraph_explore 里(其爆炸半径小节、关系图、符号体作为其 callee 列表)。源码印证:src/mcp/tools.tsDEFAULT_MCP_TOOLS = new Set(['explore']),即默认工具面只有 explore。需要把它们加回 MCP 面时,用环境变量 CODEGRAPH_MCP_TOOLS(如 CODEGRAPH_MCP_TOOLS=explore,node,search,callers),或使用对应 CLI 命令(codegraph node / query / callers / callees / impact / files / status)。

工程细节(源码级)

  • 使用指引经 MCP initialize 响应自动送达 Agent:src/mcp/server-instructions.ts 是唯一事实源,指示 Agent"直接用 CodeGraph 回答结构性问题、把返回源码视为已读、不要用 grep 复核、编辑后看陈旧横幅";根无索引时改发 SERVER_INSTRUCTIONS_NO_ROOT_INDEX 变体,提示用 projectPath 按项目查询。
  • 即使 server 自身根目录没有 .codegraph/ 索引,工具仍可用:传 projectPath 查询任意已索引项目(monorepo 中只索引了部分服务的子服务、或第二个仓库)。无索引路径返回干净的"改用内置工具"指引——工具层用 NotIndexedError 一类"可恢复的拒绝"转成成功形态的引导响应而非 isError: true(避免 Agent 学到"工具坏了"而整个会话放弃调用),见 src/mcp/tools.ts
  • 输入输出有硬性预算:查询类自由文本上限 10,000 字符、路径类上限 4,096 字符、响应输出上限 15,000 字符(防止恶意/异常客户端灌爆 FTS 扫描与上下文)。

十一、作为库嵌入

npm 包重新导出其程序化 API,importrequire 都能在你的进程内解析出 CodeGraph 类——适合嵌入应用(如 Electron 主进程):

import CodeGraph from '@colbymchenry/codegraph';
// CommonJS 亦可:
//   const { CodeGraph } = require('@colbymchenry/codegraph');

const cg = await CodeGraph.init('/path/to/project');
// 或: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();   // 文件变更自动同步
cg.unwatch(); // 停止监视
cg.close();

更底层的构件也从同一入口导出,供直接驱动图的调用方使用:DatabaseConnectionQueryBuildergetDatabasePathinitGrammars / loadGrammarsForLanguagesFileLock

嵌入前提

  • 从 npm 安装(npm i @colbymchenry/codegraph),以便匹配平台的 per-platform 包(携带编译好的库及其依赖)与 shim 一并被拉取;
  • API 跑在你的运行时上,需要 Node 22.5+ 以使用内置 node:sqlite(Electron 自带 Node 满足 22.5+ 即可)。CLI 与 MCP server 不受此限——它们跑在自包含的 bundle 运行时上;
  • 类型随包提供。与其他 Node 库一样,保持 @types/node 可用且 skipLibCheck: true(常见默认)。

十二、配置体系:零配置默认 + 一个可选文件

CodeGraph 默认零配置——无需编写或维护任何东西即可起步;语言支持从文件扩展名自动生效。唯一的可选文件是 codegraph.json,用于映射自定义文件扩展名与索引策略。其解析与校验实现在 src/project-config.ts,按项目根缓存、逐条容错(坏条目告警跳过、绝不致命;无配置文件即完全默认行为)。

开箱即跳过的内容

  • 依赖、构建与缓存目录——node_modulesvendordistbuildtarget.venvPods.next 等,覆盖所有受支持栈——即使没有 .gitignore 也生效,保证图里是你的代码而非三方噪声;
  • .gitignore 里的一切——git 仓库中经 git 遵循,非 git 项目则直接读 .gitignore(根与嵌套);
  • 大于 1 MB 的文件——生成 bundle、压缩 JS、vendored 大块文件。

要把别的东西排除,加进 .gitignore;要把默认排除的目录拉回索引(比如确实想索引某个 vendored 依赖),用 gitignore 否定语法 !vendor/——默认规则统一适用,提交依赖/构建目录不会把它强塞进图,.gitignore 否定是显式选择。

.gitignore 无法丢弃你已提交的目录。对于 checked-in 的 vendored 主题/SDK(如 static/ 下的 Metronic 主题),在 codegraph.jsonexclude 下列出——gitignore 风格模式、对仓库根相对路径匹配、在 index/sync/watch 全程生效:

{
  "exclude": ["static/", "**/vendor/**"]
}

反过来,当真实源码被刻意 gitignore(项目位于第二 VCS——SVN、Perforce——下且 .gitignore 了自己的源码以免入 Git),用 include 强制拉回(includeIgnored 只复活内嵌 git 仓库,不复活普通源码):

{
  "include": ["Tools/", "Local/typescript/"]
}

CodeGraph 从磁盘发现这些文件并覆盖 .gitignore(index/sync/watch 全程)。显式 exclude 仍然胜出,内置跳过目录(node_modulesdist.git)永不复活。

有时某目录不该离开索引(仍要能在里面搜到东西),只是不该压过你的真实代码——scripts/optional-skills/ 下通用命名的辅助函数(usagestatusrun)可能在精确名匹配上赢过真正回答查询的产品代码。把这些树列入 deprioritize

{
  "deprioritize": ["optional-skills/", "scripts/"]
}

它是 exclude排序对偶:路径留在索引中、可直接搜到,只是不再赢过一方代码;作用于 query/searchexplore 的排序。它不是过滤器——与内置的 example/sample/fixture/benchmark/demo/ 处理(那些会把文件直接从某些结果集中丢弃)不同,deprioritize 只改变名次。想让东西彻底消失请用 excludesrc/project-config.ts 中的接口注释把四个字段概括为:extensions(扩展名映射)、includeIgnored(复活内嵌 git 仓库的显式 opt-in)、exclude(召回杆——内容彻底离索引)、include(反向白名单)、deprioritize(相关度杆——内容保留,只是不再赢)。

自定义文件扩展名

项目若用非标准扩展名承载受支持语言(如 Lua 的 .dota_lua、PHP 的 .tpl),这些文件默认被跳过,因为扩展名不在 CodeGraph 的识别表内。在项目根用 codegraph.json 映射:

{
  "extensions": {
    ".dota_lua": "lua",
    ".tpl": "php"
  }
}

每个取值是受支持的语言 id。用户映射叠加在内置默认之上且冲突时胜出,因此也可以重指内置扩展名(如 ".h": "cpp")。把文件提交进版本库即可与团队共享。拼错的语言或格式坏的文件只会被警告并跳过——绝不破坏索引;无 codegraph.json 的项目行为与从前完全一致。新增或修改映射后重新索引(codegraph index)。

十三、自动同步的三层机制——为什么不用手动 codegraph sync

Agent 启动 codegraph serve --mcp 后,三层保证索引与代码同步,并确保在"编辑到下次同步"的短暂窗口里 Agent 绝不会拿到静默的错误答案:

  1. 带去抖自动同步的文件 watcher。 原生 FSEvents / inotify / ReadDirectoryChangesW watcher 捕获每个源文件的创建/修改/删除,去抖窗口后触发重索引(默认 2000ms,可用 CODEGRAPH_WATCH_DEBOUNCE_MS 调节,钳制在 [100ms, 60s]——解析与钳制逻辑在 src/mcp/engine.ts 附近)。编辑爆发合并为单次同步。
  2. 逐文件陈旧横幅。 去抖窗口内,若 MCP 工具响应将引用尚待同步的文件,响应头部会加 ⚠️ 横幅点名该文件并告知 Agent 直接 Read 它;未被响应引用的待处理文件则以小 footer 形式呈现。无论如何,Agent 都拿到显式信号——已在 Claude Code 上验证,Agent 会明确说"Reading the file directly for the live content"再去打开。
  3. 连接时追赶(catch-up)。 MCP server(重)连接时,先对工作树做一次快速的 (size, mtime) + 内容哈希对账再回答第一个查询——于是没有任何 MCP server 运行时发生的编辑(终端里的 git pull、另一个编辑器的改动、上一次已退出的 Agent 会话)会在下一会话的第一次工具调用中被吸收。
agent writes src/Widget.ts
  → watcher fires (<100ms)
  → debounce (default 2s)
  → sync; Widget.ts is in the index
  → next agent query sees it

随时可用 codegraph status(CLI)验证;若有待处理项,会看到 ### Pending sync: 小节列出文件及其编辑时长。

确需手动 codegraph sync 的少数场景:watcher 被禁用(沙箱环境,或 CODEGRAPH_NO_DAEMON=1),或你在 Agent 会话之外脚本化操作索引、想在脚本开头做一次 pre-flight 同步。

十四、遥测:字段白名单与关闭方式

CodeGraph 收集匿名使用统计——哪些工具/命令被用、哪些语言被索引——用于决定语言与 Agent 支持工作的优先级。永不收集代码、路径、文件/符号名、查询或 IP;使用数据先在本机聚合成每日总量再发送,ingest 端点是本仓库内的公开代码telemetry-worker/,含 migrations/0001_init.sql),强制执行文档化的字段白名单。安装器会事先询问;随时关闭:

codegraph telemetry off    # 或:CODEGRAPH_TELEMETRY=0,或 DO_NOT_TRACK=1

TELEMETRY.md 列出每个字段的完整清单:四类事件(installindexusage_rollupuninstall)加统一信封(随机 machine_id、版本、os/arch、node 大版本、CI 标志、schema 版本)。"off 就是 off":禁用时不记录、不建立连接、不发送任何"已退出"信号。另外,MCP server 每天至多一次在后台检查新版发布(只取版本号);DO_NOT_TRACK=1 同时禁用该检查,单独关闭用 CODEGRAPH_NO_UPDATE_CHECK=1

十五、验证过的发行版与平台

验证发行版:每个构件都由公开的 Release workflow 构建并发布——绝不来自某台笔记本——且带加密证明:

  • npm 包经 trusted publishing(OIDC——不存在可被盗的长生命周期 npm token)发布,并附 provenance 声明,把每个版本链接到构建它的确切 commit 与 workflow run。校验已装内容:npm audit signatures
  • GitHub Release bundle(及 SHA256SUMS)带签名的构建证明(SLSA v1.0 Build Level 2)。校验任意下载的 bundle:gh attestation verify codegraph-darwin-arm64.tar.gz -R colbymchenry/codegraph

2026 年 7 月之前发布的版本早于该管线,不带证明。

支持平台:每个发行版对三大桌面 OS 的 Intel/AMD(x64)与 ARM(arm64)都提供自包含构建(内嵌 Node 运行时——无需编译):

平台 架构 安装方式
Windows x64, arm64 PowerShell 安装器或 npm
macOS x64, arm64 shell 安装器或 npm
Linux x64, arm64 shell 安装器或 npm

支持 Agent:交互安装器自动检测并配置——Claude Code、Cursor、Codex CLI、opencode、Hermes Agent、Gemini CLI、Antigravity IDE、Kiro、GitHub Copilot(copilot-vscodecopilot-clicopilot-jetbrains 三个目标)。

十六、Troubleshooting(官方排障清单)

  • "CodeGraph not initialized"——先在项目目录运行 codegraph init
  • 索引慢——确认 node_modules 等大型目录被排除;用 --quiet 降低输出开销。
  • MCP 报 database is locked——当前构建不应出现:CodeGraph 自带 Node 运行时并使用内置 node:sqlite 的 WAL 模式,并发读永不阻塞写者。仍遇到时:处于旧版(<0.9)安装——重装获取 bundle 运行时;或 codegraph status 显示 Journal: 不是 wal——WAL 无法在该文件系统启用(网络共享与 WSL2 /mnt 常见),把项目(连同 .codegraph/)移到本地磁盘。
  • MCP server 连不上——Agent 自己启动 server,无需手动拉起。确认项目已初始化并索引(codegraph status)、MCP 配置中的路径正确;仍失败则重跑 codegraph install 重写配置。
  • codegraph status/sync 正常但 MCP 工具调用报 Transport closed——几乎都是 WSL2 且项目位于 Windows 盘(/mnt/c 路径),此时跨会话共享后台 server 的本地 socket 不可靠。CodeGraph 现在会回退到进程内服务该会话而非断连;仍遇到就在 MCP server 环境中设 CODEGRAPH_NO_DAEMON=1(每个会话独立进程);把项目移到 Linux 原生文件系统(如 ~/ 下)可恢复共享 server。
  • 符号缺失——MCP server 保存时自动同步(等几秒);必要时手动 codegraph sync。检查文件语言是否受支持、是否位于 .gitignore 或默认排除目录(node_modulesdist)内。
  • Windows 与 WSL 共享同一 checkout——不要让两边指向同一个 .codegraph/:后台 server 锁与 SQLite 索引都绑定写它们的 OS,SQLite 锁在 WSL2/Windows 文件系统边界上不可靠。给一侧设 CODEGRAPH_DIR 为不同名称(如 Windows 上 CODEGRAPH_DIR=.codegraph-win,WSL 留在默认 .codegraph)让两边各持一份索引;CodeGraph 索引与监视时会跳过兄弟的 .codegraph-* 目录,互不干扰。
  • 超大仓库(数十万文件)或 .codegraph/codegraph.db-wal 很大——-wal 是 SQLite 预写日志:等待折叠进 codegraph.db 的写。构建大索引时 CodeGraph 允许它按索引比例增长(软阈值 = 256 MB 与索引大小四分之一中的较大者,上限 2 GB)再折叠回来,因为折叠太频繁才是大索引在普通磁盘上变慢的元凶。静止时裁剪到 64 MB;被杀会话留下的残留在下次打开项目时折叠+裁剪——索引本身无大小上限。两个环境变量可调:CODEGRAPH_WAL_VALVE_MB(索引期软阈值)与 CODEGRAPH_WAL_HEAL_MB(静止尺寸与裁剪阈值);CODEGRAPH_WAL_VALVE_DEBUG=1 把每次决策打印到 stderr。WAL 阀实现见 src/db/wal-valve.ts,测试见 wal-deferral.test.tswal-heal.test.ts

十七、适用前提与限制

  • 当前仓库版本为 1.6.0(见 package.json),运行环境要求 Node 20–24(dev 侧);嵌入 API 要求 Node 22.5+(node:sqlite),CLI/MCP 则使用自包含运行时不受限;
  • 索引滞后文件写入约 1 秒;跨文件解析是尽力而为的名称匹配,歧义调用可能返回多个候选;
  • CodeGraph 不做正确性验证——那是 TypeScript 编译器/测试套件/linter 的职责,它提供的是它们没有的结构上下文;
  • 小窗口长会话需为驻留的稠密上下文预留预算(见第五节"代价面"说明);
  • 许可:MIT(LICENSE)。

十八、延伸阅读(仓库内路径)

登录后查看全文
热门项目推荐
相关项目推荐