乐于分享
好东西不私藏

你的 AI 助手每天都在失忆,有人给它写了本"交接文档"

你的 AI 助手每天都在失忆,有人给它写了本"交接文档"

一个开源项目,让 Claude Code、Codex 们少走 46% 的弯路


想象一个每天失忆的天才同事

假设你的团队来了个新人。

他聪明得吓人,任何语言都会写,通宵不累,从不抱怨。唯一的问题是:他每天早上醒来都会忘光前一天的一切。

于是每天上班,他都要重新问一遍:

  • • "我们的登录逻辑写在哪儿?"
  • • "这个函数改了会影响谁?"
  • • "数据库那层是怎么连的?"

他翻遍全项目,画出一张心智地图,漂亮地干完活——然后下班,地图清零。

第二天,重来一遍。

听起来荒诞。但这几乎是当下每一个 AI 编程助手的真实工作方式。

没有地图的 AI:grep 一个词、打开一个文件、跟着 import 跳走、退回来、再试一次

你给 Claude Code 一个任务,它并不是"直接开工"。

它先要 grep 一个关键词,打开一个文件,顺着 import 跳到下一个,发现不对,退回来,再试一次。

这个过程会烧掉一次任务里大部分的工具调用、token 和等待时间——而这些成本,和你真正想解决的问题毫无关系。

更扎心的是三件事:

  • • 重复:每个新任务,探索成本从零再付一遍
  • • 丢弃:这一轮好不容易搞明白的结构,会话结束就蒸发
  • • 不共享:你的同事和他的 AI,还得从头再来一次

人类进一个新项目,只需要"上手"一次。AI 每一次都要重新上手。


Nanonets 的解法:把理解写下来,钉在代码库里

最近在 GitHub 上蹿升很快的开源项目 Graft(来自 Nanonets 团队,MIT 协议,目前 2.5k star、212 个 fork),针对的就是这件事。

最直观的感受,是官方这段左右分屏的对比演示——同一个任务、同一个模型、同一套文件工具,唯一的区别是右边接上了 Graft:

左边:从零开始翻找,一个文件接一个文件。右边:先读地图,直奔目标

左边那位在反复地 grep、打开、退回、再试,屏幕上滚过一大堆你并不关心的文件名;右边那位几乎没有"找"的过程,它一上来就知道该去哪儿。

这不是剪辑技巧带来的错觉。官方给出的一组硬指标是:工具调用少 46%、token 少 42%、耗时少 60%,而在 SWE-bench Verified 这个业界标准评测上,正确率反而从 54% 提到了 66%——更快、更省,而且更对。

这三件事同时成立,是相当反直觉的,也正是这个项目值得聊一聊的原因。

它的想法朴素得近乎"土":既然 AI 每次都要重新理解一遍代码库,那就让它只理解一次,然后把结果写成文件存下来。

不是向量数据库,不是 embedding,不是需要常驻的索引服务。就是一个文件夹,里面是一堆互相链接的 Markdown 文件——每个文件对应代码库里的一个子系统、一个 API 或一个概念。

用它自己的话说:"这个图谱就是一组你的 agent 可以打开、grep、跟着链接跳转的文件,和它读仓库里任何其他文件的方式完全一样。"

这句话是整个项目最聪明的地方。

它没有发明一套新协议、新数据库、新查询语言,而是选择了AI 本来就最擅长的载体:人话写的文本文件


一个"节点"里到底装了什么

大多数代码索引工具给你的是一个地址:"这个东西在那个文件的第 42 行。"

这告诉 AI 去哪儿找,但没告诉它会找到什么。

所以 AI 还是得打开源文件、从头读一遍。

Graft 的节点里塞的是意义,一个文件包含三层深度:

部分
装了什么
Summary(摘要)
用大白话讲清这段代码干什么——就像资深工程师带新人时会说的那样。哪怕这段代码从来没写过注释,摘要也在那儿
Crux(关键)
真正承载逻辑的那几行:判断条件、跳过条件、状态变更。原样摘出来内联存着,让 AI 直接看到"怎么做的"
Sources(来源)
这个节点是从哪些文件生成的,每个都带内容哈希——所以 Graft 能精确知道哪个节点过期了
Links(链接)
用 depends_onusesimplements 这类动词连接到其他节点,写成 [[双链]],AI 可以顺着跳
Notes(笔记)
你自己在下面写的任何东西,重新生成时会保留,永远不会被覆盖

