其余宿主适配层各自对接谁

2026-08-10

CLI-Anything 这个仓库里,cli-anything-plugin/ 是给 Claude Code 用的那份插件,我们采集时(2026-08-10,对应仓库快照 39634a6)它有 26 个文件、5865 行。但仓库根下还并排着另一批以 agent 宿主命名的目录:codex-skill/hermes-skill/reasonix-skill/qoder-plugin/opencode-commands/.pi-extension/,另外还有一个只放测试的 skill_generation/

第一眼看过去,很容易把它们当成同一个插件的六份移植——同一套方法论,换个宿主重新包一遍。真去读安装脚本会发现不是这么回事:这六家「装上了」这三个字,含义完全不在一个层级上,而且更新语义各不相同。这篇就把这六个目录逐个拆开,落到具体文件和行号上。

先看体量:最大的 735 行、最小的 155 行

find <dir> -type fxargs wc -l 数,我们采集时六家的规模是这样的:

目录宿主文件数总行数最大的那份文件
.pi-extension/Pi Coding Agent4735tests/test_extension.test.ts 285 行
opencode-commands/opencode5568cli-anything-list.md 188 行
codex-skill/Codex5379SKILL.md 154 行
reasonix-skill/Reasonix5330SKILL.md 164 行
hermes-skill/Hermes Agent4183SKILL.md 132 行
qoder-plugin/Qodercli1155setup-qodercli.sh 155 行

qoder-plugin/ 整个目录只有一个 shell 脚本,hermes-skill/ 也只有一份 SKILL.md 加两个安装脚本和一个 4 行的 yaml。这个体量差本身就是线索:它们做的根本不是同一件事。

四种接入契约

一、复制快照:codex-skill

