你的第一本真实手册
从一个你从没读过的仓库,到一份可以直接应用的改动计划,一共八步——并把便宜的检查点放在正确的位置上。
这是在一个真实仓库上的完整闭环。请按顺序执行;它有意把免费的检查放在昂贵的步骤前面。
alias handbook="node $(pwd)/packages/cli/dist/main.js"
export REPO=~/code/myrepo
export WORK=work/myrepo第 1 步——先看清,再动手
handbook analyze --source $REPO --work $WORK{
"language": "multi",
"files": 412,
"functions": 3187,
"edgesKept": 9042,
"edgesDropped": 611,
"filesUnparsed": 3
}这一步免费,而且是你的冒烟测试。 不用 LLM、不用 key、不花 token。
继续之前先读懂这些数字
files比你预期的低很多? 某种语言被整个跳过了,或者你的源码根目录不对。用-v查看扫描日志。 -files高得离谱? 你正在分析node_modules、vendor或某个构建目录。常见目录会被自动跳过;如果没有跳过,就把--source指向真正的源码根目录,而不是仓库根目录。edgesDropped相对edgesKept大得吓人? 对动态语言来说这很正常。看看phase1/dropped-calls.json——每一个未解析的调用都在那里被分了类,而不是被藏起来。 -filesUnparsed不是 0? 这些文件都带着原因写在phase1/scan-coverage.json里。其中unreadable和unparsable的那些什么事实都贡献不了,也不会有自己的页面,所以现在生成出来的手册,恰恰在那里有个洞——值得在为文字付钱之前先补上。
上面这些问题现在就修。这里的每个问题拖到后面都会变得更贵。
第 2 步——生成手册
这是要花 token 的一步。中等规模的仓库,预期是分钟级。
先从便宜的开始:
handbook generate --source $REPO --work $WORK这相当于 --detail brief 加 --synth-mode oneshot:每个文件一张短卡片,外加单遍生成的骨架。这是判断手册的形状对不对的最快方式。
看看 $WORK/phase2/skeleton.yaml。阶段列表像不像你的系统?像,就升级:
handbook generate --source $REPO --work $WORK \
--phase 2a --detail deep --resume--phase 2a --resume 只加深卡片,并跳过已经有完整卡片的文件。你已经验证过的骨架原样保留。
如果骨架本身就不对,那就改用 actor–critic 循环重跑 2b:
handbook generate --source $REPO --work $WORK --phase 2b,2c,3 --synth-mode doctor可恢复、可取消、有缓存
卡片完成一张写一张。Ctrl-C 是安全的。--resume 从停下的地方继续,--llm-cache
让重跑几乎免费,run-manifest.json 记录着上一次成功运行花了多少 token。
第 3 步——渲染
handbook render --work $WORK --title "MyRepo Handbook" \
--html --html-single --agent-site --llms-txt不用 LLM。 想跑多少次就跑多少次——放在 CI 里、每次提交都跑也没问题。
加上 --source-base-url https://github.com/me/myrepo/blob/main 可以把手册里的每个文件路径变成指向真实文件的链接。不加的话,产出中完全不含任何外部 URL——这对私有代码库很重要。
打开 $WORK/handbook/html/overview.html 读一读。评判这本手册好不好,就在这一刻。
第 4 步——为你的代理打包
handbook skill --handbook $WORK/handbook --out skills/myrepo \
--name myrepo --project "MyRepo" \
--work $WORK --source $REPO \
--agent-dir $WORK/handbook/agent--work 加 --source 一起会产出 coverage.json:每个文件一个内容哈希。正是它让手册的漂移日后可以被检测出来,而不是悄悄出错。
--agent-dir 会带上代理索引和它的事实表,并给 SKILL 的路由协议配上 grep 配方——这样代理一条命令就能把一个符号名变成 path:startLine-endLine,而不必读一堆文字再去猜。
第 5 步——校验
handbook validate --skill skills/myrepo --source $REPO检查结构、frontmatter 契约、索引 ↔ 阶段页的一致性,并对你的源码重新做哈希,报告已经落后的页面。失败时以退出码 2 结束,所以该放进 CI 的就是这条命令。
第 6 步——规划一个真实改动
handbook plan --source $REPO --handbook skills/myrepo/references \
--request "Retry failed uploads three times before giving up" \
--out plan.md一个只读的代理循环:它只会列目录、读文件、grep——它根本没有写工具——用手册做路由,对照真实源码验证,然后写出 plan.md。
读一读这份计划。真的去读。它以一个机器可读的声明块结尾:
### EDIT 1
- file: `src/upload.py`
- where: `Uploader.send (~88)` — wrap the request in the retry helper
```old
response = self._client.put(url, data)
```
```new
response = self._retry(lambda: self._client.put(url, data), attempts=3)
```
```json
{ "will_modify": ["Uploader.send"], "will_add": ["Uploader._retry"], "will_remove": [] }
```放弃的规划器会以非零码退出
如果它拿不出一份可用的计划——比如它不断虚构文件内容,或者轮次用完了——它会大声失败,而不是往 plan.md
里写一段道歉,让脚本再高高兴兴地把这段道歉喂给 apply。
第 7 步——应用它,并留好退路
handbook apply --source $REPO --plan plan.md --dry-run # verify only, never writes
handbook apply --source $REPO --plan plan.md # for realDry run 在精神上不是可选项。它会针对当前文件内容解析每一个锚点,并明确告诉你哪些编辑会落地。
应用时会打印备份目录。在用得上它之前,先把它复制到别处:
handbook rollback --backup $REPO/.handbook-patches/2026-08-08T14-05-11-204Z回滚会拒绝任何在打补丁之后又发生变化的文件,除非你传 --force——因为直接恢复会悄悄毁掉那些后续工作。四条安全规则详见应用改动。
第 8 步——让手册跟上代码
代码动了。不要重新生成——用 resync 同步。
一个 case 就是你自己组装的一个目录:
cases/upload-retry/
edited/ copy of the repo after the change (required)
plan.md the plan from step 6 (optional — sharpens scope)
change.diff unified diff of the change (optional — widens scope)mkdir -p cases/upload-retry
cp -R $REPO cases/upload-retry/edited
cp plan.md cases/upload-retry/
handbook resync --case cases/upload-retry --work $WORKResync 会重新分析编辑后的代码树,对比新旧调用图,然后只重新生成变化的部分。$WORK/handbook 下已渲染的产出会自动刷新。
手头没有端点?--no-llm 会刷新结构性事实,并把叙述标记为过期,而不是假装它还是最新的。
如果你的仓库非常大
| 症状 | 怎么办 |
|---|---|
| 文件数以千计 | 先用 --detail brief。之后用 --phase 2a --detail deep --resume 有选择地加深。 |
| 跑得慢 | 调高 --read-workers / --assign-workers / --narrate-workers,它们都受 --llm-concurrency 约束。 |
| 触发限流 | 调低 --llm-concurrency。调高 --llm-retries 和 --llm-retry-backoff。 |
| 生成文件巨大 | --max-chars-per-file 20000 截断每个文件发送的内容。 |
| 你只关心一个子系统 | 把 --source 指向那个子目录。调用图只由你扫描的部分构建。 |
| 迭代过程中反复重跑 | 用 --llm-cache;想刻意忽略缓存时用 --refresh。 |
更多内容见成本与性能。