comfyui harness:工作流软件的 harness 长什么样

2026-08-10

CLI-Anything 仓库里的 harness 高度同构:一棵固定的目录树、四份固定的文档、一套 Click 命令注册写法。我们采集时(2026-08-10,对应仓库快照 39634a6)仓库里有 69 个 agent-harness 目录。同构结构本身另有一篇专门讲,这一篇只干一件事:把 comfyui 这一个拎出来,说清它和其它同类不一样在哪。

选它的理由是它的位置很特别。ComfyUI 本身是一款以节点工作流为核心的出图软件,直觉上给它套命令行,重头戏应该在「编工作流」。但我们把它的命令面数完之后,情况正好相反。

先看它有多小

我们精读了 12 个代表应用的 harness(blender、obs-studio、krita、gimp、inkscape、QGIS、zotero、obsidian、comfyui、kdenlive、freecad、n8n),行数统计口径是 find <app> -name '*.py' -not -path '*/tests/*' | xargs wc -l | tail -1。同为 2026-08-10 的采集口径,comfyui 的非测试代码是 1293 行,12 个里最少;作为对照,同一口径下 freecad 是 22450 行、blender 是 5958 行。

它的 comfyui_cli.py 是 425 行。core/ 下只有 4 个模块:images.py(137 行)、models.py(169 行)、queue.py(194 行)、workflows.py(158 行)。utils/ 更是只有一个文件 comfyui_backend.py(156 行)。

但它的测试不小:测试代码 1075 行,73 个 def test_test_core.py 63 个 + test_full_e2e.py 10 个)。1075 对 1293,测试行数达到非测试行数的八成以上,是我们数过的 12 个里最高的;同口径下第二高的 obs-studio 是 1554 对 2986,约五成,最低的 freecad 是 2670 对 22450。这两个数放在一起是个可核查的对照:非测试代码最少,但测试行数并不低。至于覆盖面,下一节的 19 条命令更能说明问题。

反直觉的那一处:工作流那一组是最小的

它的命令面是 5 个组、19 条组内命令,外加一条顶层 replcomfyui_cli.py:364)。19 条全列在这儿:

命令组条数命令
workflow3list / load / validate
queue5prompt / status / clear / history / interrupt
models6checkpoints / loras / vaes / controlnets / node-info / list-nodes
images3list / download / download-all
system2stats / info

把这张表横着读一遍:条数最多的是 models(6 条),其次是 queue(5 条);顶着「工作流」名头的 workflow 组只有 3 条,而且这 3 条的动词是 list、load、validate——列出来、装载、校验。这 19 条命令的名字里,没有出现新建、改写、连线这类编辑动作。

queue 组那 5 条则明显是另一种性质:prompt 提交、status 看队列、history 翻历史、interrupt 打断、clear 清空。models 组的 6 条全是「问宿主你手上有什么」——有哪些 checkpoints、loras、vaes、controlnets,某个节点的信息,全部节点清单。system 组的 stats / info 同理。

也就是说,这个 harness 的重心不在「离线把工作流编出来」,而在「对着一个已经跑起来的 ComfyUI 发指令、问状态、取产物」。它更像遥控器,不像编辑器。你如果是奔着「用命令行拼节点图」去的,看完这张表就该改主意——省下的是自己去翻 425 行 CLI 的时间。

需要说明的是,各命令的参数校验逻辑、--json 输出结构我们没有逐条核实,上面这张表只到命令名这一层。

它怎么驱动宿主:纯 HTTP,且默认地址就在本机

12 个代表应用驱动宿主的方式差得很远:blender 生成 bpy 脚本再调可执行文件,gimp 走 Script-Fu 批处理,kdenlive 走 melt 子进程,freecad 生成 Python 宏交给 FreeCADCmd。comfyui 是纯 HTTP

utils/comfyui_backend.py 开头 1 到 8 行的模块 docstring 写得很直白:它包装 ComfyUI 的 REST API HTTP 调用,并且是唯一发网络请求的模块。默认地址在同文件第 14 行:DEFAULT_BASE_URL = "http://localhost:8188"。图片取回走 /view 端点(core/images.py:1-7 的模块 docstring)。

这里有一条必须原样说清楚的:comfyui_backend.py 第 8 行注明「No authentication is required by default」——默认不需要鉴权。这是源码注释里的口径,不是我们的评价。连带的现实是,要用这个 harness,你得自己在本机或内网装好并运行 ComfyUI;这条 HTTP 链路指向的是一台真实在跑的实例,queue clearqueue interrupt 这类命令作用在那台实例上。这类 harness 会在本机执行外部程序与脚本、并驱动你自己安装的宿主软件,是否使用、以什么网络边界使用,请结合自身环境评估——我们没有安装或运行过其中任何一个,给不出配置建议。

和另外三个需要真宿主的放在一起看

12 个代表应用里,有几个的端到端测试明确写了「要求宿主真在运行」。把 comfyui 和其中三个的驱动方式、e2e 要求摆在一张表里(同为 2026-08-10 采集口径),它的位置就清楚了:

