CodeBuddy CLI 委派

将长时间运行的编码批次委派给隔离的无头 CodeBuddy CLI 代理,然后独立验证每项结果。

carloswonmore
2026年10月8日
0 收藏
64 下载

安装与下载

1 ClawHub CLI

从源直接安装技能的最快方式。

npx clawhub@latest install codebuddy-cli-delegation

2 手动安装

将技能文件夹复制到以下位置之一

全局模式 ~/.openclaw/skills/
工作区 {'/skills/'}

优先级:工作区 › 全局 › 内置

3 提示词安装

将此提示词复制到 Openclaw 即可自动安装。

请帮我使用 Clawhub 安装 skill-codebuddy-cli-delegation。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。

更倾向于下载?

获取包含原生技能文件的ZIP压缩包。

下载技能 (.zip)

基本信息

名称 CodeBuddy CLI 委派
Slug codebuddy-cli-delegation
创建者 carloswonmore
创建时间 2026-10-08 05:32:15
更新时间 2026-10-08 05:32:15
收藏数 0
使用量 64
浏览量 2

安装指南

  1. ClawHub CLI 从源直接安装技能的最快方式。
    npx clawhub@latest install codebuddy-cli-delegation
  2. 手动安装 将技能文件夹复制到以下位置之一
    全局模式
    ~/.openclaw/skills/
    工作区
    /skills/
    优先级:工作区 > 本地 > 内置
  3. 提示词安装 将此提示词复制到 OpenClaw 即可自动安装。
    请帮我使用 Clawhub 安装 codebuddy-cli-delegation。如果尚未安装 Clawhub,请先安装(npm i -g clawhub)。
    更倾向于下载?
    获取包含原生技能文件的ZIP压缩包。
    下载技能 (.zip)

什么是

CodeBuddy CLI 委派是一套专用于 CodeBuddy 的工作流,可将大规模编码工作(例如重构、编写测试、更新文档和无人值守批次运行)交给独立启动的无头代理处理。它通过明确的指令、运行预算、受控权限和可追踪的输出,帮助避免前台超时和上下文过载。
干净环境的 Node.js 启动器会剥离可能干扰 CLI 启动的主机注入变量;工作流则规定何时可以安全地并行执行,以及如何隔离共享资源。Openclaw Skills 用户可以采用实用的委派流程:在独立检查日志、文件、测试和对抗性检查之前,代理的说法一律视为未经验证。其实现细节已针对 CodeBuddy CLI 2.156.0 进行测试;未经重新测试,不应复制到其他 CLI 产品。

应用场景

委派大型批次重构,避免前台会话耗时过长或上下文负担过重。
在一组指定文件中生成或扩展测试,然后独立重新运行相关测试命令。
根据明确的范围和验收标准,补充文档或其他仓库产物。
使用时间限制、权限模式、重定向的 stdin 和已保存的日志运行无人值守编码批次。
只有在隔离工作树、依赖项、数据库、端口和生成产物之后,才并行处理相互独立的工作。
通过对抗性探测、变异检查和直接检查审计代理实现,而不是依赖其摘要。

工作原理

定义可验证的目标、已知发现、允许的文件范围、禁止的更改、资源预算、验证命令和预期交付物。
委派前检查项目约定:将场景映射到实现路径,找出含糊的验收标准,并解决冲突或测试环境风险。
由委派方明确选择模型。为该模型设置工作强度和其他受支持参数;不要让 skill 代替用户选择模型。
通过干净环境的 Node.js 包装器启动 CodeBuddy。隔离主机注入的环境变量,加载项目级设置,为无人值守运行关闭 stdin,并捕获 CLI 输出和退出状态。
默认串行运行。对于并行批次,先隔离 Git 工作树、依赖项、数据库和端口,并确保它们的写入集合互不重叠。
检查已保存的输出和 CodeBuddy 会话记录。适用时,在函数调用日志中验证所需的 Skill 或 Agent 调用,并检查声称的文件更改是否确实存在。
独立重新运行指定检查。将零测试结果、缺失输出和未经验证的说法视为尚未解决,而不是成功证据。
使用对抗性案例和变异控制探查关键断言,恢复所有测试变异,然后报告运行详情、模型和工作强度设置、变更文件、验证结果及待处理的审批。

配置指南

安装并验证 CodeBuddy CLI 身份,并确保 Node.js 可用。文档所述的启动器行为和 CLI 专用标志基于 CodeBuddy CLI 2.156.0;依赖特定版本的选项前,请先查看当前 CLI 帮助。
将 scripts/codebuddy-cli.js 放入 skill 或项目文件中。在 Windows、macOS 或 Linux 上,使用 Node.js 调用它:
node scripts/codebuddy-cli.js -p "Reply with one word: ready" --model hy3 --effort high --output-format json
可选择将 skills-bootstrap.template.md 复制为启动器旁边的 skills-bootstrap.md。如果存在,启动器会读取此文件,并将其内容附加到 system prompt。
确认最低限度的测试成功,并在开始批次前检查 stderr。包装器支持原生 CLI 选项和已记录的 PowerShell 风格别名,例如 -Prompt、-Model 和 -Effort。
为无人值守运行配置明确的模型、工作强度、权限模式、输出格式、轮数上限、超时时间,并关闭 stdin。将自动批准范围限制在独立 CLI 内;不要默认授权危险操作。
分别保存每个提示和运行日志。使用项目级设置(--setting-sources project)以避免有问题的用户级钩子。在目标环境中重新测试所有启动器更改;仅进行语法检查不足以证明运行时正确。
mkdir -p .cli-runs
node scripts/codebuddy-cli.js -p "$(cat .cli-runs/task.prompt.md)" \ --model hy3 --effort high --permission-mode bypassPermissions \ --output-format json --max-turns 150 \ .cli-runs/task.log 2>&1

