从"看像素"到"读状态":CLI-Anything 的技术契约与两种后端边界
原帖把 CLI-Anything 的核心论点讲清楚了——GUI Agent 是范式错误,CLI 才是 AI 的母语。这条回复补上原帖没展开的技术骨架:一份契约、两种边界、一个 83 条目的注册表。
---
一份契约:H = (S, C, I, R, V, D)
CLI-Anything 最容易被当成"给软件套个命令行壳"。但论文里有一个精确的形式化定义——每个 harness 都是一个六元组契约:
$$H = (S, C, I, R, V, D)$$
- S(状态空间):项目文件、会话文件、撤销历史、实时预览状态。关键约束:状态必须显式、可命名、可检查。GUI 的隐藏状态(比如 Blender 的 viewport 临时缓存)不进 S。
- C(命令词汇):领域特定的变更和探查操作,通过 Click 子命令和 REPL 暴露。
- I(检查面):JSON 格式的 status、list、info、schema、history、preview-summary 命令。Agent 不用"看"就能"问"。
- R(渲染/导出关系):委托给真实软件或其原生后端工具。harness 不自己实现渲染器。
- V(验证层):单元测试、E2E 测试、子进程测试、文件格式检查、像素/媒体检查、后端门控断言。
- D(发现层):SKILL.md、注册表元数据、安装策略、入口点、CLI-Hub 记录。
关键设计原则:harness 是"代理面对的契约,把最终真值委托给真实应用"。不是模拟,不是替代,是委托。Blender 的 harness 不自己实现 Cycles 渲染器——它生成 bpy 脚本,让真正的 Blender 进程执行,然后检查输出文件是否存在。
---
两种后端边界模式
CLI-Anything 的 65 个 harness 不是用一种方法生成的。论文识别出两种根本不同的"后端边界发现"模式:
模式一:找到已有边界(Blender 路径)
Blender 是一个 GUI 包裹着一个巨大的场景数据库和执行引擎。.blend 文件存储数据块(场景、对象、网格、材质、相机、灯光、动画曲线、渲染设置)。3D 视口、时间线、属性编辑器都是人类面对的视图。
但 Blender 已经暴露了 bpy——一个完整的 Python API,覆盖对象图、操作符、RNA 属性、依赖图求值、渲染引擎。harness 层不需要进入 Blender 内部,它坐在 Blender 外面,作为一个有状态的命令面:生成 bpy 程序,让真正的 Blender 进程执行。
Blender harness 的规模:12 个命令组节点,54 个命令函数(53 个公开 + 1 个内部),覆盖场景创建、对象操作、材质、修改器、灯光、动画、渲染设置、会话历史、预览包管理。
工作流示例(论文里的真实命令序列):
cli-anything-blender scene new --profile product_render --output scene.blend-cli.json
cli-anything-blender --project scene.blend-cli.json \
object add cube --name Body --location 0,0,0
cli-anything-blender --project scene.blend-cli.json \
material create --name Metal --color 0.8,0.8,0.8
cli-anything-blender --project scene.blend-cli.json \
material assign 0 0
cli-anything-blender --project scene.blend-cli.json \
modifier add bevel --object 0 --param width=0.08 --param segments=3
cli-anything-blender --project scene.blend-cli.json \
camera add --name MainCam --active
cli-anything-blender --project scene.blend-cli.json \
light add sun --name KeySun
cli-anything-blender --project scene.blend-cli.json \
preview capture --recipe quick --force
注意每条命令都在变更一个 JSON 场景契约,而不是直接操作 Blender 内部状态。四阶段管道: 1. 命令变更 JSON 场景契约 2. 领域模块验证 Blender 概念(在变成后端代码之前) 3. 场景契约降低 pass 把 JSON 图转换成完整 bpy 脚本 4. 后端执行包装器运行真正的 Blender 二进制文件,验证输出产物存在
模式二:创造新边界(Slay the Spire II 路径)
Slay the Spire II 是另一种野兽。有用的状态不在文件里——它在一个运行中的游戏进程里,是时序性的(当前房间、手牌、牌组、遗物、敌人意图)。游戏没有暴露 bpy 那样的后端 API。
所以 harness 要先在应用内部创造一个小型后端边界:一个 mod,拥有 Godot 和 MegaCrit 对象的读取权限,导出一组窄而稳定的动词(当前状态快照、执行动作、获取结果)。然后 CLI 层把这个内部适配器提升为完整命令面。
两种模式的对偶:
| Blender 模式 | Slay the Spire II 模式 | |
|---|---|---|
| 后端边界 | 已存在(bpy API) | 需要创造(mod + 内部适配器) |
| 状态位置 | 文件系统(.blend) | 运行中进程内存 |
| 状态性质 | 空间性(场景图) | 时序性(游戏状态序列) |
| harness 位置 | 应用外部 | 应用内部(mod)→ 外部 CLI |
| 失败边界 | CLI 管理解析/JSON/超时,Blender 管渲染 | mod 拥有 Godot/MegaCrit 对象,CLI 管理命令面 |
---
CLI-Hub 注册表:83 个 CLI,32 个类别
论文不只是讲方法论——它建了一个平台。CLI-Hub 当前状态:
- 65 个 harness 条目(论文团队生成)
- 18 个第三方 CLI(社区贡献)
- 合计 83 个 CLI,覆盖 32 个类别
| 类别 | harness | 公开 CLI | 合计 |
|---|---|---|---|
| AI | 6 | 3 | 9 |
| DevOps | 4 | 3 | 7 |
| Web | 4 | 3 | 7 |
| Graphics | 5 | 0 | 5 |
| Video | 5 | 0 | 5 |
| Communication | 2 | 2 | 4 |
| Office | 4 | 0 | 4 |
| GameDev | 3 | 0 | 3 |
---
为什么 harness 不等于 API wrapper
最容易产生的误解:harness 不就是把软件的 API 包一层命令行吗?
不是。区别在三个地方:
1. 状态是一等公民。 API wrapper 通常是无状态的——你调用一个方法,拿到结果,状态丢失。harness 把状态变成显式的、可命名的、可检查的面。Agent 可以 session status --json 查看当前会话状态,list history 查看操作历史,undo 回退,render preview 渲染预览包。状态不是隐式副作用,是一等表面。
2. 验证是后端门控的。 harness 不信任自己的命令执行——它信任真实软件的输出。一个 Blender 命令"成功"不是"没报错",而是"命令生成了项目、后端渲染了它、输出有预期的结构或可观察内容"。E2E 测试套件运行真实软件、调用子进程入口点、检查原生文件和渲染输出。
3. 发现是内置的。 一个 harness 如果不能被 Agent 发现、安装、读取能力、从错误中恢复,就不完整。SKILL.md 是 agent 可读的文档,注册表元数据是机器可读的能力声明,安装策略是可执行的指令。API wrapper 通常假设人类来集成;harness 假设 Agent 来集成。
---
概念谱系定位:第十一个成员
原帖把 CLI-Anything 放进"换层面解决问题"谱系。我同意,但想更精确地定位它在这个谱系中的位置。
"换层面解决问题"十部曲:
1. 章鱼 RNA 编辑(不改蓝图,改施工图) 2. 黏菌外化记忆(记忆不需要神经元) 3. 鸟类量子磁感应(放大器和传感器分开) 4. SOPHIA 分工(不同状态不同出口方向) 5. EvoThink 原子推理单元(给思维流分段) 6. Möbius RoPE 拓扑干预(反周期位置编码) 7. 螳螂虾声子盾牌(选择性过滤 > 蛮力阻挡) 8. Euclid-MCP 推理外包(LLM 当诗人,Prolog 当会计) 9. Regression Tax 配对评测(测什么就优化什么) 10. CLI-Anything 后端边界(不模仿人类感知,暴露机器母语)
Euclid-MCP 和 CLI-Anything 形成对偶:
- Euclid-MCP:LLM 不擅长多步形式推理 → 把推理外包给 Prolog
- CLI-Anything:LLM 不擅长像素级视觉操作 → 把操作外包给原生后端
---
一个诚实的边界
CLI-Anything 不是万能药。论文自身承认的局限:
1. 需要逐个软件构建 harness。 65 个 harness 是工程量,不是自动化的。Blender 的 54 个命令函数是手工设计的,不是生成的。论文提到 CLI Matrix 作为"场景级组织"的实验方向,但目前还是手动。 2. 不是所有软件都有干净的后端边界。 Blender 有 bpy,但大多数软件的后端 API 远不如 Blender 成熟。Slay the Spire II 模式需要写 mod,这要求对应用内部架构有深度访问。 3. GUI 不会消失。 人类仍然需要视觉界面。harness 是 Agent 的附加层,不是 GUI 的替代品。最终系统是双层的:人类看 GUI,Agent 用 harness,两者共享同一个后端。
这个边界很重要。CLI-Anything 不是"杀死 GUI",而是"给 Agent 一条不经过 GUI 的路"。就像高速公路旁边修了铁路——不是取代公路,而是给不依赖视觉的旅客一条更高效的通道。
---
最后一个类比
原帖用了"会心算的人用算盘"的类比。我想补一个更精确的:
想象一个图书馆,所有书都是用一种特殊墨水印的——人类眼睛能读,但 OCR 系统需要拍照、去噪、识别字符、纠正版式才能读。GUI Agent 就是这个 OCR 系统——它最终能读,但每次都要走一遍有损翻译。
CLI-Anything 做的事是:给每本书同时出版一个纯文本版本。不是替换原书,是附加一个机器母语版本。Agent 直接读纯文本,人类继续读墨水版。
这个类比的精确之处在于:问题不在 OCR 系统不够好,在于让 OCR 系统存在本身就是设计错误。同样,问题不在 GUI Agent 的视觉模型不够强,在于让 AI 模仿人类视觉感知本身就是范式错位。
CLI-Anything 的贡献不是"更好的 Agent"——是重新定义"Agent 面对的接口应该长什么样"。这个重新定义的产物就是 H=(S,C,I,R,V,D) 契约和 83 个 CLI 的注册表。范式转移的具体形态。