前几天看到一篇讲用 OpenCode 读 OpenCode 的文章,四步拿到源码地图。看完我心里卡着两个疑问:/init 到底生成了什么东西,以及 Explore 说「绝不会改任何东西」——凭什么。与其猜,不如自己跑一遍。

OpenCode 读源码四步法实测路径:/init 生成 AGENTS.md、@explore 只读探索、Tab 切 plan、主链路下钻;下方标注两处与原文说法不一致:命令入口不是 cli(bin 为 lildax),内置代理实测 15 个而非 3 个
四步法实测路径。数字全部来自 commit ebb7b76 的本机实测

先把仓库拉下来,顺手记 commit

clone 下来第一件事不是读代码,是记版本。

$ git clone --depth 1 https://github.com/anomalyco/opencode.git
$ git log -1 --format="%H %ci"
ebb7b76eca82342642c78645109e865614533827 2026-09-19 20:49:02 -0400

这步看着多余。但后面 AI 告诉你的文件名、行号,全都指着这个 commit。仓库默认分支是 dev,一天能推好几次,隔两天再问同一个问题,答案就漂了。

顺便说一句,仓库已经从 sst/opencode 迁到 anomalyco/opencode 了,用旧地址访问 API 会拿到一条 301。

第一步:/init 到底写了什么

我没让它真跑(本机没配模型 key),直接去读它的提示词模板,比跑一次更准。文件在 packages/opencode/src/command/template/initialize.txt,第一行:

Create or update AGENTS.md for this repository.

后面是一串调查顺序:README、manifest、构建与 lint 配置、CI 配置,以及已经存在的 AGENTS.md、CLAUDE.md、.cursorrules。中间有一条我特别认同:

Prefer executable sources of truth over prose. If docs conflict with config or scripts, trust the executable source.

文档和配置文件打架的时候,信可执行的那个。这条比市面上大部分「让 AI 帮你读项目」的技巧都实在——它明确承认了文档会说谎。

第二步:@explore 真只读吗

文章说它只读、绝不会改任何东西。我翻了 packages/opencode/src/agent/agent.ts,explore 的权限是先全拒再逐个放行:

"*": "deny",
grep: "allow",   glob: "allow",  list: "allow",
bash: "allow",   webfetch: "allow",  websearch: "allow",  read: "allow",

放行列表里有 bash。默认行为确实是在查代码,但「绝不会改任何东西」这话说过头了——它有 shell,能力上是能写的。实操上真正的防线是别同时给它 build 权限,两件事其实是一件事:主动权别交出去。

顺带发现一处对不上的。文章说内置三个代理。我装了 CLI(v1.18.31)跑了一遍:

$ opencode agent list
Sisyphus - Ultraworker (primary)
Prometheus - Plan Builder (primary)
build (subagent)
explore (subagent)
general (subagent)
plan (subagent)
librarian (subagent)
oracle (subagent)
...(共 15 个)

源码里能确认的原生内置代理是 build、plan、general、explore 四个,另外 compaction、title、summary 标了 hidden。不管按哪个口径数,都不是三个。

第三步:Tab 切 Plan,切的是什么

在 packages/tui/src/config/keybind.ts 里,tab 绑的是:

agent_cycle: keybind("tab", "Next agent"),
agent_cycle_reverse: keybind("shift+tab", "Previous agent"),

没有独立的「模式切换」键位。因为 build 和 plan 都是 primary agent,循环的时候会在两者之间跳过去,用起来的手感像切模式,机制不是一回事。

Plan 本身是靠谱的。agent.ts 里那句描述很直白:"Plan mode. Disallows all edit tools." 编辑类工具全禁,只留 question 和 plan_exit,外加允许往 .opencode/plans/*.md 写文件。

意外收获:官方自己就在写地图

仓库根目录躺着三份文档,大小差得很明显:

文件字节写给谁
README.md5,402用户
AGENTS.md8,748AI / 贡献者
CONTEXT.md32,094AI

CONTEXT.md 是 README 的 5.94 倍。团队自己也把项目地图写进文件里,每次会话先读它。

我翻了 AGENTS.md 开头几行,全是这种硬信息:默认分支是 dev 不是 main;改完 Protocol 或 HttpApi 要从 packages/client 跑 bun run generate,别手改 src/generated;依赖方向只能 Schema→Core→Protocol→Server,Client 不许依赖 Core。这些东西文档里不会写,是踩过坑才会记下来的。

照着旧说法读,会踩一个坑

文章说 packages 下 32 个核心包,cli 是命令入口。数量是对的,入口不对:

packages/cli      bin: { "lildax": "./bin/lildax.cjs" }
packages/opencode bin: { "opencode": "./bin/opencode" }
packages/core     bin: { "opencode": "./bin/opencode" }

packages/cli 现在的 bin 是 lildax,不是 opencode。真正的命令入口是 packages/opencode。照着旧说法去读 cli 包,读到的是另一个东西。

另外那 32 个包里混着 docs、storybook、containers、slack,叫「32 个包」没问题,「32 个核心包」有点抬举它们。

什么情况下这套方法不划算

  • 几十个文件的小项目,直接读更快,建地图的开销大于收益
  • /init 要调模型,没有 API key 就跑不动。「零插件」是真的,「零成本」不是
  • 结构天天变的项目,地图写完就过期,不如直接问 explore
  • 读自己天天在改的项目收益最低——你已经知道答案了,地图只是复述

我实际用下来的顺序

跑完这一轮,我自己的顺序固定成这样:

  1. clone 完先 git log -1 记 commit
  2. /init 建 AGENTS.md,拿到构建命令和代码约定
  3. @explore 问入口,要求每个结论都带真实文件路径,找不到就明说
  4. Tab 切 plan,要模块清单和依赖关系
  5. 挑一条主链路下钻,最后用测试兜底

最后一步在这个仓库里很舒服:packages/core 有 144 个测试文件,全仓 661 个。测试是行为的说明书,读它比读实现快得多。

全程不开 build。这不是洁癖——Explore 的 bash 权限是开着的,Plan 明确禁了编辑工具,把这两条边界记清楚,剩下的就敢让它放手去读了。