数据架构

该工作流使用仓库文件、每次运行的提示和日志,以及 CodeBuddy 自身的会话记录;它不规定单独的数据库 schema。
产物 用途和组织方式
scripts/codebuddy-cli.js 跨平台 Node.js 启动器。移除指定的主机注入环境变量,通过文件系统定位 CodeBuddy,转换受支持的参数别名,可选地附加引导提示,并转发 stdio 和退出状态。
skills-bootstrap.md 可选的 system prompt 补充内容,存储在启动器旁边;通常从 skills-bootstrap.template.md 复制而来。
.cli-runs/.prompt.md 明确的任务约定:目标、已知发现、范围、预算、验证和交付物。
.cli-runs/-.log 捕获的运行输出,供之后审查。每个批次或续接阶段分别保存日志。
~/.codebuddy/projects//*.jsonl CodeBuddy 会话记录。工具事件使用 type: "function_call",字段包括 name、callId 和 arguments;应验证匹配的结果,而不要假定其日志格式与其他 CLI 相同。
Git 工作树和隔离资源 对于并行批次,应分开分支和工作目录、依赖项、数据库/schema、端口和输出目录。确保写入集合互不重叠,并在审计后按顺序合并批次。
审查 JSONL 会话时,在需要的情况下统计实际的 Skill 和 Agent 函数调用。将报告的文件列表与工作树进行比较,并在交付报告中保留独立测试结果和未解决事项。

高级特性

使用单个 Node.js 文件实现的跨平台干净启动器,通过基于文件系统的 CLI 发现机制定位程序,避免启动辅助进程搜索 PATH。
环境变量清理和 Windows Git Bash 检测,以减少主机配置泄漏和启动失败。
为选定的 PowerShell 风格名称和原生 CodeBuddy CLI 标志提供参数兼容层;无法识别的选项会继续传递。
可选的引导 system prompt,用于强制执行项目工作流、skill 加载要求和可审计报告。
安全并行准备规则,涵盖 Git 工作树、依赖项、数据库、端口、生成产物和互不重叠的写入。
通过 CodeBuddy 的 --agents 选项配置每个子代理的模型、工作强度、工具和轮数,并明确验证所需代理是否确实被调用。 -c 或明确的会话 ID 继续会话,从而在不同运行阶段调整工作强度。
通过对抗性探测、变异控制、正反控制和直接检查产物来独立验收。
基于证据的运行报告,记录模型和工作强度设置、耗时、退出状态、日志路径、变更文件、重新运行结果及待处理审批。


name: codebuddy-cli-delegation description: 把大批量编码任务派给「独立无头 CodeBuddy CLI」执行的标准流程。CodeBuddy CLI 专用(非通用 CLI 技能):干净环境启动(避免宿主注入环境变量导致 0 字节静默挂死)、指令预算与并行准入(四隔离 + 写集不相交)、模型与参数分配(模型由派发方指定,参数按阶段分配)、独立审计验收(对抗性探针 + 变异对照,不采信 CLI 自述)。含 21 个可用模型清单与厂商档位映射、启动器模板,全部结论基于 CodeBuddy CLI 2.156.0 实测。用于批量改造、批量补测试、批量文档回填、无人值守跑批次等前台会超时的大任务。触发词:用 CLI 派活、让 CLI 干一批、无人值守跑、交给 CLI 做、批量改造、批量补测试、前台会超时、代码审计外包、headless CLI、CodeBuddy CLI。英文关键词 / English keywords:delegate to headless CodeBuddy CLI, unattended batch run, batch refactor, batch test authoring, agent delegation audit, adversarial probe, mutation control, clean-env launcher, headless agent delegation. agent_created: true

CodeBuddy CLI 派活(Headless Agent Delegation)

一句话:把一批活交给一个独立启动的无头 CodeBuddy CLI agent 去干,你只负责 写清指令 → 控预算 → 收产物 → 独立验收。

它解决什么:前台同步做会超时 / 上下文会被撑爆 / 需要并行多批次的大活。 它不解决什么:需要人来拍板的决策、需要访问你所在宿主私有状态的事、一次性的小改动。

⚠️ 适用范围:这是 CodeBuddy CLI 专用技能

