跳到正文

产品 02 · 确定性代码知识图谱

CodeGraph

tree-sitter → SQLite + FTS5 · CLI + MCP · 无模型

一份索引,三个入口。 tree-sitter 把仓库解析成项目级的符号、调用与依赖索引,再针对它回答结构性问题:谁调用了这个函数、它能到达什么、改动它会牵连到哪里。这些答案来自一次完整的语法树解析,不是文本匹配的猜测,也不来自任何模型。

前提

里面没有模型,所以输出是可复现的字节

这不是省下来的一个功能,而是整件事成立的前提。二进制里不含 embedding、不含向量索引、不含 LLM 调用,因此同一个仓库、同一个问题,在你的笔记本、同事的机器和 CI runner 上返回完全相同的字节。可复现,才谈得上下面这三件事:

  1. 01交给编码 Agent 时,它拿到的是事实而不是一次采样;同一轮对话里问两次不会得到两个答案。
  2. 02放进 CI 里可以 diff —— 影响半径变了就是代码结构变了,而不是模型今天心情不同。
  3. 03出错时可以复现。一个确定性的管道,bug 有唯一的重现路径。

01

它解决什么问题

"改这个函数会碰到哪些地方" 这类问题,grep 答不了。grep 认字符串,不认调用关系:同名的方法、被重新导出的符号、经由 trait 或接口分发的调用,它一律看不见;反过来,注释和字符串里的同名文本它又一定会报出来。于是你回到人工翻文件,一层层往上追调用者,直到自己觉得追干净了 —— 这个"觉得"就是回归 bug 的来源。CodeGraph 把这层结构预先算好、落盘,然后用一次查询回答它。

  • 01

    在陌生仓库里改代码的人

    接手一个几十万行的项目,需要在动手之前知道这个符号被谁用着、改了会波及哪里。先看半径,再决定改法。

  • 02

    编码 Agent

    一次结构化查询就拿到相关符号的源码和它们之间的调用路径,替代几十轮 grep 加读文件 —— 上下文更准,token 更少,来回更短。这也是 MCP 入口存在的原因。

  • 03

    编辑器与 IDE

    通过本机 HTTP 接同一份索引,不必各自再实现一套跨文件解析。远程开发场景下 HTTP 也是唯一可靠的通道。

  • 04

    CI 与代码评审

    一次改动的影响半径可以被算出来、被 diff、被写进评审意见。确定性输出让"这次变更比上次多牵连了三个模块"成为一句可以验证的话。

02

它怎么工作

四个阶段,没有一步需要联网,也没有一步会把你的代码发出去。索引写在仓库自己的 .codegraph/ 目录里。

  1. 01

    解析

    tree-sitter 按语言逐文件构建语法树,提取符号定义、调用点与文件间依赖,并做跨文件符号解析 —— 这一步决定了后面所有答案的精度。

  2. 02

    落盘

    结果写进项目级的 SQLite 数据库,全文检索由 FTS5 承担。SQLite 静态链接进二进制,机器上不需要预装任何系统库。

  3. 03

    查询

    符号搜索、调用者、被调用者、依赖、变更影响半径,以及按 PageRank 中心度排序的全图导出。查询走索引,是亚毫秒级的读,不是重新扫一遍仓库。

  4. 04

    跟随

    后台守护进程监听文件变化(2 秒防抖)并增量更新索引,落后写入约一秒。同一个项目的多个客户端 —— 终端标签页、Agent、编辑器 —— 共用这一个守护进程;全部断开且空闲超时后它自行退出。

03

三个入口,同一份索引

索引只建一次。人、Agent 和编辑器分别从最顺手的那个口子进来,看到的是同一份数据,不存在"CLI 的答案和 Agent 的答案不一致"这种情况。

  • 01

    CLI

    给人用

    $ codegraph query "<symbol>" -p .

    基于 Clap 的子命令集:init、index、sync、query、files、status、callers、callees、impact、affected、check、export、unlock,外加 bash / zsh / fish / powershell / elvish 的补全安装。

  • 02

    MCP over stdio

    给编码 Agent

    $ codegraph serve --mcp

    标准 MCP stdio 服务。codegraph install --yes 会自动探测已安装的 Agent 与 IDE 并写好配置;codegraph skill install 还能把使用说明作为 Skill 装进它们各自的技能目录。

  • 03

    MCP over HTTP

    给编辑器与远程开发

    $ codegraph serve --http

    默认只监听 127.0.0.1:8111,不对外暴露。codegraph http list 查看在跑的实例,codegraph http stop <addr> 停掉其中一个。SSH 远程开发时这是推荐通道。

04

能问它什么

同一个问题,命令行和 MCP 两侧是同一份实现,答案一致。

能问它什么
问题命令行MCP 工具
这个符号在哪里定义的?codegraph querycodegraph_search
这块代码是怎么工作的?codegraph exportcodegraph_explore
把它的源码和调用链一起给我codegraph query --jsoncodegraph_node
谁调用了它?codegraph callerscodegraph_callers
它调用了什么?codegraph calleescodegraph_callees
改动它会牵连到哪里?codegraph impactcodegraph_impact
这次改动影响了哪些文件?codegraph affected
索引建好了吗?codegraph statuscodegraph_status

impact 给出的是传递闭包,不是一层调用者 —— 这也是它和手工往上翻调用链最主要的差别。export 支持按 PageRank 中心度排序输出全图,用来找一个陌生仓库里真正的枢纽。