应用驱动方式e2e 是否需要真宿主依据
comfyuiHTTP REST(utils/comfyui_backend.py:14否,全 mocktests/test_full_e2e.py:1-8
obsidianHTTPS REST,走 Local REST API 插件(utils/obsidian_backend.py:17tests/test_full_e2e.py:1-7
n8nREST API + 本地 SQLite 版本库(utils/n8n_backend.py:1是,需实例与环境变量tests/test_full_e2e.py:1-3
QGISimport PyQGIS + qgis_process --json是,需 QGIS 运行时utils/qgis_backend.py:105/171

comfyui 的 tests/test_full_e2e.py 头部原文写的是:所有测试都用 mock 过的 HTTP 响应,它们要求 ComfyUI 被安装或运行;同包的 tests/TEST.md 第 5 行也写着「No ComfyUI installation required」。而 obsidian 那份 e2e 头部写的是需要 Obsidian 带 Local REST API 插件在跑、不可用就跳过,n8n 那份写的是需要一个运行中的 n8n 实例。

这个差别值得留意的地方在于:测试全绿并不覆盖「你那台真实例的响应长什么样」。这是测试文件 docstring 与 import 给出的结论,不是运行结果——我们没有跑过任何一个 harness 的测试。

顺带一提,同样是「工作流/场景集合」类软件,obs-studio 的 harness 走的是完全相反的路线:全包 0 处 subprocess、0 处 HTTP,只读写 JSON 场景集合,它的 SKILL.md 第 11 行直接写「No OBS installation required for editing」。一个把状态全留在本地、根本不碰宿主进程,一个不留本地状态、全靠网络打给宿主——两个极端在同一个仓库里并存。

三处「本来该有」的东西它没有

同构仓库里最省事的读法,是先看它缺了什么。

一、没有 session.py core/ 下的 4 个模块里没有它,也就是说这个 harness 没有工程文件、没有 undo/redo。作为对照,blender、obs-studio、gimp、kdenlive 四个都带同一款 Session 类,撤销栈上限是类常量 MAX_UNDO = 50。我们采集时(2026-08-10)全仓 agent-harness 目录 69 个,其中数出的 session.py 是 40 个(find 计数),comfyui 的 core/ 里没有这一份。

二、包里没有 __main__.py(依据是 find comfyui -type f 的结果)。这一层在别的 harness 里是三行转发,用来支撑 python3 -m cli_anything.<app> 这条运行路径。我们采集时全仓有 __main__.py 的是 58 个。comfyui 这边,能作数的是 setup.py 注册的 console_scripts——12 个代表应用的 setup.py 都注册了 console_scripts,命名统一为 cli-anything-<app> 这个形式。

三、--dry-run 是 0 处grep -c 'dry.run\|dry_run')。同一条命令在 blender、obs-studio、gimp、kdenlive 各有 4 处,inkscape 7 处,n8n 5 处;QGIS、zotero、obsidian、comfyui 都是 0。对一个所有写操作都直接落到远端实例的 harness 来说,这一项的缺席比在别处更值得你先知道。

它是 12 个里唯一自己写 REPL 的

CLI-Anything 有一份共享的 REPL 皮肤 utils/repl_skin.py,规范要求从 plugin 目录复制过来。我们精读的 12 个里有 11 个带它,其中 10 份 md5 完全相同(623dc43e9c2421a97231d398ea303f0c,567 行),QGIS 和 n8n 各自是另一份。

comfyui 是那个例外:grep -c 'repl_skin' comfyui/agent-harness/cli_anything/comfyui/comfyui_cli.py 的结果是 0。它自带一个 while 循环 REPL,写在 comfyui_cli.py:364-416,靠 click.prompt 收行(:398),再用 cli.main(args, standalone_mode=False) 重入同一棵 Click 命令树(:405)——重入这一手和共享皮肤的做法是一致的,不一样的是外面那层壳。

它的 REPL help 里还硬编码了一张命令表(:377-385)。这处给你留了一个现成的核查动作:把 :377-385 那张手写表,和上文那 5 组 19 条命令逐条比一遍,看两边是否对得上。这类「文档/提示里的清单」与「代码里的命令」对不上的情况,在这个仓库的其它 harness 里是有先例的。

它在齐件清单里的位置

注册表里有条目、目录里有 harness,不等于四件套是齐的。comfyui 有两处需要照实记下来:

第一,它缺顶层的 <APP>.md(那份项目分析与 SOP 文档)。同样缺这一份的还有 firefly-iiiminimaxn8nnovitasketchzoom,共 7 个。包内的三份——README.mdskills/SKILL.mdtests/TEST.md——comfyui 是齐的。

第二,它的 agent-harness/cli_anything/ 目录下存在 __init__.py。规范文档 cli-anything-plugin/HARNESS.md 第 702 到 703 行用加粗 Critical 写的是这个目录 must NOT 含 __init__.py(理由是 PEP 420 命名空间包),而我们采集时 ls */agent-harness/cli_anything/__init__.py 列出 8 个,comfyui 在其中,另外 7 个是 chromadb、godot、intelwatch、obsidian、pm2、seaclip、videocaptioner。规范写的是一种,仓库里是另一种,这是两个可以各自核对的事实,我们只陈述到这里。

还有一个全仓口径值得在评估任何一个 harness 时先看一眼(同为 2026-08-10 采集口径):打包文件里 Development Status4 - Beta 的有 45 处、3 - Alpha 2 处,全仓没有任何一个标 5 - Production/Stable

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

上面每个数字都是从文件系统和源码文本里数出来的,clone 下来就能复现:

find comfyui -name '*.py' -not -path '*/tests/*' | xargs wc -l | tail -1
grep -c 'repl_skin' comfyui/agent-harness/cli_anything/comfyui/comfyui_cli.py
grep -c 'dry.run\|dry_run' comfyui/agent-harness/cli_anything/comfyui/comfyui_cli.py
find comfyui -type f
ls */agent-harness/cli_anything/__init__.py

以上命令按仓库中的统计口径组合,未经实测,以你本地 clone 的实际输出为准。五条依次对应:非测试行数、共享 REPL 皮肤的引用数、--dry-run 出现次数、包内文件清单(用来确认 session.py__main__.py 都不在),以及全仓那 8 个破例的 __init__.py。数字会随上游更新变动,值得记住的不是 1293 和 19,而是这个 harness 的形状:窄命令面、零本地状态、纯 HTTP、e2e 全 mock。


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

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