更换在 cron 里运行程序员代理的 CLI,看起来只是一行改动:换掉二进制文件,保留提示词。但实际上有五层会出问题,而它们全都不是提示词。2026-11-05,发布本博客的那条流水线从一个代理 CLI 迁到了 Verboo Code,我们亲历了这次迁移。以下是每一层出的问题以及对应的修复命令,全部已在 verbeux-ai/code v0.15.41 的源码中核实。
简短回答:重新确认非交互模式(-p)、无浏览器认证、配置目录(~/.verboo)、运行时(engines.node)以及 MCP 工具的协议。只要这五层里还有一层是从旧 CLI 借来的,迁移就没有完成。
为什么更换代理的 CLI 不只是换一条命令?
因为命令只有一行,但它周围的环境不是。一个由 cron 触发、自行运行的代理,依赖旧 CLI 默默替它解决的五层东西。一旦换掉二进制文件,每一层都可能悄无声息地失效:
- 非交互模式。cron 没有终端。如果新 CLI 没有办法在完全不追问的情况下运行,它会在第一次确认时卡住。
- 认证。cron 没有浏览器。如果新 CLI 的登录要打开网页,会话就永远建立不起来。
- 配置目录。命令、技能和权限放在一个很可能与旧 CLI 不同的目录里。
- 运行时。每个包都会声明它支持的 Node 版本,很容易装在一台对不上的服务器上。
- 外部工具。MCP 服务器通过协议通信,客户端与服务端必须使用同一修订版本。
如何证明新 CLI 能在没有终端的情况下运行?
在动任何脚本之前,先用一句无害的提示词运行二进制文件,并要求 JSON 输出。只要它返回结果,非交互契约就还在:
verboo -p "只回复:ok" --output-format json
-p(即 --print)打印回答后退出,适合管道使用。--output-format 只在配合 -p 时生效,可选 text(默认)、json(单个结果)或 stream-json(实时事件流)。在 cron 里你应该用 json:每次运行一个对象,方便写入日志。
还有三个参数决定无人值守任务的行为。--max-turns 限制代理在停止前的往返次数,避免任务挂着不动。--max-budget-usd 为每次运行设置花费上限。--no-session-persistence 让这次运行不落盘,避免每日 cron 堆积一堆没人会恢复的会话。另外要知道,在 -p 模式下工作目录的信任确认对话框会被跳过,所以只把任务指向你信任的目录。
没有浏览器时,认证放在哪里?
cron 不会打开浏览器,所以标准的交互式登录用不了。Verboo Code 用两条路径解决,选哪条取决于任务在哪里运行:
| 路径 | 工作方式 | 何时使用 |
|---|---|---|
verboo auth login --headless | 无需浏览器:显示一个网址让你在另一台设备上打开,再回填验证码 | 你自己控制的机器,会话可以保留下来 |
ANTHROPIC_API_KEY | 通过环境变量传入 API key,不使用 OAuth 会话 | 一次性的 CI runner,或任务结束即销毁的容器 |
走 key 这条路时,变量名就是 ANTHROPIC_API_KEY 本身,不是别的名字。设置它就等于把凭据存进了环境,最低要求是别打印到日志里,并限制谁能读取任务的配置。
为什么旧配置会污染新任务?
因为新 CLI 不读旧 CLI 的目录。Verboo Code 把所有东西放在 ~/.verboo,而且源码明确写着:它既不读取、也不迁移其他 CLI 的全局文件。这意味着你的命令、技能和权限不会白来:技能在 ~/.verboo/skills,命令在 ~/.verboo/commands,权限在 ~/.verboo/settings.json。把一个 CLI 的目录直接复制到另一个上不管用,因为格式不同。
例外是会话目录,而且这是有意为之。它默认仍在 ~/.claude/projects,正是为了支持跨 CLI 的 --resume。如果你想要完全隔离,把它指到别处即可。若同一台机器上跑多个任务,最干净的做法是给每个任务一个自己的配置目录:
export VERBOO_CONFIG_DIR=/opt/jobs/blog/.verboo
verboo -p "同步草稿" --output-format json
这样任务就有了自己的 key、自己的权限和自己的历史,不会和同一台机器上的交互式会话互相抢占。
这个包要求什么运行时?
安装时要看 Node 版本,而不只是 CLI 版本。@verboo/code 包声明了 engines.node >= 22.0.0。在旧服务器上安装前先确认:
node -v
npm install -g @verboo/code
verboo --version
如果 node -v 返回 20,最短的路是先升级 Node,再去和 npm install 较劲。engine 报错出现在安装中途,看起来像是另一回事。
怎么知道 MCP 工具到位了?
靠症状,而它是安静的。当客户端与服务端的协议修订版本对不上时,握手失败,工具列表返回为空,代理就只是"不用"这个工具。没有响亮的报错:提示词照跑,输出照出,而依赖那个工具的动作从未发生。
所以在怪提示词之前,先看工具列表。想精确固定哪些服务器进入任务,就用 --mcp-config 指定正确的文件,再加上 --strict-mcp-config,它会忽略机器上其他所有 MCP 配置。cron 任务应当始终使用同一份服务器列表,而不是当前目录里碰巧存在的那份。
关掉旧 CLI 之前要检查什么?
让两边并行跑几天,比较输出,而不是比较感觉。"迁移完成"的标准是客观的:
- 任务连续跑两次,全程无人干预,最终产物与旧 CLI 的一致。
- 每次运行的日志记录调用了多少个工具、分别是哪些。
- 模拟一次故障(key 失效、网络断开)时以明确报错结束,而不是任务挂住。
- 服务器的
node -v与包的engines.node一致。 - 没有任何一步还依赖只存在于旧 CLI 目录里的文件。
五条都成立,你就迁移完了。只要还有一条依赖旧 CLI,下一个任务就会在那里自行崩掉,而且多半是在周末。
这五层不会因 CLI 而异。如果目的地是 Verboo Code,确切的顺序很短:npm install -g @verboo/code,用 verboo auth login --headless 建立会话,再在 cron 里用 verboo -p 配合 --output-format json。安装它,并在同一个目录里对两边运行同一句提示词,然后再关掉旧代理。