codex-skill/scripts/install.sh 的落点是 ${CODEX_HOME:-$HOME/.codex}/skills/cli-anything,目录已存在就拒绝覆盖并退出(第 10 到 11 行、第 28 到 32 行)。装的时候它不只是把自己拷过去,而是把上游 cli-anything-plugin/ 的一整套资源 vendor 进这个 skill 目录:HARNESS.mdcommands/*.mdguides/*.mdrepl_skin.pypreview_bundle.pyskill_generator.pytemplates/*,外加仓库 docs/PREVIEW_PROTOCOL.md(第 49 到 56 行)。落盘方式也考究:先 mktemp 一个暂存目录,写完再 mv 过去做原子落地,配 trap 清理(第 41 行、第 58 行、第 34 到 39 行)。

这一类的含义是:安装那一刻,上游内容被复制成了一份快照。仓库后来改了 HARNESS.md,这份已装好的 skill 不会跟着变。

二、只复制自身:hermes-skill、reasonix-skill

hermes-skill/scripts/install.sh 的落点是 ${HERMES_HOME:-$HOME/.hermes}/skills/cli-anything-hermes,动作只有一个 cp -R 拷自身目录,不 vendor 任何 plugin 资源(第 7 到 18 行)。也就是说宿主那边拿到的只有一份 SKILL.md(132 行)和一个 4 行的 agents/hermes.yaml,方法论的完整版并不在里面。

reasonix-skill 结构同理,多一份 116 行的 README。它们的 SKILL.md 承担的是「把方法论压缩进一份文件」的角色,而不是「把方法论指到某个路径」。

三、只注册路径:qoder-plugin

qoder-plugin/setup-qodercli.sh 一个文件都不复制。它做的是把 cli-anything-plugin绝对路径注册进 ${QODER_HOME:-$HOME}/.qoder.jsonplugins.sources.local[] 数组(第 41 行、第 103 到 109 行)。有 jq 就走 jq 改写、并先备份出一份 .qoder.json.bak;没有 jq 且配置文件已经存在,脚本直接退出,把需要手动加进去的 JSON 片段打印出来(第 75 到 84 行、第 98 到 100 行)。

这一类的含义正好和第一类相反:从脚本写入的内容看,宿主拿到的是仓库里那份原件的绝对路径,不是一份拷贝。至于 Qodercli 什么时候会重新读取这条路径下的内容,仓库里没给依据,我们也没有实测,这里不下结论。可以确定的只有一点:把仓库目录挪个位置或者删掉,这条登记下来的路径就指空了。

四、上下文注入:.pi-extension

.pi-extension/cli-anything/index.ts 依赖 @mariozechner/pi-coding-agent 的 ExtensionAPI(第 18 行),注册 5 个 slash 命令:/cli-anything:refine:test:validate:list(第 8 到 13 行)。它的工作机制在 README 第 87 到 91 行写得很直白:读 HARNESS.md 加上对应的 command spec,拼成一条用户消息,经 pi.sendUserMessage() 送进会话(index.ts:57-84)。

安装落点是 $HOME/.pi/agent/extensions/cli-anythinginstall.sh 会在其下建 commands/guides/scripts/templates/(和 tests/)(第 17 行、第 68 到 71 行、第 119 行)。它的 README 里还有一句把整个格局定死的话:命令 spec、guides、脚本、模板、HARNESS.md 的规范源头唯一,一律以 cli-anything-plugin/ 为准,install.sh 负责复制过去(第 79 到 83 行)。

opencode-commands/ 的接入方式则最简单:5 个 md 文件,连安装脚本都没有,就是宿主自己的命令文件格式,直接放进去就算接上了。注意这里说的「简单」指的是接入契约,不是体量——按上一节的表,它 568 行,在六家里排第二。

反直觉的那一处:被移植的其实是路径

看完这四类接入契约,容易得出的结论是「各家包装方式不同」。但真正的难点不在包装,在同一份 HARNESS.md 在每个宿主下的落点都不一样,于是每一家都得自带一张路径重映射表

codex-skill/SKILL.md 第 44 到 54 行就是这么一张表,典型的一行是 guides/… 要读成 references/guides/…。因为 vendor 过来的时候目录被重排了,而文档里的相对路径写的还是仓库里的样子。

pi 扩展那边更明显。它注入的消息里带一段 Path Remapping Rules(index.ts:74-80),把容器路径 /root/cli-anything/<software>/ 映射到当前工作目录,把 cli-anything-plugin/*.py 映射到扩展自带的 scripts/ 目录。

/root/cli-anything/ 这个前缀不是凭空来的。仓库里 HARNESS.md 的位置本身就有两种口径:plugin 的 README 在 Prerequisites 里写它在 ~/.claude/plugins/cli-anything/HARNESS.mdcli-anything-plugin/README.md:47),而同仓的 scripts/setup-cli-anything.sh 第 38 行检查的是硬编码的 /root/cli-anything/HARNESS.md,第 102 行也照这个路径打印。两处写的不是同一个路径,这是两个可以各自核对的事实,我们只陈述到这里。

把这三处串起来看,这套多宿主适配的实质就清楚了:功能本体(方法论文本、生成器脚本、模板)只有一份,放在 cli-anything-plugin/;每个宿主适配层的主要工作量,是把这份内容搬到宿主认的位置,再补一张表告诉 agent「文档里写的路径请按这张表换算」。这也解释了为什么 qoder-plugin/ 一个文件都不用复制却也能工作——它压根没搬,直接让宿主去引用原地址,自然也就不需要重映射。

「对接谁」的第二层含义:翻到宿主的工具名上

除了路径,各家 SKILL.md 还要把动作翻译成宿主自己的工具名。这一层的差异同样是逐字写在文件里的:

  • hermes-skill/SKILL.md 第 29 到 35 行列的是 Hermes 内置工具绑定:terminal / execute_code / delegate_task / read_file / write_file / patch
  • reasonix-skill/SKILL.md 第 33 到 42 行列的是 bash / write_file / edit_file / multi_edit / read_file / grep / glob / ls / web_fetch,外加两个可选的 mcp__codegraph__searchmcp__codegraph__context
  • codex-skill/SKILL.md 第 12 到 22 行给的是一条 6 级方法论回退链,最后一级才是「用下面这份浓缩规则」

三家 agents/*.yaml 倒是整齐:openai.yamlhermes.yamlreasonix.yaml 都是 4 行,结构相同,就 interface.display_name / short_description / default_prompt 三项。

元数据上还有几处小分叉,照着抄配置时容易踩:hermes-skill/SKILL.md 第 2 行的 frontmatter namecli-anything-hermes,与其余适配层的 cli-anything 不同;reasonix-skill/SKILL.md 第 4 行多一个 runAs: subagentopencode-commands/ 的 5 个 md YAML frontmatter(含 description,其中 cli-anything.mdcli-anything-refine.md 还有 subtask: true),而 cli-anything-plugin/commands/ 下那 5 个 md 没有 frontmatter,直接以 # … Command 开头。命名风格也分两路:opencode 用连字符(cli-anything-refine),plugin 那边用冒号子命令(cli-anything:refine),Qodercli 打印出来的则带双前缀,形如 /cli-anything:cli-anything <path>setup-qodercli.sh:150)。

顺带一个跟本篇直接相关的命令面差异:pi 扩展注册的是 5 个命令,opencode-commands/ 也是 5 个 md,cli-anything-plugin/commands/ 同样 5 个(cli-anything.md 147 行、list.md 237 行、validate.md 123 行、refine.md 104 行、test.md 73 行)。但 cli-anything-plugin/verify-plugin.sh 第 24 到 27 行只逐个检查其中 4 个,没有检查 commands/list.mdscripts/setup-cli-anything.sh 第 88 到 91 行打印可用命令时也只列了 4 条。README 第 122 行把 /cli-anything:list 列为正式命令,commands/list.md 也确实存在且有 237 行。这几处数目不一致,我们只陈述到这里。

测试覆盖也不是一碗水端平

按目录文件清单看,六家里只有两家自带测试:codex-skill/tests/test_install.sh(92 行)和 .pi-extension/cli-anything/tests/test_extension.test.ts(285 行,其中有 14 处 it( 用例)。hermes、reasonix、qoder、opencode 四家的文件清单里没有测试文件。

另外那个容易被忽略的 skill_generation/ 目录,整个只有一个文件 tests/test_skill_path.py(198 行、11 个测试函数),验证的是 pip 安装之后 SKILL.md 能不能被 ReplSkin 自动发现;它搭测试树的方式是从 cli-anything-plugin/repl_skin.py 复制源文件(第 1 到 7 行、第 36 到 37 行)。也就是说「plugin 是上游、其余是下游拷贝」这条关系,连测试代码都是照这个方向写的。

你可以自己跑一遍的核对动作

上面每一条都能在 clone 下来的仓库里自己复现:

# 1. 六家的体量
for d in codex-skill hermes-skill reasonix-skill qoder-plugin opencode-commands .pi-extension; do
  echo -n "$d "; find "$d" -type f | wc -l
done

# 2. 复制快照 vs 复制自身 vs 只注册路径
grep -n 'cp \|DEST_DIR' codex-skill/scripts/install.sh hermes-skill/scripts/install.sh
grep -n 'plugins\|qoder.json' qoder-plugin/setup-qodercli.sh

# 3. frontmatter 的三处分叉
head -6 hermes-skill/SKILL.md reasonix-skill/SKILL.md opencode-commands/cli-anything.md
head -3 cli-anything-plugin/commands/cli-anything.md

# 4. HARNESS.md 的两种路径口径
grep -rn 'HARNESS.md' cli-anything-plugin/README.md cli-anything-plugin/scripts/setup-cli-anything.sh

以上为按仓库中的文件与参数语义组合的只读核查示例,未经实测,以官方文档与脚本的实际输出为准。第 2 组命令能直接把三类接入契约的差别看出来:codex 那份有一串把 plugin 目录里的文件拷进暂存目录的 cp,hermes 那份只有一条 cp -R 拷自身目录,qoder 那份一条 cp 都没有。

Windows 侧还有两点要单独提。codex、hermes、reasonix 三家都各带一份 install.ps1(分别 67、26、24 行),我们没有读这三份脚本的内容,它们与对应 install.sh 的行为是否一致,这里给不出结论。另一点是 cli-anything-plugin/scripts/setup-cli-anything.sh 第 14 到 25 行:它在 Windows 的 bash 环境下会检测 cygpath 是否缺失,缺了就报错退出。

一句必须说清的边界

这一整层适配层,做的都是「把方法论和命令 spec 送进某个 agent 会话」这件事,它们本身不操控任何桌面软件。真正干活的是被生成出来的那些 harness——那才是会在你本机起子进程、执行外部程序与脚本的部分,而且大多要求你自己先把宿主软件装好(例如 krita 的 e2e 测试文件头明写这些用例调用真实的 Krita,且没有优雅降级)。

顺着这条边界还有一件事值得提醒:注册表里有条目不等于这个能力你装上就能用。cli-hub/README.md 第 5 行与 setup.py 第 54 行的描述都写的是 “40+ CLI harnesses”(README 自称),而我们实读 registry.json 是 79 条、public_registry.json 是 22 条、合计 101 条。条数与「能不能在你机器上跑起来」是两回事,前者只是一份清单。

选哪一家适配层,取决于你日常用哪个 agent 宿主,这一步没什么可挑的。真正需要提前想清楚的是更新语义,而这一点只能按脚本语义来判断:qoder 那种「只注册路径」的形态,宿主拿到的是仓库原件的位置;codex 那种 vendor 复制,宿主拿到的是安装那一刻的快照;hermes、reasonix 拿到的则只是一份压缩过的 SKILL.md,完整方法论仍在 cli-anything-plugin/ 里。宿主各自在什么时机重新读取这些内容,仓库文档没写,我们也没跑过,不做推断。这三种没有优劣之分,但装之前得知道自己装的是哪一种。


本文依据 CLI-Anything 官方仓库(github.com/HKUDS/CLI-Anything)的 README、registry.jsondocs/ 与各 agent-harness/ 下的源码整理,核对日 2026-08-10,对应仓库快照 39634a6。 本文内容为仓库源码与文档口径,我们没有安装或运行过其中任何一个 harness, 也没有在本机驱动过任何一款宿主软件,因此不涉及实际操控效果的任何描述。 这类 harness 会在本机执行外部程序与脚本,是否使用请结合自身环境评估。 注册表与 harness 内容随上游更新而变动,请以仓库最新内容为准。 安全相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。