escoffier-labs/graphtrail

GitHub: escoffier-labs/graphtrail

一个用 Rust 编写的本地代码图工具,将仓库的符号与调用关系索引到 SQLite,通过 CLI 和只读 MCP server 为 AI 编程 agent 提供结构化的调用者、被调用者、影响分析和上下文查询。

Stars: 2 | Forks: 0

GraphTrail banner

GraphTrail

一个本地代码图 sidecar,它将你的 repo 映射为由符号、import 和 call 边组成的 SQLite 图,然后通过 CLI 和只读的 MCP server 回答调用者、被调用者、影响和上下文的问题。它是你的 AI agent 在编辑前阅读的资料,因此修改始于 call graph 而非猜测。与 grep 或 embedding 索引不同,它遍历真实的 tree-sitter call 边,保持只读,运行时无需 daemon 且无需网络。

网站 → graphtrail.escoffierlabs.dev

CI status Crate version 0.2.0 MIT license MCP server

GraphTrail 仅对代码进行一次索引,此后保持增量更新,并在 agent 修改任何代码行之前回答结构性问题。

Recording: graphtrail init and sync build a code graph, then callers and context answer structural questions before an edit

graphtrail initsync 索引 repo,然后 callerscontext 直接从代码图中获取答案。

索引一个 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技术, 代码分析, 代码图谱, 凭证管理, 可视化界面, 开发工具, 网络流量审计, 通知系统