有个细节特别值得说:Crux 存的是代码本身,不是行号。

因为行号会漂移——上面随便插几行无关代码,42 行就变成 47 行了。

但真正重要的那几行本身不会变。

存文本而不存数字,这个决定看似微小,却让整套东西在真实的、每天都在变的代码库里站得住脚。


上手只要两条命令

npm install -g @nanonets/graft   # 装 CLI,一次
graft init                       # 建图谱 + 接进 Claude Code

就这样。graft init 会问你要接哪些 agent(Claude Code、Cursor、Codex、Gemini、Copilot、Kiro、Windsurf 都支持),然后往对应的配置文件里写入接线。

从下一次会话开始,Graft 就自动随行:每次提问自动把相关节点塞进上下文,每次改完代码在后台自动重建图谱。

没有守护进程,没有需要记得去重跑的索引。

值得一提的两个设计克制之处:

  • • 不写任何东西,除非你点头。graft init --dry-run 会先列出它打算碰的每一个文件。在没有终端交互的环境(CI、Docker)里,它干脆什么都不写,只打印一条命令让你自己跑。
  • • 基础层完全不用 API key。 结构图谱是 tree-sitter 硬解析(共 20 门语言的真实 AST,其中 TypeScript/JavaScript、Python、Go、Java 是全保真的跨文件调用解析),确定性的、不联网、不调模型。只有生成"人话摘要"的 --deep 那一层才需要模型,而且用你自己的 key、你自己选的模型——OpenAI、Anthropic、OpenRouter、本地模型都行。
  • • 零遥测。 唯一的网络请求就是你自己配的那个模型调用。

增量也快得离谱:官方给的数据是 124 个文件的仓库,冷启动 0.74 秒,改一个文件后重建 0.18 秒。

正因为便宜,它才敢做到"每次查询前都先刷新一遍图谱"——一次结构比对只要约 3 毫秒,且完全不花钱。

所以你得到的答案,描述的永远是此刻的代码,包括你刚改完还没提交的部分。


数据:省了多少,错了没有

这类工具最容易翻车的地方是:快了,但答得更糙了。

Graft 团队没有回避这点,做了一个 162 次运行的对照测试:同一个 agent、同一套文件工具,唯一变量是有没有图谱。而且用另一个模型当裁判打分,还设了关键词底线,防止"答得快但答得错"混过去。

指标(每任务均值)
冷启动
有 Graft
成本
$0.0429
$0.0292(−32%)
未缓存输入 token
8,070
4,650(−42%)
工具调用次数
4.2
2.3(−46%)
耗时
39.8 秒
15.8 秒(−60%)
正确率
93%
93%(持平)

等待时间砍掉六成,工具调用砍掉近一半,正确率没掉。

还有一个更有意思的结果:如果不主动往上下文里塞,而是让 agent 自己按需去问图谱("pull 模式"),速度优势会缩水,但正确率从 93% 跳到 98%——比冷启动高 5 个百分点。

团队给的建议很实在:"要快就 push,要准就 pull。"

真实项目上的测试也做了。他们在 PocketBase(Go,约 350 个文件)上跑了 15 个任务,其中 5 个是真实已合并的 PR,回滚到基线提交重新实现,然后对比 agent 改的文件是不是维护者当初改的那批:

15 个任务合计
原生 Claude Code
有 Graft
成本
$13.91
$11.02(−21%)
总耗时
2,044 秒
1,762 秒(−14%)
PR 复现
5 / 5
5 / 5(改的文件一模一样)

差距最大的地方,正是跨文件理解——"OAuth2 各家提供商的鉴权是怎么走通的"这个问题,成本从 0.84。

这符合直觉:越是需要在多个文件之间来回穿针引线的问题,"有地图"的优势越明显。

还有一份"别人家的卷子"

上面这些都是团队自己设计的测试,自说自话总归有嫌疑。

所以他们又跑了一遍业界标准的 SWE-bench Verified——真实 GitHub 项目里的真实 issue,用官方评分程序打分。

这个评测的好处是没法糊弄:没有裁判模型,没有相似度打分。你的补丁被打上去,跑维护者自己写的测试,要么把原本失败的测试修好且没弄坏别的,要么就是不及格。

50 道题,两边都用 Claude Sonnet 5,同样的 Docker 镜像、同样的轮次上限:

