escoffier-labs/graphtrail
GitHub: escoffier-labs/graphtrail
一个用 Rust 编写的本地代码图工具,将仓库的符号与调用关系索引到 SQLite,通过 CLI 和只读 MCP server 为 AI 编程 agent 提供结构化的调用者、被调用者、影响分析和上下文查询。
Stars: 2 | Forks: 0
GraphTrail
一个本地代码图 sidecar,它将你的 repo 映射为由符号、import 和 call 边组成的 SQLite 图,然后通过 CLI 和只读的 MCP server 回答调用者、被调用者、影响和上下文的问题。它是你的 AI agent 在编辑前阅读的资料,因此修改始于 call graph 而非猜测。与 grep 或 embedding 索引不同,它遍历真实的 tree-sitter call 边,保持只读,运行时无需 daemon 且无需网络。
网站 → graphtrail.escoffierlabs.dev
GraphTrail 仅对代码进行一次索引,此后保持增量更新,并在 agent 修改任何代码行之前回答结构性问题。
graphtrail init 和 sync 索引 repo,然后 callers 和 context 直接从代码图中获取答案。
索引一个 repo,然后询问谁调用了某个符号,以及 agent 在编辑它之前应该加载什么上下文。`context` 包正是 agent 通过 MCP 获取的内容。
## 它的功能
GraphTrail 是一款专为 AI 编程 agent 和开发者设计的代码图导航工具。它通过 tree-sitter 在单次传递中解析每个源文件,提取符号(函数、类、方法)、import 和 call 边,并将它们写入位于 `.graphtrail/` 下的小型本地 SQLite 图中。基于该图,它能回答你在修改代码前会问的结构性问题:全文符号搜索、某个符号的调用者、其被调用者、修改带来的影响(爆炸半径),以及一个上下文包(汇集了入口点及其调用者和被调用者邻近关系,以供执行任务使用)。
它在同一个图上提供两种交互界面。一种是供人类和脚本使用的命令行界面,另一种是只读的 Model Context Protocol (MCP) server(`graphtrail-mcp`),它将相同的查询暴露为 agent 可调用的工具。该 MCP server 在每个连接时都开启 `SQLITE_OPEN_READ_ONLY`,因此它永远不会修改你的图,并且支持多 repo:一个运行中的 server 可以为你已索引的任何 repository 提供服务。它支持 Python、TypeScript/JavaScript、Rust 和 Go。完成索引后,它是只读的,不安装任何 hook,不启动 daemon,也不进行任何网络调用。
## 安装说明
GraphTrail 是一个 Rust crate,包含两个二进制文件:`graphtrail`(CLI)和 `graphtrail-mcp`(MCP server)。从 [crates.io](https://crates.io/crates/graphtrail) 安装这两个工具:
```
cargo install graphtrail
```
或者跟踪 repository 的最新提交:
```
cargo install --git https://github.com/escoffier-labs/graphtrail
```
或者通过克隆源码进行构建:
```
git clone https://github.com/escoffier-labs/graphtrail.git
cd graphtrail
cargo build --release # binaries land in target/release/
```
## 快速开始
索引一个 repository,然后向代码图询问结构性问题:
```
# 先进行一次全量 Index,随后增量保持最新。
graphtrail init /path/to/repo
graphtrail sync /path/to/repo # incremental: a no-op when nothing changed
graphtrail sync /path/to/repo --force # rebuild every file
# 对 repo 的 graph database 执行 Query。
DB=/path/to/repo/.graphtrail/graphtrail.db
graphtrail --db "$DB" search "handoff lint"
graphtrail --db "$DB" callers serve
graphtrail --db "$DB" callees serve
graphtrail --db "$DB" impact serve --depth 3
graphtrail --db "$DB" context "handoff lint" --json
graphtrail --db "$DB" stats --json
graphtrail --db "$DB" doctor /path/to/repo --json
```
当 sync 根目录位于 git repository 内时,`sync` 会遵循 `.gitignore` 文件和 `.git/info/exclude`,但如果未被忽略,仍会索引诸如 `.github` 之类的隐藏路径。即使被忽略的文件已被提交,它们也会被跳过,因为 GraphTrail 遵循忽略规则而不是 git status。
在依赖脚本或 agent 工作流中的图之前,请使用 `doctor`。它以只读方式打开数据库,检查 schema 的新鲜度、上次同步的时间间隔、待处理的新增/修改/删除/指纹失效的文件,并以状态码 0 表示 `FRESH`,1 表示 `STALE`,2 表示 `NEEDS-MIGRATION` 或数据库缺失。
针对 GraphTrail 自身被索引源码的一个真实 `callers` 查询:
```
$ graphtrail --db .graphtrail/graphtrail.db callers serve
main --calls@19 hops=1--> serve (src/bin/graphtrail-mcp.rs -> src/mcp.rs)
```
## MCP server
`graphtrail-mcp` 是一个只读的 MCP server,通过 stdio 使用换行符分隔的 JSON-RPC 2.0 进行通信。它没有异步 runtime,也没有额外的依赖,从而保持 sidecar 足够小巧。默认数据库来源于 `--db
`、`--db=`、`GRAPHTRAIL_DB` 环境变量或工作目录下的 `.graphtrail/graphtrail.db`。每个工具还接受一个可选的 `repo`(使用 `/.graphtrail/graphtrail.db`)或 `db`(显式路径)参数,因此单个运行中的 server 就可以为任何已索引的 repository 提供服务。数据库在每次调用时延迟打开,因此即使在默认 db 不存在的情况下,server 也能启动。
向 MCP 客户端注册它。对于 Claude Code,请添加到 `.mcp.json`(项目作用域)或 `~/.claude.json`(用户作用域)中:
```
{
"mcpServers": {
"graphtrail": {
"command": "/abs/path/to/graphtrail-mcp",
"args": ["--db", "/abs/path/to/repo/.graphtrail/graphtrail.db"]
}
}
}
```
### 工具
该 server 暴露了十个工具。此列表已根据 `graphtrail-mcp` 实时的 `tools/list` 响应进行了验证:
| 工具 | 必需参数 | 返回内容 |
|---|---|---|
| `search` | `query`(可选 `limit`,默认为 20;可选 `path`) | 根据名称对代码符号(函数、类、方法)进行全文搜索,可选择根据已索引的文件路径进行过滤。 |
| `callers` | `symbol`(可选 `depth`,默认为 1,范围限制在 1..5) | 调用指定符号的符号(传入的 call 边),每条边带有 `hops`。 |
| `callees` | `symbol`(可选 `depth`,默认为 1,范围限制在 1..5) | 被指定符号调用的符号(传出的 call 边),每条边带有 `hops`。 |
| `impact` | `symbol`(可选 `depth`,默认为 1,范围限制在 1..5) | 符号的调用者和被调用者的组合(变更的爆炸半径),每条边带有 `hops`。 |
| `context` | `task`(可选 `limit`,默认为 12) | 一个上下文包:匹配的入口点及其调用者/被调用者的邻近关系和相关文件。 |
| `stats` | 无 | 文件、符号、边、import、schema 版本、sync 元数据的计数,以及按语言分类的文件计数。 |
| `doctor` | 无 | 图的新鲜度契约:schema 状态、上次同步的时间间隔、待处理的文件更改、被忽略的条目,以及 `FRESH`/`STALE`/`NEEDS-MIGRATION` 判定结果。 |
| `file_neighbors` | `path` | 通过传入或传出 call 边连接到已索引文件的文件。 |
| `repos` | 无(可选 `roots`) | 默认数据库元数据,以及可选的对根目录下 `.graphtrail/graphtrail.db` 的一层扫描。 |
| `diff` | `before`, `after` | 两个已索引图数据库的结构化 diff:新增、删除、更改的符号,以及新增和删除的 call 边。 |
每个工具还额外接受一个可选的 `repo` 或 `db` 选择器以供多 repo 使用。
`doctor`、`repos` 和 `diff` 不接受 `refresh`;`doctor` 报告陈旧状态,并将刷新操作留给选择启用它的查询工具。
Call 边工具将每个方向的边数上限设定为 500 条真实边。当遍历达到上限时,JSON 数组将包含一行带有 `kind: "truncated"` 的最终记录。
一个真实的 `stats` 工具调用(该 server 首先索引了 GraphTrail 自身的源代码):
```
{
"edges": 168,
"files": 26,
"imports": 119,
"language_files": {
"go": 1,
"python": 3,
"rust": 18,
"typescript": 4
},
"schema_version": 2,
"symbols": 150,
"synced_at": "1783099401",
"tool_version": "0.2.0"
}
```
## 可选集成
GraphTrail 的 Brigade 适配器是内置的:`graphtrail context "" --markdown` 会将上下文包渲染成对 Brigade 友好 的 Markdown 文档,你可以直接将其放入 handoff 的证据部分。
另外两个适配器受限于可选的 cargo 特性,因此默认的二进制文件不包含网络和跨工具的依赖:
```
# 根据 graph context、Code Search 语义命中结果和 MiseLedger 证据,构建一份 context brief。
cargo run --features codesearch,miseledger -- \
--db context "rate limiting" --markdown --blend-code-search --evidence
# 将 Code Search embedding 命中结果与 graph centrality 相融合。
# 遵守 CODE_SEARCH_URL 和 CODE_SEARCH_API_KEY。
cargo run --features codesearch -- --db blend "rate limiting" --json
# 展示提及某个 symbol 或 term 的 MiseLedger 证据项(只读 FTS)。
# 遵守 MISELEDGER_DB(默认为 ~/.local/share/miseledger/miseledger.db)。
cargo run --features miseledger -- links "dispatch" --json
```
## 组件如何协作
GraphTrail 是一组专注工具中的一个小节点:
- **Code Search** 负责维护语义块、摘要和 embedding。
- **GraphTrail** 负责维护符号、import、call 边和图上下文。
- **MiseLedger** 负责维护 session、证据归档和 JSON receipt。
- **Brigade** 负责维护 operator 工作流、handoff、上下文包和 guardrail。
在内部,代码被拆分为专注的模块:`model`(共享类型)、`extractors`(按语言划分的 tree-sitter 提供程序及遍历)、`store`(`db`、`schema`、`sync`)、`query`(`search`、`graph`、`context`、`stats`),以及一个轻量级的 `cli`。
## 为什么不直接用 grep 或 embedding 索引?
- **grep / ripgrep** 只能查找文本,而不能查找结构。它们会显示名称出现的每一行,但不知道一个函数是否调用了另一个函数,因此无法回答“谁调用了这个”或“如果我修改它会破坏什么”。GraphTrail 遍历真实的 tree-sitter call 边并直接回答这些问题。
- **Embedding / 语义索引**(Code Search 保留的那种)非常适合“查找看起来与某个概念相关的代码”,但它是根据相似度而不是可达性进行排序的。它无法告诉你修改的爆炸半径。GraphTrail 是结构层;两者可以很好地组合,这正是可选的 `blend` 功能所做的。
- **语言服务器 (LSP)** 在编辑器内部提供精确的按语言导航,但它是一个有状态的 daemon,绑定到一个项目和一个进程,而不是 agent 可以通过 MCP 同时跨多个 repo 访问的可查询数据库。GraphTrail 将一个小型图持久化到磁盘,保持只读,不运行 daemon,并且可以通过单个 server 支持多 repo。
- **完整的代码智能平台**(图数据库、ctags server、托管索引器)功能更强大,但运行成本也高得多。GraphTrail 有意被设计为一个 sidecar:每个 repo 一个 SQLite 文件,无需网络,没有后台进程。
## GraphTrail 不包含什么
GraphTrail 是一个 sidecar,而不是一个平台。它不会:
- 运行 daemon,安装 hook 或监视你的文件系统
- 在默认构建中进行网络调用
- 掌管记忆、receipt、发布或调度(这些仍由 Brigade 和 MiseLedger 负责)
- 维护语义块、摘要或 embedding(由 Code Search 掌管)
- 在索引完成后修改你的代码或图(MCP server 在构建时就是只读的)
它将源代码索引到图中并回答结构性问题。这就是它全部的职责。
## 贡献
欢迎提交 Issue 和 Pull Request。有关本地开发环境配置及易于合入的修改,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md);如需私下报告漏洞,请参阅 [SECURITY.md](SECURITY.md);另请参阅 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)。GraphTrail 采用 MIT 许可证;请参阅 [LICENSE](LICENSE)。标签:AI编程助手, CLI, MCP服务器, Rust, SOC Prime, Tree-sitter, WiFi技术, 代码分析, 代码图谱, 凭证管理, 可视化界面, 开发工具, 网络流量审计, 通知系统