`registry.json` 的结构与那 79 条记录

2026-08-10

想搞清楚 CLI-Anything 到底覆盖了哪些软件,很多人第一反应是去数 README 的演示表格。更省事的做法是直接读仓库根目录的 registry.json——它是这个项目对外声明”我这里有哪些 CLI”的那份索引。

但这份索引读起来有个坑:它是一张指针表,不是一张能力清单。79 条记录里的每一条,都只是告诉你”某个东西在哪儿”,至于指过去有没有东西、能不能跑起来,是另一回事。下面按我们采集时(2026-08-10,仓库快照 39634a6)实读到的结构逐层拆。

顶层:两个键,一个日期

用 Python 把它 load 进来看顶层键,结果只有两个:metaclis

meta 三个字段:repo 指向 https://github.com/HKUDS/CLI-Anythingdescription 是 “CLI-Hub — Agent-native stateful CLI interfaces for softwares, codebases, and Web Services”,updated 写的是 2026-06-19registry.json:3-5)。

clis 是数组,我们实读到的长度是 79

这里第一个可复现的核查动作,就是别用眼睛数、也别用 grep -c 数大括号——JSON 里嵌套对象会让你数出一个虚高的值。老老实实解析:

import io, json
d = json.load(io.open('registry.json', encoding='utf-8'))
print(list(d.keys()), len(d['clis']))

meta.updated2026-06-19 值得单独留意:它是注册表自己声明的更新日期,而我们读到的仓库快照是 39634a6(2026-08-03 提交)。这两个日期不是一回事,写文章、做统计时别把 updated 当成”仓库最后一次动 registry 的时间”来用——它就是文件里的一个字符串字段。

15 个字段,只有 10 个是全覆盖

把 79 条记录的键取并集,得到 15 个字段名。但这 15 个字段的出现频次差别很大:

字段出现次数
name / display_name / version / description / requires / homepage / install_cmd / entry_point / skill_md / category各 79
source_url78
contributors78
install_strategy1
contributor1
contributor_url1

这张表要这么读:上面十行才是你可以放心当作”一定存在”的字段,写解析代码时可以直接 entry['name'];下面五行都得先判空。尤其那三个只出现 1 次的字段,是名副其实的孤例——

  • 唯一带 install_strategy 的条目是 siyuan,值为 "pip"
  • 唯一缺 contributors、改用 contributorcontributor_url 两个标量字段的条目是 qgis

你可以自己跑一遍 collections.Counter 更新每条记录的 keys() 来复现这张频次表,几行代码的事。

反直觉的那一处:字段规范是”必填”,实际记录并不齐

CONTRIBUTING.md 里对 registry 条目的字段有明确规定:11 个字段全部标为 “Required”,其中 contributors 要求是 {"name","url"} 形式的对象数组,仓库内 harness 的 skill_md 要求写成根目录 skills/ 树下的相对路径(CONTRIBUTING.md:59-72)。

而我们实读的 79 条记录里,至少有三处与这份规定对不上:

  1. qgis 用的是 contributor + contributor_url 两个标量字段,不是 contributors 数组(CONTRIBUTING.md:72 要求的是数组);
  2. calibrelldbqgisunrealinsightsmacrocli3mfminimax 这 7 条的 skill_md 没走 skills/ 前缀,写的是各自 harness 内部的路径(这 7 个路径我们用 os.path.exists 逐条查过,文件都在);
  3. 有 5 条记录的 skill_md 直接是 nulladguardhomecomfyuimermaidsketchclibrowser

两处口径不一致,位置都在上面写清楚了:一边是 CONTRIBUTING.md:59-72,一边是 registry.json 里对应的那几条。以我们实读的仓库状态为准。说完差异就到这儿,我们不去推断哪边”该改”。

对读者的实际影响很直接:如果你打算写脚本消费这份注册表,别按 CONTRIBUTING 的字段规格来写解析器,按上面那张频次表来写。contributors 当必填数组直接展开的代码,会在 qgis 这条上炸;把 skill_md 当非空字符串直接拼路径的代码,会在那 5 条 null 上炸。

skill_md:三种取值,指向三个地方

skill_md 是这 15 个字段里信息量最大的一个,因为它决定了”给 agent 读的那份说明书”到底在哪。79 条的取值分成三类:

  • 63 条是仓库内的相对路径——路径本身指向本仓库,不必去外部取(其中 7 条不在 skills/ 树下、指向各自 harness 内部,这 7 条我们逐条查过,文件都在;其余各条是否都命中真实文件,我们没有逐条核实);
  • 11 条是远程 URLzoteroopenwebuiueatelierve-twinistatainkstitchhacker-feeds-clitinyfishmeerk40tpalmiermagnific)——这些说明书不在这个仓库里,要去别处取;
  • 5 条是 null——注册表这一栏是空的。

