
这是什么
一个 Agent Skills 技能包:每份技能把某一种编码 agent CLI 当作实现者来驱动,而审查与提交始终留给编排方。所有技能形状一致——一份写给「没有聊天记录的新会话」的任务书、一个负责无头启动并轮询的 scripts/relay.mjs、四份参考文档,以及一份说同一套契约的 result.json:状态、退出码、信号、实现者自己的最终报告、它改过的文件,以及在该 CLI 暴露会话 id 时一并记下。今天共发了十七种实现者,从 Claude Code、Codex、Cursor 到 Antigravity、Grok、Kimi、Qoder、Copilot、Warp 与 Command Code;另有一个工具类技能 delegate-setup 负责探测机器上装了哪些 CLI 并写出编队车道。这个包里没有任何东西会提交,而当某条 CLI 根本拦不住写入时,它会被写成脚注,而不是被抹平。
谁做的一个个人账号加上很长的贡献者尾巴。390 次提交里有 285 次挂在作者账号下——用的是两个名字 Ahmed Nagdy 与 Ahmed Mohammed,共享该账号已验证的邮箱——另有 25 人落地过改动,最勤的三位分别是 23、10 与 7 次。几乎所有工作都有共同署名:99 条提交尾注署了模型或工具,出现最多的是 Claude Fable 5、Claude Opus 5 与 Cursor;390 次提交中有 377 次能关联到 GitHub 账号。
它是怎么搭起来的
组成 · 6一个把同一份契约重复十七遍的技能包。每个实现者拿到自己的目录,里面是同样的四份文档与一个派发脚本,于是编排方只需要学一个循环——写任务书、派发、轮询、审查、落地——就能换掉底下的 CLI。两个后果决定了大部分代码。第一,技能是单目录安装、没有打包器,所以每个 relay.mjs 都自成一体,并刻意复制那些共享辅助函数;这些副本之间的漂移靠逐字节一致性测试来管,而不是靠共享源码目录。第二,这个包拒绝接管提交:relay 停在 diff 与结构化结果上,而自主权限用每条 CLI 自己的词汇描述,包括那些根本拦不住的情况。delegate-setup 刻意是唯一的工具类技能,而且只写配置,于是用户一直想要的编排策略留在包外。
- skills/<cli>-delegate/ ×17
- 十七份实现者技能,每份是一个
SKILL.md(触发用 description 控制在 1,024 字符以内)、恰好一个scripts/relay.mjs,以及同样的四份参考——写任务书、派发与轮询、审查与落地、多任务队列。relay 从 Qoder 的 25,706 字节到 Command Code 的 58,241 字节,目录从 44 KB 到 105 KB。 - skills/delegate-setup/
- 唯一的工具类技能:
discover.mjs探测装了哪些实现者 CLI,config.mjs校验并写出车道表,lane.mjs为 relay 解析车道并在车道缺失、项目配置未受信任或实现者不匹配时大声失败,implementers.mjs保存二进制与档位的共享表。它从不派发编码任务。 - test/
- 26 个 relay 测试模块共 225 KB,另有 smoke、parity、独立安装与事件扫描四个入口,以及一个会安装 shim、并提供 CommonJS 与原生 C# 两种假 CLI 的测试装置。把新技能登记进
test/harness/constants.mjs才是让它进入超时与中止矩阵的动作,而套件会在有技能目录漏登记时直接失败。 - .github/ 与 .cursor/
- 只有一个工作流
relays.yml:在 Ubuntu 与 Windows 上用 Node 22 依次跑 parity、独立安装、事件扫描与 smoke,并只在 Linux 上校验发布用的技能清单。issue 模板把一次认领变成四个必答项——非交互命令、机器可读输出、自主权限,以及确认没有已开的认领覆盖这条 CLI——旁边还有一份 Cursor 云环境配置与安装脚本。 - AGENTS.md、CONTRIBUTING.md 与 docs/plans/
- 家规所在:一张受控词汇表给每个概念钉死一个词并禁用同义词,一份「见即封杀」名单涵盖自造的伞形术语、提到作者本机或本机配置的说法,以及无法验证的断言;此外是合入清单与发布仪式,以及一份 7,682 字节的 relay 去重方案——它被取代的第一版作为附录留在同一文件里。
- skills.sh.json 与两个 schema id
- 包清单把十七份实现者技能归在一个分组下、把
delegate-setup归在 Setup 下;两份 JSON 契约承担各部分之间的数据:delegate-fleet.v1描述全局或项目级车道表,项目那份必须与一次批准哈希吻合,否则失败关闭;delegate-relay.result.v1描述每次运行的结果文件。
取舍,以及它替代了什么
每个实现者一个自成一体的 relay,再加一套逐字节一致性测试 替代 代码生成器、共享片段或打包器
技能是逐个目录安装的,跨目录 import 会让单技能安装直接崩掉。采用的方案还进一步论证:不会漂移的重复只是占磁盘,这些辅助函数几乎没有改动,而一条六十行的比对闸门就能挡住真正造成伤害的那件事——于是机器被拒绝,闸门被建起来。
relay 永不提交,由审查者落地 替代 让实现者把活干完,连提交一起做掉
这是不变量而不是偏好,并且专门针对唯一不听话的实现者执行:Aider 默认提交,还会把用户先前未提交的脏改动一起提交,所以它的 relay 永远传
--no-auto-commits与--no-dirty-commits,且不把它们开放成选项。一份结果契约,以及每份技能恰好四份参考文档 替代 每种 CLI 各定一套结果形状
清单把形状钉死——四份参考,「not three, not five」,因为形状就是契约——而每个 relay 都写
delegate-relay.result.v1。正因为如此,编排方只需学一次循环,换实现者时不必重新学怎么读结果。用各条 CLI 自己的术语描述自主权限,并公开它管不了的部分 替代 在整个编队上假装只有一种只读模式
有些实现者没有强制的只读模式,还有一种在无头运行时根本无法阻止写入。规则写得很直白:没有只读模式的 CLI 可以合入,但暗示自己有只读模式的技能不行——所以这些缺口变成脚注与触发器,而不是沉默。
把编排策略留在包外 替代 在包里附带编队编排器或故障转移控制器
两个提案得到的是同一个答复:这个仓库每种 CLI 实现者只发一份技能,外加
delegate-setup;再做一个跨实现者派发、负责故障转移并承载编排策略的工具类技能超出范围。那一层的设计讨论串留在它自己的 issue 里,而不是被吸收进来。用附注 git 标签钉住安装 替代 依赖技能 frontmatter 里的
metadata.versionSkills CLI 按 git ref 安装,所以发布仪式把每份技能的版本号更新只为告知,真正钉住的是那一个附注标签。两份 JSON 契约 id 单独版本化,只在形状破坏时才动,这样一次文档发布不会看起来像一次破坏性变更。
依据README.md(30,078 字符)、CONTRIBUTING.md、AGENTS.md、docs/plans/relay-core-dedup.md、skills/delegate-setup/references/schema.md、skills.sh.json、.github/workflows/relays.yml、各 issue 与 pull request 正文及评论,以及完整的 158 个文件树及其体积。
制作过程
6 个阶段- 01
每种实现者一份技能,以及一条由两次白干换来的认领规则
仓库建于 2026-06-14,第一次提交只加了一份技能
codex-delegate和它周围的打包脚手架。三个月后它已经带着十七份实现者技能加delegate-setup上线,390 次提交而尾部明显收窄:六月 5 次、七月 151 次、八月 197 次、九月 37 次。对一个个人仓库来说,它的协作面相当宽——102 个 pull request 里合并了 71 个,38 个 issue 关掉了 25 个,25 位贡献者,作者之外最勤的三位各有 23、10 与 7 次提交。CONTRIBUTING.md开门见山解释这条规矩为什么存在:有两个人各自独立地把同一份委派技能做了一遍,两次都白干了,所以实现者要先开 issue 认领再动手。认领模板要求写清该 CLI 精确的非交互命令、relay 能从它的输出里解析出什么、它的自主权限怎么设,并且明说认领「not an assignment, not exclusive」。合入清单则用来裁决撞车的 pull request:满足条目更多的那份合并,平手时先看验证证据、再看谁先认领,而落选那份里独有的改进会被一并拉进来,并在落地的提交里按编号致谢。 - 02
十二天里打了七个附注标签,而发布单位是一个目录
这里的发布就是 git tag,不是 GitHub release:一共七个标签,没有一个发布对象。七个全部落在十二天里——
v0.2.0在 2026-08-04 的 18:07,v0.3.019:51,v0.3.120:33,v0.4.021:55,一个晚上打了四个标签,接着第二天上午v0.4.1、2026-08-08 的v0.4.2、2026-08-16 的v0.5.0;九月的 37 次提交一个都没打。CONTRIBUTING.md把仪式写死:先在master落地,把每份技能的metadata.version改成同一个 semver,再建附注标签并推送——因为安装方用npx skills add amElnagdy/delegate-skills@v0.2.0钉版本,而不是读 frontmatter。两个 JSON 契约 id,delegate-fleet.v1与delegate-relay.result.v1,单独版本化,只有形状破坏时才动。真正让打包决定变得吃重的是:技能是逐个目录安装的,没有打包器、没有依赖图,所以skills/<name>-delegate/必须能独立加载——一个普通的跨目录 import 会让单技能安装直接崩掉。这个约束正是为什么每个 relay 都自带一份共享辅助函数,也是为什么用一套逐字节比对测试去管这些副本,而不是搞一个共享源码目录。 - 03
relay 永不提交,而有一种实现者得专门拦住它
组织原则是一次分工:实现者修改真实工作树、写出结构化的
result.json,然后停手;编排方拿 diff 重跑项目自己的验收命令,并亲自提交。README 把它写成不变量——relay 永不提交,因为提交属于审查者——而且同样的强硬也被用在「技能允许声称什么」上。旁边还有三条:必须是另一条 CLI 去改真实工作树,好让git diff成为交付物;脚本只用 Node 内置模块,不带依赖、不自己联网、不读写凭据、不上报;每条 CLI 的自主权限都要用它自己的术语描述。这条规则有一个写明的边界情形,而不是例外:Aider 默认会提交,它的--auto-commits与--dirty-commits都默认为真,而后者会在动手之前就把用户尚未提交的旧改动提交掉。所以它的 relay 永远传--no-auto-commits与--no-dirty-commits,并且两个都不开放成选项。把它们串起来的说法在 README 里:这是一个循环,而不是转发器——转发器交出一件事、拿回输出,而这里你要派发、轮询、审查、落地,无论一件事还是一整条队列。 - 04
十七种 CLI,各用各的术语描述,包括拦不住的地方
十七种实现者 CLI 提供的安全原语并不相同,而文档拒绝假装它们相同。Command Code 的无头模式只有两个状态、中间什么都没有:
-p运行会收走写、编辑与 shell 工具,--yolo则放开进程能碰到的每一个工具,而--permission-mode auto-accept与--tools-all并不会打开那道写闸门——于是任务书里列的路径只是指引而非围栏,唯一真正的边界是容器。Kimi、Pi 与 Warp 干脆没有 CLI 强制的只读模式,所以touchedFiles与 diff 是审查者拿来对照的东西,不是保证。Grok 无头运行时无法被阻止写入;relay 会针对检测到的 Git 可见改动报出一个三态readOnlyViolation触发器,脚注则说明它既不强制执行也不做归属。ZCode 更怪:它的 CLI 装在桌面应用里,四种文档化的模式里只有plan与yolo能在无头下工作,因为build与edit会拦下每一个写工具、然后改完零个文件退出 0——所以 relay 直接拒绝这两个模式,而不是把它报成一次成功。逐个维护它们正是大部分工作,而分歧同样被写下来:OpenCode 的 relay 每次派发前都探测已装 CLI 的版本,因为 2.x 把推理档位写成model#variant,而 1.x 仍然收--variant。 - 05
十个几乎一模一样的 relay,以及一次抽样错误改掉的方案
到八月初,仓库里已经有十个
relay.mjs,共享着 80% 到 90% 近乎逐字相同的代码,docs/plans/relay-core-dedup.md记下了后来的处理办法。它自己的结论是:真正的问题是漂移,不是重复——共享辅助函数已经悄悄分叉,2026-08-04 的逐字节检查发现killChild里的空值保护只存在于 Claude 那一份,另外九个遇到空子进程会直接抛错;时长解析在十份里有八份用 BigInt 变体,而 Antigravity 与 Pi 用 Number 变体。文件里还留着它自己第一版的失败:那一版只把 Claude 的 relay 和 Codex 的比了一遍,然后假定另外八个和 Claude 一致,实际上它们和 Codex 一致——于是那个号称不改行为的批次,其实改了九个文件的行为。最终采用的形状是先把分叉的实现统一一次、并把更强的行为带过去(只有 Vibe 给git status探测加了上界,而现在的标准实现给十个都加了上界),再加一个约六十行的逐字节一致性测试,外加一个「独立安装」检查:把单份技能目录拷到临时目录里,在那里跑relay.mjs --help。方案明确拒绝了代码生成器与共享片段,也把只出现一次的原子写副本继续内联,并为每一个拒绝给出理由,好让这些决定日后能被重新审视,而不是被反复争论。 - 06
那些失败报告换来了什么,以及这个项目拒绝吞下什么
这些 issue 对「委派怎么坏掉」写得异常具体。编号 126 讲的是一种实现者正常退出、却留下一个继承了 stdio 管道的游离孙进程:
exit触发了,close永远不来,而所有 relay 都只认close,于是整次运行连result.json都没有——而挂钟看门狗也帮不上忙:不设超时就会永远挂着,设了超时则会把一次其实成功的运行报成超时。编号 125 是一场被摊在明面上的分歧:有人称 Codex 的版本预检在 Windows 上每次派发要花约四秒,另一位用八次运行里 126 到 163 毫秒的实测回应,并请对方说明自己机器的配置。边界同样被明确守住。有人提议在编队之上加一层持久编排层,得到的回复是这个仓库每种 CLI 实现者只发一份技能外加delegate-setup,那样一层属于它自己的项目;另一个想在多个实现者之间派发并做故障转移的工具类技能也以同样理由被关掉,引的是贡献指南里「不要再造一个工具」那条;而 88 号 issue 作为那一层的设计讨论串一直开着,提议者描述的 Claude、Codex、OpenCode 与 Antigravity 车道,最后由一个做同样事情的姊妹项目给出了回答。树里最后一次提交是 2026-09-20 的合并;Devin、Kiro、Kilo 与 Muse 的实现者 pull request 仍然开着。
相关档案
全部档案 →第 061 号
Reticle
一个 MCP 服务器加一个只在开发期生效的 SDK:让编码 agent 从应用内部去读、去操作一个正在运行的 web 或桌面应用,然后给出判词和该改的文件与行号,而不是一张截图。
第 070 号
OpenChatCut
一个本地优先的视频剪辑器,剪辑方式是跟它说话:内置 agent 与外部 Codex、Claude Code 会话调用的是界面自己在用的同一套剪辑工具,于是每一处改动都落在一条真实的多轨时间线上——是片段、转场、字幕、特效或音频,仍然能拖、能撤销、能导出。工程与素材留在本机,预览与最终渲染都出自 Remotion。
第 062 号
Ponytail
一套装进编码 agent 的规则与 skill 包:写代码之前,agent 先停在七级阶梯上第一个成立的那级——不必存在、代码库里已有、标准库能做、平台原生能力能做、已装的依赖能解决、一行能写完——另外六个命令分别用来调档位、审 diff、审整仓库、把欠下的妥协收进台账、打印实测记分板、列出全部命令。