本技能的全部实测结论都只对 CodeBuddy CLI 成立,具体包括: 干净环境启动器要剥离的变量名(CODEBUDDY_* / ACC_PRODUCT_CONFIG_* / SERVER__*)、 --setting-sources project、--permission-mode bypassPermissions、 --effort 六档档位与厂商映射、21个可用模型清单、--agents 的 JSON schema、 -c 恢复会话、--tools 白名单、以及会话日志路径 ~/.codebuddy/projects/。

换用别的 CLI(Codex / Gemini CLI / Claude Code 等)时不要照搬本技能: 那些 CLI 的注入变量清单、参数名、会话日志结构、权限机制都不同, 必须各自重新实测,否则会踩到「按CodeBuddy 的假设去剥别的 CLI 的变量」这类错。

其中真正与CLI 无关、可直接复用的方法论(换 CLI 后仍成立,只需重新验证载体): §二(并行准入与四隔离)、§3.5(派发前契约核对六动作)、§7.3–7.7(对抗探针与变异对照)、§零铁律 3(不采信自述)。 建议这些部分另立一份 agent-delegation-audit 之类的通用技能, 由本技能与将来的其他 CLI 技能共同引用 —— 但那需要另做一次提炼与验证。

零、四条铁律(先看这个,其余都是细节)
绝不直接启动裸 CLI —— 宿主会把自己的环境变量注入子进程,轻则跑错配置,重则永久挂死。 必须走一个「干净环境启动器」。
默认串行;但并行是「支持」的 —— 要不要并行,取决于「共享可变资源是否隔离」,与端口无关。 串行的真实理由是共享可变资源只有一份(同一个库 / 同一份契约 / 同一个 git 工作区) 加上「逐批可归因审计」会被交错 diff 破坏(分不清某一行属于哪一批);瓶颈在审计而非执行。 要并行就必须先做「四隔离」(目录+git / 依赖 / 数据库 / 端口)并保证写集不相交 —— 见 §二。 ⚠️ 不要再写「端口按工作区派生,第二个实例必 EADDRINUSE」—— 该结论已于 2026-10-01 实测推翻,详见 §二。
不采信它的自述 —— 它说「已通过 / 已标记 / 已加载」都要自己复跑一遍才能算完成。 历史上出现过「文案说已标记异常、代码里根本没调那个方法」这类事。
模型由派发方显式指定;技能只负责在给定模型下分配参数,永不替派发方选模型。 派活时把 --model 当成输入而不是建议值。技能该提供的是「模型可用性事实表」(§一) 与「在给定模型下怎么分档」(§五之三),不是「这个阶段该用哪个模型」。 ⚠️ 写过「阶段 → 推荐模型」的速查表是危险品:它会让下一次派活悄悄滑向「技能替人做技术选型」, 而选型责任与后果都在派发方。想按阶段换模型,必须由派发方显式拆成多批或多子代理(§五之三)。
一、为什么需要「干净环境启动器」

Agent 宿主(WorkBuddy / VS Code 扩展 / 桌面端)向子进程注入的变量里,至少有三类会让独立 CLI 出错:

注入变量 后果 *_SERVICE_PROXY_URL=http://127.0.0.1:/... 独立 CLI 会去绑定同一个端口提供 service-proxy → EADDRINUSE 未捕获异常 → 进程永久挂死(0 字节输出,300s 无任何反应) *_CONFIG_DIR= CLI 误读宿主的配置目录:技能 / 模型 / 插件全错位 SERVER__PORT / SERVER__HOST(没有前缀,容易被漏掉) 同上,仍会去 listen 那个已被占用的端口 → 挂死
(如 ACC_PRODUCT_CONFIG_PATH) 决定了 CLI 用哪个 authentication.id 去读凭据 → 去读宿主的凭据文件 → 报「未登录」(但其实是登录着的)

做法:启动前把所有疑似注入变量 unset 掉,再让 CLI 回落到它自己的默认位置。

启动器:单个 .js,三平台通用

scripts/codebuddy-cli.js —— 一个文件覆盖 Windows / macOS / Linux,无需 .sh / .ps1 / .bat。

环境 调用方式
任意平台 node scripts/codebuddy-cli.js -p "指令" --model hy3 --effort high
Linux/macOS(先授权一次) chmod +x scripts/codebuddy-cli.js 后 ./scripts/codebuddy-cli.js -p "指令"

用 node 前缀最稳:Windows 上双击/直接执行需要文件关联,而 .js 的关联不总存在。