指标
原生 Claude Code
有 Graft
正确率
27 / 50(54%)
33 / 50(66%),+12 个百分点
token 消耗
1.42 亿
1.09 亿(省 23%)
成本
$52.34
$42.43(省 19%)
工具调用
1,370 次
1,031 次(省 25%)
总耗时
13,094 秒
8,922 秒(省 32%)

更值得看的是它赢在哪儿。 官方指出,每一个正确率上的胜负,形状都一样:没有地图的那一方,只改对了一个文件,漏掉了它的兄弟文件。

比如 Django 的一个 issue,正确的修复需要动 5 个文件,冷启动的 agent 只改了 1 个,结果连带弄坏了 18 个原本通过的测试——还连续犯了两次。

另一个 issue 需要动 4 个文件,它改了 1 个,103 分拿了 102 分,差的就是那个"没想到还要改这里"。

Graft 找齐了剩下的。而且在其中一道题上,它用了一半的 token 和一半的时间

这几乎是对"上下文"价值最精确的注解:AI 的失误,很多时候不是不会写代码,而是不知道还有什么在等着被改。


看得见的地图

Graft 还有个让人眼前一亮的功能:graft viz,本地起一个交互式图谱查看器。

搜索 → 跳到节点 → 依赖关系亮起:琥珀色是它依赖谁,青色是谁依赖它

这里的边不是抽象的"相关",而是代码自己的动词usescallsproducesconfiguresvalidatesimplements……每一个动词对应一个真实的工程问题:

  • • part_of / contains —— 这东西住在哪儿?
  • • uses / depends_on —— 我改了它,什么会崩?
  • • configures —— 什么能不改代码就改变它的行为?
  • • validates —— 什么在检验它?(测试、漂移检查)

而更实用的是"爆炸半径"(blast radius)——你刚改完一个文件,它立刻告诉你谁会受影响:

改文件 → 影响范围内联显示 → 图谱自动重新同步 → 在 graft viz 里得到确认

对于任何维护过大型代码库的人来说,这个功能的价值不用解释。


比工具本身更值得琢磨的事

Graft 好不好用,一年后自有分晓(它目前还是 pre-1.0,从 main 分支持续发布)。但它指向的那个问题,值得所有关注 AI 的人认真想一想。

过去两年,行业的注意力几乎全在"模型有多强"上。 参数量、上下文窗口、跑分。但当模型强到一定程度之后,瓶颈就悄悄换了位置——不再是它会不会,而是它知不知道。

一个能考 SWE-bench 高分的模型,扔进你公司那个五年历史、三十万行、注释稀烂、原作者早就离职的代码库里,它一样会抓瞎。不是因为它笨,是因为没有人给它做过入职培训

这就是最近被反复提起的"上下文工程"(context engineering)。整个 2025 到 2026 年,这个领域的共识正在从"让模型自己去 grep"转向"预先构建结构化的上下文层"。

学术界也在跟:一篇 2026 年的研究显示,把 tree-sitter 构建的知识图谱通过 MCP 暴露给 agent,在 31 个仓库上把 token 用量降到了约十分之一。

Graft 在这条路上的选择很有性格——不用向量、不用 embedding、不建数据库,就是纯文本文件加确定性解析。

这在一堆"AI 原生"方案里显得有点复古,但它换来的是三样很珍贵的东西:可读、可 diff、可审查

图谱错了?你能看见。代码变了图谱没跟上?在 PR 的 diff 里一目了然,而不是烂在某个外部存储里悄悄发霉。

这或许才是最有意思的一点:当 AI 越来越多地参与写代码,"给 AI 看的文档"和"给人看的文档"正在合并成同一样东西。

一份好的架构说明,从此不只是给新同事看的了。它同时是你 AI 助手的记忆。写好它,收益翻倍。


最后

如果你在用 Claude Code、Codex 或任何编程 agent,并且经常感觉"它在我的项目里像个无头苍蝇"——这个方向值得你花二十分钟试试。

npx @nanonets/graft init --dry-run   # 先看看它想动哪些文件

不装全局、不写任何东西,先看一眼再决定。

而如果你只是个旁观者,那么记住这句话就够了:

人类进一个项目,只需要上手一次。AI 每一次都要重新上手。
谁先把这件事解决掉,谁就拿到了下一轮的门票。


项目地址https://github.com/NanoNets/Graft
官网:https://graft.nanonets.ai

本文数据与图片均引自项目官方 README 与官网,部分基准为团队自测结果,仅供参考。