05

安装与上手

一键脚本会探测平台、下载对应的预编译二进制并放到 PATH 上 —— 不需要 Rust 工具链,也不需要等编译。它没有发布到 crates.io,所以从 crates 索引走的那条 cargo 安装路径找不到它;有 Rust 环境时,用下面的 --git 从源码装。

安装

# Linux 与 macOS

$ curl -fsSL https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.sh | sh

# Windows(PowerShell 5.1 及以上)

$ irm https://raw.githubusercontent.com/sunerpy/codegraph-rust/main/scripts/install.ps1 | iex

# 或从源码 —— 未发布到 crates.io

$ cargo install --git https://github.com/sunerpy/codegraph-rust codegraph-rs

上手

# 建索引,写进 ./.codegraph/

$ codegraph init && codegraph index

# 查一个符号

$ codegraph query "GraphTraverser" -p .

# 看改动它的影响半径

$ codegraph impact GraphTraverser

# 把 MCP 服务写进已安装的 Agent 配置

$ codegraph install --yes

设 CODEGRAPH_VERSION 可以钉住某个版本而不取最新。CI 里设 CODEGRAPH_NO_DAEMON=1 走前台模式;不想要文件监听就传 --no-watch。排除规则写在 .codegraph/config.toml 的 [indexing] exclude 下,自定义扩展名映射写在 .codegraph/codegraph.json。

06

语言支持

一共解析 38 种语言,但深度不一样,而深度才是有用的那个数字。下面三档是按提取深度分的,不要把它们合成一个"支持 38 种语言"。

第一档29完整符号提取
TypeScript · TSX · JavaScript · JSX · ArkTS · Python · Go · Rust · Java · C · C++ · C# · PHP · Ruby · Swift · Kotlin · Dart · Scala · Lua · Luau · Objective-C · R · Solidity · Nix · Terraform · Erlang · CFML · GDScript · Pascal
第二档6嵌入与模板提取
Vue · Svelte · Astro · Razor (.cshtml) · Liquid · XML / MyBatis mapper
第三档3仅到文件级
YAML · Twig · Properties

第二档的语言,符号来自宿主文件里嵌入的脚本与模板标记,粒度取决于该文件的写法。第三档只登记文件与文件间的关系,没有符号级的调用图。语言集合是固定的,不做启发式兜底 —— 一个文件要么在这套表里,要么不进图。

07

平台

六个预编译目标,发布产物命名为 codegraph-<version>-<target>.<ext>。Linux 走 musl 静态链接,不依赖 glibc,也不依赖系统 SQLite。

平台
平台架构目标三元组格式
Linuxx86_64(musl 静态)x86_64-unknown-linux-musl.tar.gz
Linuxaarch64(musl 静态)aarch64-unknown-linux-musl.tar.gz
macOSx86_64x86_64-apple-darwin.tar.gz
macOSaarch64(Apple Silicon)aarch64-apple-darwin.tar.gz
Windowsx86_64x86_64-pc-windows-msvc.zip
Windowsaarch64(ARM64)aarch64-pc-windows-msvc.zip

也可以直接从发布页下载压缩包,解压后把 codegraph 放到 PATH 上。

08

技术栈与存储

选型都是为了同一件事:单文件二进制、无外部依赖、输出可复现。

语言
Rust,Edition 2024。发布产物是单个可执行文件,不带运行时。
解析
tree-sitter,每种语言一套语法,加上跨文件符号解析。
存储
项目级 SQLite,全文检索用 FTS5。数据库静态链接进二进制,机器上不需要预装 SQLite。
索引位置
仓库内的 .codegraph/ —— codegraph.db 及其 WAL、config.toml、codegraph.json,守护进程的 pid / socket / 日志也在这里。
命令行
Clap 子命令,五种 shell 的补全脚本随二进制分发。
后台进程
按项目共享的守护进程,通过 Unix socket 通信,监听文件变化并增量更新;客户端全部断开且空闲超时后自行退出。
网络
索引与查询全程离线。HTTP 传输默认只绑 127.0.0.1。
许可
MIT。

09

它不做什么

写清边界比多列几条功能有用 —— 尤其是这类容易被误当成别的东西的工具。

  • 01

    不做相似度检索

    没有 embedding,没有向量库,问题不会被转成向量再找最近邻。它回答的是结构性问题,靠的是语法树里真实存在的边。想按"意思相近"找代码,这个工具帮不上。

  • 02

    不判断对错

    它告诉你调用关系和影响半径,不告诉你这段代码写得好不好、有没有 bug。类型检查交给编译器,风格交给 linter,正确性交给测试。

  • 03

    跨文件解析是尽力而为

    跨文件符号解析基于名字匹配,有歧义的调用会返回多个候选。动态分发、反射、运行时拼出来的调用,静态解析看不见。

  • 04

    索引不是实时的

    守护进程落后文件写入约一秒。刚改完立刻查,可能读到上一版;工具响应会标出处于陈旧状态的文件。

  • 05

    语言集合是固定的

    不在那 38 种里的语言不会被启发式地"尽量解析一下",而是直接不进图。这是明确的取舍:宁可少收,也不产出没有依据的边。

获取

在任意仓库里跑一次 init

预编译二进制、一键脚本、源码安装三条路都在下面。它是 MIT 许可的个人项目,issue 和 PR 都在同一个仓库里。