为什么用 Node 而不是 shell(三条硬理由)
「有 Node」这个前提是白送的 —— CodeBuddy CLI 本身就是 Node 应用 (真实入口首行是 #!/usr/bin/env node),装了它就必然有 Node.js。 而 shell 的可用性没有这种保证(Windows 可能没 Git Bash,POSIX 未必有 Git Bash)。
白名单友好 —— SkillHub 上传只允许 .md .txt .json .yaml .yml .js .cjs .mjs .ts .py .sh .png .jpg .svg。 .js 在内,.ps1 / .bat / .cmd 都不在 ⇒ 一份 .js 是唯一能同时满足 "跨平台"与"可发布"的形态。
绕开一整类跨平台陷阱 —— 前几轮在 .sh/.ps1 上连续踩了:UTF-8 BOM、 sh 与 Node 的路径语义不一致、多层引号下 sed 静默失效、ProgramFiles(x86) 解析…… 换成 Node 后这些整类消失(没有 shell 方言,也没有编码歧义)。
它做了什么
剥离宿主注入的环境变量(§一那张表的两组 + 产品身份 + 会话标识)
Windows 上补 CODEBUDDY_CODE_GIT_BASH_PATH —— 否则 CLI 会退化成 PowerShell; 探测顺序:PATH 里的 bash.exe → 各盘 Program Files\Git\bin\ → PATH 目录里任意 bash.exe
定位 CodeBuddy CLI —— 扫 PATH 各目录找 codebuddy(Windows 上按 PATHEXT 覆盖 .cmd/.exe)→ 从 wrapper 所在目录反推真实 js 入口 → 扫 npm 常见全局安装位置
翻译参数风格(见下)—— -Prompt / -Model 这类具名参数会被转成 CLI 认识的形态
追加 --append-system-prompt —— 读取同目录的 skills-bootstrap.md(不存在则跳过)
以 stdio: 'inherit' 启动 ⇒ 输出直接透传,日志不会被脚本污染;退出码原样传出

💡 skills-bootstrap.md 要放在 codebuddy-cli.js 同目录。 复制技能时把 skills-bootstrap.template.md 改名成 skills-bootstrap.md 放在旁边即可。

参数风格:两种写法都支持(实测踩过)

直接照抄 .ps1 版的写法会报错:

PS> node codebuddy-cli.js -Prompt "回答一个字:好" -OutputFormat json
error: unknown option '-Prompt' ← CLI 只认 -p / --print

原因:.ps1 版有 -Prompt/-Model/-Effort 具名参数,而 .js 版一开始是纯透传。 两版接口不一致 ⇒ 换版本时踩坑。

⇒ 现已加翻译层,以下三种风格实测均通过:

# 风格 A:PowerShell 具名参数(对 .ps1 版用户最自然)

node scripts/codebuddy-cli.js -Prompt "指令" -Model hy3 -Effort high -OutputFormat json

# 风格 B:CLI 原生参数

node scripts/codebuddy-cli.js -p "指令" --model hy3 --effort high --output-format json

# 风格 C:两者混用

node scripts/codebuddy-cli.js -Prompt "指令" --effort high --output-format json

翻译表(只覆盖 CLI 认识的那几个,未识别的参数原样透传 ⇒ CLI 未来新增参数仍可用):

具名写法 转为 -Prompt / -prompt -p -Model / -model --model -Effort / -effort --effort -MaxTurns / -Max-turns --max-turns -OutputFormat / -Output-format --output-format -PermissionMode / -permission-mode --permission-mode

💡 只翻译「独立的参数项」(不带值),避免误改提示词内容里恰好相同的字样。

⚠️ 这是「接口不一致」类问题的典型:同一技能的不同版本/不同脚本用了不同参数风格, 而 CLI 侧只会报 unknown option,不会告诉你"你想要的参数其实是另一个名字"。 ⇒ 凡是提供多种调用风格,必须显式写进文档并实测,否则每个换风格的人都要重踩一次。

⚠️ 为什么不用 where / command -v 找 CLI(实测踩到)

定位 CLI 时不要派生子进程去问 PATH:

// ❌ 实测在 Windows 上返回 error=EBUSY(宿主安全策略拦「进程派生进程」)
spawnSync('cmd.exe', ['/c', 'where', 'codebuddy'])

// ✅ 纯 fs 操作扫 PATH,不触发进程派生,稳
for (const dir of (process.env.PATH || '').split(path.delimiter)) {
for (const ext of (process.env.PATHEXT || '.COM;.EXE;.BAT;.CMD').split(';')) {
const p = path.join(dir, name + ext.toLowerCase());

if (fs.existsSync(p) && fs.statSync(p).isFile()) return p;

}
}

同理,别用 npm root -g 命令来定位:① 同样要进程派生;② 它随「当前用哪个 npm」而变 (实测干净环境下它指向另一个 node 的目录 ⇒ 漏判)。改成直接 fs.existsSync 扫 npm 的标准落点。

Git Bash 那条提示说明什么

若 stderr 出现 Git Bash not detected,说明脚本没能给 CODEBUDDY_CODE_GIT_BASH_PATH 指到可执行文件。按序自查:

// 逐条打印,看是哪一步没命中
process.env.PATH.split(path.delimiter).forEach(d => console.log(d));
// 手动确认目标存在
console.log(fs.existsSync('D:\Program Files\Git\bin\bash.exe'));

也可能是 Git Bash 确实没装(此时装一个即可,或确认退化成 PowerShell 对你的任务无影响—— 只在 CLI 需要真正执行 shell 命令时才有影响,纯问答/改文件不受影响)。

🔴 七轮翻车复盘:为什么「结构检查」全都测不出来

启动器从三平台 shell脚本换成单文件 .js,前后翻了七轮。前六轮是 「检查通过但实际不可用」,第七轮是接口不一致:

轮次 场景 我改了什么 检查结果 实际后果
① .sh 写三平台启动器 sh -n 通过 逻辑错 5 处:多层引号下 sed 静默失效、exec 调shell 函数(无效语法)、npm root -g 漏判、wrapper 当 js 入口跑、路径语义不一致
② .ps1 修 Join-Path 空值 花括号仍配平 从「能跑但 stderr 脏」退化为「跑不起来」 —— 引入 UTF-8 BOM 问题
③ .ps1 加 UTF-8 BOM 括号平衡 ✅ 通过(用户实跑确认)
④ .js 改用 where 定位 CLI node --check 通过 error=EBUSY —— 进程派生被宿主安全策略拦,定位恒失败
⑤ .js 改用纯 fs 扫 PATH 语法通过 ✅ 通过
⑥ .js 补 D 盘 Git Bash 探测 语法通过 探测命中 D:\Program Files\Git\bin\bash.exe,但未能验证 CLI 是否接受(沙箱无法执行 bash)
⑦ .js 从 .ps1 版切换过来 node --check 通过 error: unknown option '-Prompt' —— .ps1 有具名参数、.js 是纯透传,两版接口不一致

⑦的性质与前六轮不同:前六轮是"环境里的坑",⑦是我自己制造的接口不一致 —— 把一个技能的两种实现写成两套参数风格,用户换过来就必然报错, 而 CLI只会说"我不认识这个参数",不会提示你想要的那个名字长什么样。

⇒ 固化三条纪律:

① 任何脚本改动,验证标准是「在目标环境跑一次并读真实输出」,不是「语法检查通过」。 ② 改完必须重跑 —— 包括你"刚改好的"那一次。 ②轮就是修 bug 后没重跑,直接把可用状态改成了不可用。

③ 同一技能的多份实现(不同语言/不同平台),对外接口必须逐条对齐并写进文档。 不同实现之间不能各自发明参数风格;若要支持多种风格,必须显式做翻译层 + 实测。

⇒ 推论一:报错位置与根因可能无关。②轮报"第 57 行意外的 }",真因是第 11 字节的 编码解码中断 —— 查花括号永远查不出来。看到"语法错误指向某行"时,先怀疑文件编码。

⇒ 推论二:定位依赖"问系统"(where / command -v / npm root -g)本身可能就是故障点。 在受限环境(沙箱、容器、CI)里这些命令会因进程派生被拦。 ⇒ 优先用纯 fs 探测:自己扫 PATH、自己拼路径,比派生子进程问系统可靠得多。

⇒ 推论三:"unknown option"类报错要往"上游版本"查,而不只是看当前脚本。 它往往意味着你手里那份文档/示例来自另一个实现。

⇒ 这与 §零铁律 3「不采信自述」同源 —— 连"我自己刚写的脚本"都必须当作需要独立验收的对象。

1.1 模型可用性事实表(CodeBuddy CLI 2.156.0,2026-10-06 实测)

这张表只陈述事实,不推荐选哪个。选哪个是派发方的决定(见 §零 铁律 4)。

codebuddy --model 实测可用 21 个,各跑一次最小调用(--effort high,提示词「只回答两个字:收到」), 21/21 成功,零失败零超时,耗时 5.5–14.8s:

档 模型 ID
混元 hy3、hy3-x、hy4-preview
DeepSeek deepseek-v4.1-flash、deepseek-v4-pro
GLM glm-5.3、glm-5.3-flash、glm-5.3-flashx、glm-5.2、glm-5.1、glm-5v-turbo
Kimi kimi-k3-2、kimi-k2.8-preview、kimi-k2.7、kimi-k2.6
其他 minimax-m3-pay、step-5-preview、space-bunny
别名 fast-model、balanced-model、deep-model
别名适合「不想记模型名」的场景:fast / balanced / deep 三档实测思考量递增 (balanced ≈ kimi-k2.7 档,deep ≈ kimi-k3 档)。派发方只说「用 deep 档」也是合法的模型指定。
耗时参考:glm-5v-turbo 最慢(14.8s)、hy4-preview 与 deep-model 次之(11.0s)、 deepseek-v4.1-flash 最快(5.5s)。⚠️ 这是单轮耗时;派活总耗时由轮数决定,别据此排序「谁最快」。
别名会随账号/版本变化 —— 派发前若某 ID 报「模型不存在」,先 codebuddy --help | grep -- --model 看当前清单, 不要照抄本表。

⚠️ 本表没有「哪个模型最适合哪类任务」的结论,那是派发方的技术选型,不是技能该给的。 若你要「编码阶段用便宜模型、设计阶段用强模型」,请拆成多批(§2.3)或多子代理(§五之三)显式指定。

二、并行与串行:准入、分工、合并纪律

📌 下面「四隔离」与「写集不相交」是通用的,但示例里的 npm ci / prisma migrate / jest 来自一套 Node + Prisma + Jest 的 monorepo。你用别的栈时,换成对应命令即可 (例如 Maven 的 mvn dependency:go-offline、Python 的 uv sync、.NET 的 dotnet restore)—— 要隔离的本质是「各自独立的依赖目录」与「各自的数据库/schema」。

曾经的写法(错的):「无头模式的监听端口由工作区路径派生:同一工作区开第二个实例必然端口冲突并挂死。」

2026-10-01 实测(CodeBuddy CLI 2.156.0,经干净启动器):

实验 结果
同目录(同一工作区)并发两个实例,纯文本回复 两次均 subtype: success
同目录并发两个实例,提示词要求真实调用 Bash 工具(关键:纯文本回复可能根本起不到 service-proxy,会让结论悬空) 两个仍均成功(各自拿到 TOKEN-A / TOKEN-B),无 EADDRINUSE

错误是怎么来的:把「宿主注入的固定 SERVER__PORT=37641 会让两个子进程撞同一端口」 过度概括成了「同工作区不能并发」。注入变量被启动器剥掉后,这个约束就不存在了。

方法论(比结论本身更重要):一条「实测沉淀」的规则,要能说清它约束的到底是哪个变量、哪个资源。 说成「同工作区」这种粗粒度,会把一个「注入导致的固定端口冲突」升级成一条假的技术限制, 进而挡住本来可行的设计。 判据:写下这类规则时追问一句 ——「如果我换一种启动方式,这条还成立吗?」 成立的是资源约束(该串行),不成立的只是启动方式的副作用(不该写成规则)。

2.1 结论:并行是支持的,但必须先做「四隔离」

默认串行的理由是工程的(共享库 / 契约 / git 工作区 + 逐批可归因审计),不是技术限制。 要并行,就逐项隔离下面这四样;缺一项就会出现「串了任务」的冲突或卡死:

# 隔离项 做法 不隔离的后果

1 目录 + git 每个并行批各建 git worktree(独立目录 / 独立 index / 独立 HEAD / 独立分支) 同工作区两批同时 commit → index.lock 争用;git add -A 把对方半成品一起暂存 2 依赖 各 worktree 各自 npm ci(node_modules 不在版本库里,worktree 不会共享) 同目录两批同时 npm ci → 彼此清空重建 node_modules → ENOENT / 假失败;prisma generate 写坏生成的 client 3 数据库 各批独立 database(CREATE DATABASE _)或连接串加 ?schema= 同库并发:prisma migrate 取 PG advisory lock 互等至超时;测试 afterEach 互相删数据;全局计数断言(family=1 这类)被别的套件干扰 → 偶发红 4 端口 + 产物 各批独立日志目录;若起服务则各用不同 PORT 业务服务端口(如 3000)撞 EADDRINUSE —— 这是业务端口,与「CLI 自身注入端口」是两码事

加一条门槛:写集必须不相交。 准入前先把两批的预期改动文件清单列出来比对; 同一个文件、同一份契约(openspec/**)、同一条 migration 序列都算互斥资源,交集非空即不得并行。

2.2 适合并行的典型形态 不同工程 / 不同语言栈:如后端 apps/api/** ‖ 前端 apps/pwa/** —— 不同测试套件、不同依赖树;
写批 ‖ 纯只读批:调研 / 代码考古 / 生成报告 / 只读诊断 —— 只读批不 commit、不跑含清库的测试、不连库;
本地 ‖ 远程:本地写批 ‖ 只能在某台机器上跑的部署批 —— 资源天然分离(不同机器、不同库)。

反例(不要并行):两个批都要改同一份源码或同一份契约、都要跑同一个库的成套测试、都要 npm ci。

2.3 并行批的合并与审计纪律 各自分支、各自 commit;由主会话审计通过后串行合并回主干(一次只合并一个,合并前重跑全量)。 绝不让两个并行批各自直接提交到同一工作区。
审计仍是逐批独立(独立复跑 + 对抗探针 + 变异对照);并行只提高执行吞吐、不减少审计量。
任一批改了 openspec/**(或任何共享契约),其余批先停下等它合并。

排活策略:任务大就拆成多次串行,每批控制在 ~15 分钟内;确有多余算力再按 §2.1 上并行。

三、写指令:这是成败的关键(比选模型重要得多) 3.1 「提一句」≠「加载技能」

只把要求写成风格描述("请保持最小改动")不会触发技能加载。 必须显式要求调用 Skill 工具, 或者把要求写进 system prompt(推荐,见 §五)。

3.2 把结论喂给它,别让它自己找

最坏的模式是「你去把这个仓库里的 X 改好」——它会把预算全花在侦察上。 好指令的骨架:

目标:
已知(不要重复侦察):

  • 入口文件:
  • 现有基建:
  • 已有结论: 改动范围:
    预算:最多读 个文件;迭代期只构建/只跑受影响的工程;收尾一次全量
    验证:
    产出:

3.3 硬性预算(照着给,别客气) 项 建议值 为什么
单次运行时长 ≲ 15 分钟 单条模型请求太久会被网关/流超时掐掉,日志里表现为 error=canceled / 499 / HTTP connection closed prematurely,零产出
子代理串行数 ≤ 2 个/批 ⚠️ 2026-10-06 实测:3 个子代理串行(architect→mechanic→auditor)跑满 5 分钟仍未结束;同一任务用 2 个子代理 16 秒完成。串行子代理的耗时是乘性叠加,不是取最大值
任务体量 超过就拆 宁跑 3 次各 5 分钟,不跑 1 次 25 分钟
思考档位 默认 high;仅超时/超预算才降 ⚠️ 旧版写「显式设中低档」是错的(误以为降档省钱)。实测反证:arXiv 2607.02436(90 次独立 agent run,固定规格 + 14 项功能评分)把 reasoning effort 从 High 提到 xHigh,首次运行完美通过率 28% → 89%,纠正性提示减少约 5 倍,成本只涨 9–29%。「探索过深」在 agent 循环里常表现为反复读同一批文件(真卡住),而不是思考深;真超时了再降档,且降的理由要写进日志,否则事后无法归因 --effort 档位名 逐字核对 ⚠️ 非法值被静默吞掉:--effort bogus-level 返回 subtype: success,与 minimal/high 的返回完全一致,无报错无警告(2026-10-06 实测,5 个模型 × none/bogus-level 全部 rc=0)。档位名拼错无法从日志发现,只能靠「改了参数但行为没变」反推 --effort medium 别指望它省成本 DeepSeek 官方原文:medium / xhigh are accepted and mapped to high;GLM-5.3 与 Kimi K3 压根没有 medium 档(只有 low/high/max)。写 medium 想省钱,很可能跑在 high 上 读文件数 明确给上限 没有上限时它会读遍全仓
思考 token 指标 不要用它判断档位是否生效 ⚠️ reasoning_tokens 是噪声指标:同一模型同一档位 3 次重复采样,值在 0~150 间乱跳(glm-5.3 high → 87/3/77,minimal → 4/37/22,两档分布完全重叠)。曾据单次采样误判「minimal vs high 差 35 倍」,3 次重复即推翻。验证档位生效要找别的判据(如 --debug 也不行:-p 模式下不打请求体) 3.4 首次失败的标准动作

表现为「跑很久 + 大量只读调用 + 零文件产出」。不要重试同一条指令,而是: ① 把上一轮侦察到的结论写进新指令;② 加硬性文件/步骤预算;③ 提高超时; ④ 只有确认是超时才降档,且日志里写明「因X 超时,从 high 降到 low」。

⚠️ 别把「降档」当默认动作。它降低的是首过率(见上表),换来的只是跑完的概率, 不是跑对���概率。先用「喂结论 + 加预算」解决探索过深,这是收益最高的手段。

3.5 派发前先做一次契约核对(派活前最高性价比的动作)

📌 本节是通用方法论,但下面的实战案例来自特定技术栈(Spec 驱动的 monorepo: openspec 管契约、Prisma + Jest 做测试)。 你不用这套栈时,保留六个动作本身(它们与工具无关),把「spec」「Scenario」 替换成你项目里对应的契约文档与验收项即可。

由派发方做,不是 CLI。理由很直接:此刻改契约最便宜 —— 一行 spec 措辞 vs. 一个批次的返工 + 一次审计。 实测战绩:开工前核对一次抓出 3 处缺口(1 处规则留白 + 1 处规则相乘无规定 + 1 处命名与约束冲突), 全部在零代码状态下修掉。核对的六个动作:

Scenario → 实现路径反查。把该域每条 Scenario 拆成 WHEN= / THEN=, 逐条确认实现里真的存在那条路径。找不到 = 「有要求、无落点」。 ⚠️ 抄漏 WHEN 等于把该路径静默移出验收范围(实战:验收用了直接建库的成员,而 Scenario 的 WHEN 是 「经邀请码加入家庭」⇒ 真实路径零断言)。
规则相乘(找交集处无规定)。把该域的新规则与既有规则两两相乘:门禁 / 凭据类型 / 状态机 / 定时路径 / 可见性。交集处若无人规定,就是缺口 —— 它不在任何单个 Requirement 里,逐条读规格永远找不到。 实战:收口规则(两个请求时点)× 信号规则(「触发那次收口的响应」)⇒ 发现第二个时点(start)漏落点; 顺手实测确认「定时路径只做过期、不做收口」⇒ 排除并不存在的第三时点。
判据留白(凡「按…判定」而无数值或可判定谓词)。spec 出现「按…规模/权重/优先级判定」「视…而定」 而没有数字、没有可判定谓词时,Scenario 就是不可判定的,实现者只能自选阈值。 实战:「家庭版信号默认按主任务规模判定」——「规模」全篇无定义 ⇒ 该 Scenario 不可判定。 处置:或裁定一个判据(并把阈值写进 design),或裁定本变更取定值、只保留取值域; 两者都必须在契约里显式写「为什么否决另一个」(否则下一批会有人重新猜一次)。
命名与硬约束的一致性。任务里出现的名字若像列名(xxx_level / xxx_status)而契约说 「不落库 / 零 migration」,就是会让实现者加错东西的陷阱 —— 改名并显式写「不得新增列」。
占位断言普查(否则与你自己的「禁改既有测试」约束打架)。派发前跑一遍:
grep -rn "不在本批|待 [0-9]|后续变更|本批不"

凡「为将来预留、届时必需更新」的断言(注释里写着「X.Y 不在本批」那种), 在本批契约生效的那一刻就会变成错的,实现方必然要在「守约束」与「守 spec」之间自行取舍 —— 实测:某批交付时实现方按 spec 改了 2 处占位断言,方向正确、覆盖面未削弱,但字面违反了硬约束, 逼得审计侧额外做一次裁定。 ⇒ 处置:在指令里点名列出这些占位断言(原断言 / 应改成什么 / 依据哪条 spec), 并给「禁改既有测试」加一条例外:「已被本批契约推翻的占位断言必须更新,且须在报告里逐条列出」。 区分判据:占位断言(注释自证「届时更新」)可改;既有行为的守护断言只许追加。 顺带:本批契约生效后,仓库里的过期注释也要一并更正(注释不实会误导下一批的审计者)。
「被测对象会不会被替身/桩换掉」(否则你新建的守卫可能是恒真的)。 派发前查一遍测试配置里的 moduleNameMapper / setupFiles / transform / 各类 mock:
grep -rn "moduleNameMapper|jest.mock|mocks|setupFiles"

若本次的契约断言依赖某个包的真实行为(装饰器元数据、框架默认序列化、DI 解析顺序……), 而该包在测试环境里正是被替身替换的那个 ⇒ 你的断言会恒真通过,且任何变异都打不红它。 实测:某仓库为绕开一个 ESM 报错,把 @nestjs/swagger 映射成无操作替身 (ApiTags/ApiBearerExt/ApiExtension 全变 no-op)。本批要新建「从产物核对 41 条鉴权声明」的守卫 —— 替身在时,该守卫必然全绿,与实现是否正确无关。 ⇒ 处置(三选一,必须在指令里写明选哪个):① 让守卫改从真实包读元数据(可能要先修那条 ESM 报错的根因); ② 显式用 jest.mock/loader 局部打桩,只桩掉出问题的那一个子模块;③ 换一种不依赖该包的方式取证据。 MUST NOT 默认「守卫能读到真实行为」 —— 恒真断言比没有断言更糟:它会给你一个「已验证」的假信号, 而你的变异对照也会因为同一个替身而打不红(形成闭环自欺)。

三条出口:① 只是漏落点 ⇒ 直接补 tasks.md;② 涉及产品语义 ⇒ 问用户裁定,再落到 spec + design; ③ 任何改动后 openspec validate --strict 必须绿。 契约没补齐前不派发 —— 派出去的不是代码,是「一个替你猜契约的 agent」。

四、无头模式下的用户级 hooks:优先级最高的坑

如果宿主用户级配置(~/./settings.json)里被工具(如团队脚手架)注入过 hooks, 无头运行会被它们掐死,典型症状:

钩子命令本身是 CMD 语法(2>nul / exit /b 0),却由 bash 执行 → nul: Permission denied;
钩子会等 stdin 到 EOF:stdin 关闭时 6.8s 返回,stdin 保持打开时 32.7s —— 超过钩子自带的 10s 超时 → 判定 UserPromptSubmit operation blocked by hook → 整轮失败。

绕法:只加载项目级设置(CodeBuddy CLI 为 --setting-sources project),牺牲用户级插件配置。 另外:无头运行一定要 &1

✅ 实测:第一轮 --effort minimal 记下编号 A1,第二轮 -c --effort high 准确读出 A1 ⇒ 上下文跨档位保留,换档有效。

⚠️ 三条限制:

-c 是「继续该目录最近的对话」,按目录定位,不按任务名 ⇒ 同目录下多批并行会串味, 此时必须改用 -r 显式指定会话。 第二批的 --max-turns 是新的上限,不继承第一批剩余额度。
每批的日志要分别落盘(log1.json / log2.json),审计时逐批独立复核(§七)。

做不到的事:单次运行内部,主 agent 无法给自己或已派出的子代理改档。 需要「设计→编码→测试」三段不同档位时,要么拆三批,要么三段各配一个子代理(§五之三)。

六、权限模式与运行
无人值守运行必须显式给「自动批准」档(CodeBuddy CLI 为 --permission-mode bypassPermissions), 否则会在某个确认点上原地等死。
但:自动批准只应作用于这个独立 CLI,不要让宿主的审批体系一并放开。危险动作 (push --force / reset --hard / 删库 / 改生产)仍然要求人在对话里明确授权。
⚠️ 省略这个参数的后果实测过:子代理的 Edit 会被拦,而它的自述是 「子代理已调用,但实际编辑被非交互权限限制阻断」,文件实际未改 —— 报告基调却像任务已完成。凡写批次必给权限档,审计必独立确认文件真改了(§五之三 事实2)。
统一日志落盘,便于事后审计:

mkdir -p .cli-runs

LOG=".cli-runs/$(date +%H%M%S)-.log"
timeout 1500 node .workbuddy/bin/codebuddy-cli.js
-p "$(cat .cli-runs/.prompt.md)"
--model --effort high
--permission-mode bypassPermissions
--output-format json --max-turns 150
"$LOG" 2>&1

echo "exit=$? bytes=$(wc -c