第三类里有个可核查的细节:那 5 条虽然 registry 里写着 null,但 skills/ 目录下实际存在 cli-anything-adguardhomecli-anything-comfyuicli-anything-mermaid 三个目录。也就是说目录已经建好了,注册表这一栏没回填。核查动作很简单:拿这 5 个 name 去 ls skills/ 的结果里比一遍就知道了。

这一栏正是”注册表条目 ≠ 可用能力”最直白的体现。一条记录出现在 clis 数组里,只能说明这份索引收录了它;它的说明书是本地文件、是远程链接、还是干脆没填,得逐条看。

source_urlinstall_cmd:装的是谁的代码

79 条里有 78 条带 source_url(缺这一键的正是前面提过的 qgis),其中 11 条指向独立仓库,其余 67 条的值是 null——也就是仓库内自带的 harness。上面那 11 条 skill_md 为远程 URL 的条目,正好就是这 11 条 source_url 非 null 的独立仓库条目。

install_cmd 是 79 条全有的字段。以数组第一条 jumpserver 为例(registry.json:9-24 是一条字段齐全的示范),它的 install_cmd 长这样(registry.json:16):

pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=jumpserver/agent-harness

读到这一行,有几件事必须说清楚,不能糊过去:

  • 这条命令是从 git 拉源码到本机安装并执行的。执行注册表里的 install_cmd 等于同意在你的机器上跑第三方代码,source_url 非 null 的那 11 条拉的还不是这个仓库的代码。
  • 装完 harness 也不等于能用。README 明确提醒过:包装真实桌面软件的那些 CLI,需要用户自行安装上游应用README.md:236)。注册表里有 blendergimpkdenlive 这些条目,不代表你的机器上有 Blender、GIMP 或 Kdenlive。
  • 这类 harness 的工作方式本来就是在本机驱动外部程序与脚本。装不装、在什么环境里装,请结合自己的机器情况判断。

requires 字段(79 条全有)正是给这件事留的位置——注册表用它声明该条目的前置依赖。想判断某个条目对你是否可用,读 requires 比读 version 有参考价值得多;具体每条写了什么,clone 下来 json.load 一看便知。

categoryversion:两栏自报数据

category 共出现 31 种取值,条目数分布是:ai 8、web 6、devops 6、video 6、graphics 6、office 4、3d 3、image 3、automation 3、gamedev 3,之后是 database / network / audio / diagrams / debugging / communication / design / search / knowledge / science 各 2,剩下 11 种各 1 条(testing、generation、finance、streaming、project-management、scientific、music、game、osint、knowledge-management、storage)。

这个分布有个直接后果:31 个类目里有 21 个类目只有一到两条记录。如果你想按 category 做筛选或分组展示,绝大多数类目是单条的,分组这层抽象基本没帮上忙。另外 scientificscienceknowledgeknowledge-management 这几组取值在字面上就贴得很近,做归并时得手动定规则。

version 一栏的分布是:1.0.0 49 条、0.1.0 14 条、1.0.1 4 条、0.1.1 3 条、1.1.0 3 条,另有 0.4.10.23.10.2.02.4.70.3.01.3.0 各 1 条。需要强调的是,这是条目自己声明的版本字符串。它与 harness 里实际有多少代码、测试齐不齐是什么关系,我们没有核实,也不从这个字符串推任何结论。

79 这个数字,和 README 里的数字对不上

最后一件写代码前该知道的事:registry.json 的 79 条,和 README 呈现出来的软件数量不是同一个口径。

我们对 README 的演示表格做正则计数,带 cli-anything-* 入口的行只有 44 行;README 正文另一处写的是 “Tested across 18 diverse, complex applications”(README.md:999,README 自称)。此外注册表条目数与仓库顶层目录数也不相等——那个差集里具体差了哪几个,我们另有一篇专门讲,这里不展开。

所以引用数字时务必带上口径:说”79”要说明是 registry.jsonclis 数组长度;说”18”要说明是 README 自称的测试覆盖应用数。这两个数分别回答的是不同的问题,混着用会得到一个谁都不认的结论。

一份可以照着做的核查清单

想自己确认上面每一条,按这个顺序走一遍即可,不需要装任何东西:

  1. json.load 打开 registry.json,打印顶层键与 len(d['clis']) —— 得到 2 个键与 79;
  2. Counter 累加每条记录的 keys() —— 得到那张 15 行的频次表,确认哪 10 个是全覆盖;
  3. skill_mdnull 的条目、以 http 开头的条目 —— 得到 5 与 11;
  4. source_url is None —— 得到 67,再加上缺这个键的 1 条,正好与 11 条非 null 凑齐 79;
  5. 把上一步筛出来的本地 skill_md 路径拿去 os.path.exists 逐条查 —— 确认那 7 条没走 skills/ 前缀的路径是真实存在的;
  6. CONTRIBUTING.md:59-72 的字段规格与第 2 步的频次表并排看 —— 差异就在那里。

这六步是纯文本读取,不涉及安装、不涉及执行任何 harness,任何人 clone 下来都能重跑一遍得到同样的数。这也是我们这篇里所有数字的来路。


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

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