🤖 CLI-Anything 深度解析:为什么软件 CLI 化是 AI Agent 时代的必选项?
本文用一张思维导图 + 源码级拆解,带你搞懂 CLI-Anything 的本质、7 阶段流水线,以及如何把任意 GUI 软件变成 AI Agent 可调用的命令行工具。
🧭 思维导图速览
mindmap
Root((CLI-Anything))
为什么CLI化
GUI面向人类
AI Agent无法操作GUI
CLI面向程序
脚本化/自动化/远程执行
本质
AI插件 + 方法论文档
核心是HARNESS.md
AI编码助手是执行引擎
与MCP关系
互补非竞争
CLI Anything = 框架
MCP等于协议
成果物实现
drawio harness
目录结构
核心代码
REPL界面
SKILL.md
关键原则
必须调用真实软件
禁止优雅降级
所有命令支持json
一、为什么需要软件 CLI 化?——AI Agent 的“操作困境”
1.1 GUI 是为人类设计的,不是为 AI 设计的
想象一下:你让 AI 助手“用 GIMP 给这张图片加个水印”。AI 能做什么?
- ❌ 它打不开 GIMP 的窗口(没有显示器)
- ❌ 它移动不了鼠标(没有鼠标驱动)
- ❌ 它看不懂弹出来的对话框(无法解析视觉信息)
- ❌ 它获取不到“操作成功”的反馈(没有 stdout)
结论:传统 GUI 软件对 AI Agent 来说,就像一本合上的书——看得见封面,读不懂内容。
1.2 CLI 化到底解决了什么?
| 维度 | GUI 模式 | CLI 化之后 |
|---|---|---|
| 🤖 AI 交互 | 无法操作 | 原生支持(命令 = 函数调用) |
| 📜 自动化 | 需要脆弱的 RPA | 直接写脚本,稳定可靠 |
| 🔁 批处理 | 人工逐个点 | for file in *.jpg; do cli-anything ... |
| 🔗 可组合性 | 封闭系统 | command1 | command2 管道串联 |
| 🌍 远程执行 | 需要显示器 | SSH 无头运行 |
| ✅ 可测试性 | UI 自动化(慢、脆) | 断言 stdout 即可 |
💡 一句话总结:CLI 化就是把软件的“操作界面”从像素变成文本,从人类专用变成人人(包括 AI)可用。
二、CLI-Anything 的本质:一个“AI 插件 + 方法论”
2.1 核心公式
┌─────────────────────────────────────────────────────────────┐
│ │
│ CLI-Anything = HARNESS.md(方法论) + 插件壳(适配层) │
│ │
│ 本质:一个 AI 编码助手插件 + 一套可复用的 SOP 文档 │
│ 创新点:方法论沉淀 + 插件化适配(不是技术突破,是工程范式) │
│ │
└─────────────────────────────────────────────────────────────┘
关键洞察:CLI-Anything 自己不做任何实际工作。它只提供:
- 📋 约束:
HARNESS.md定义规则(必须调用真实软件、禁止优雅降级等) - 🧩 模板:目录结构、代码模式、测试模板
- 🔄 流程:7 阶段流水线(源码分析 → 架构设计 → 实现 → 测试 → 发布)
真正干活的是 AI 编码助手(Claude Code、Codex、OpenCode 等)。CLI-Anything 相当于给 AI 配了一副“施工图纸”和一套“标准工具”。
2.2 架构图
用户输入
│
▼
┌────────────────────────┐
│ AI 编码助手 │
│ (Claude Code 等) │
└────────────────────────┘
│
│ 读取
▼
┌─────────────────────────────────────────────────────────────────────┐
│ cli-anything-plugin │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ HARNESS.md │ │ commands/ │ │ templates/ │ │
│ │ │ │ │ │ │ │
│ │ 方法论 SOP │───▶│ 触发器命令 │───▶│ SKILL.md │ │
│ │ 7 阶段流程 │ │ cli-anything │ │ Jinja2 模板 │ │
│ │ 强制规则 │ │ refine │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ repl_skin.py │ │ guides/ │ │
│ │ │ │ │ │
│ │ 统一 REPL │ │ 详细实现指南 │ │
│ │ 界面组件 │ │ MCP/时间码等 │ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
│
│ AI 编码助手按方法论执行
▼
┌────────────────────────┐
│ 成果物生成 │
│ (如 drawio harness) │
└────────────────────────┘
2.3 与 MCP 的关系:互补而非竞争
| 维度 | CLI-Anything | MCP |
|---|---|---|
| 定位 | 框架(如何把软件变成工具) | 协议(Agent 与工具如何通信) |
| 产出 | Python CLI 包(cli-anything-xxx) | 工具接口定义(JSON Schema) |
| 关系 | 成果物可被 MCP 包装 | 可作为 CLI 的后端 |
示例协作:
- CLI-Anything 生成
cli-anything-drawio - 开发者用 MCP 把它包装成标准工具接口
- AI Agent 通过 MCP 协议调用 draw.io 功能
🚀 未来趋势:CLI-Anything 负责“造工具”,MCP 负责“通工具”,两者结合,AI 就能操作任意软件。
三、方法论文档:HARNESS.md 详解
3.1 七阶段流水线(一张图看懂)
flowchart LR
P1[Phase1<br/>源码分析] --> P2[Phase2<br/>CLI架构设计]
P2 --> P3[Phase3<br/>实现]
P3 --> P4[Phase4<br/>测试规划]
P4 --> P5[Phase5<br/>测试实现]
P5 --> P6[Phase6<br/>测试文档]
P6 --> P65[Phase6.5<br/>SKILL生成]
P65 --> P7[Phase7<br/>PyPI发布]
每个阶段的核心任务:
| 阶段 | 任务 | 产出示例 |
|---|---|---|
| 1. 源码分析 | 识别后端引擎、映射 GUI 操作 → API、发现现有 CLI | DRAWIO.md |
| 2. CLI 架构设计 | 选交互模式(REPL/子命令)、定义命令组、设计状态模型 | 命令树设计 |
| 3. 实现 | 数据层(XML 操作)、后端集成、REPL 界面、会话管理 | drawio_cli.py |
| 4. 测试规划 | 制定单元测试 + E2E 测试计划 | TEST.md |
| 5. 测试实现 | 写单元测试、E2E 测试、CLI 子进程测试 | test_*.py |
| 6. 测试文档 | 记录测试结果 | 更新 TEST.md |
| 6.5 SKILL 生成 | 生成 Agent 发现文件 | SKILL.md |
| 7. PyPI 发布 | 配置 setup.py,验证安装 | 可 pip 安装的包 |
3.2 强制规则(非协商)
以下三条规则是 HARNESS.md 的核心约束,任何 CLI harness 都必须遵守:
✅ 规则 1:必须调用真实软件(禁止重新实现)
# ❌ 错误:自己用 Pillow 渲染
def export_to_png(project):
from PIL import Image
img = Image.new('RGB', (1920, 1080))
return img
# ✅ 正确:调用真实 draw.io 可执行文件
def export_to_png(drawio_path, output_path):
drawio = find_drawio()
subprocess.run([drawio, "--export", drawio_path,
"--output", output_path, "--format", "png"])
# 由 draw.io 的完整引擎渲染
✅ 规则 2:禁止优雅降级(软件是硬依赖)
# ❌ 错误:软件不存在时跳过测试
@pytest.mark.skipif(not shutil.which("drawio"), reason="not installed")
def test_export():
...
# ✅ 正确:找不到就报错,给出明确安装指令
def find_drawio():
path = shutil.which("drawio")
if not path:
raise RuntimeError(
"draw.io is not installed. Run:\n"
" macOS: brew install --cask drawio"
)
return path
✅ 规则 3:所有命令必须支持 --json 输出
@click.command()
@click.option("--json", "json_mode", is_flag=True)
def project_new(json_mode):
result = {"status": "created", "path": "./project.drawio"}
if json_mode:
click.echo(json.dumps(result)) # 🤖 AI 可解析
else:
click.echo(f"✓ Created project: {result['path']}") # 👨💻 人类可读
💡 小贴士:
--json是 AI Agent 和 CLI 之间的“通用语”。有了它,Agent 就能像调用函数一样解析返回结果。
四、成果物实战:draw.io CLI harness
4.1 目录结构(一目了然)
drawio/agent-harness/
│
├── DRAWIO.md # 软件分析文档
├── setup.py # PyPI 打包配置
│
└── cli_anything/drawio/
├── drawio_cli.py # CLI 入口(Click + REPL)
├── core/ # 业务逻辑
│ ├── project.py # 项目:new, open, save
│ ├── shapes.py # 图形:add, remove, move
│ ├── connectors.py # 连接线
│ ├── export.py # 导出:render
│ └── session.py # 会话 + undo/redo
├── utils/
│ ├── drawio_backend.py # ★ 调用真实 draw.io
│ ├── drawio_xml.py # XML 操作
│ └── repl_skin.py # 统一 REPL 界面
├── skills/
│ └── SKILL.md # Agent 发现文件
└── tests/
├── TEST.md
├── test_core.py
└── test_full_e2e.py
4.2 核心代码片段解析
后端集成:调用真实 draw.io
# cli_anything/drawio/utils/drawio_backend.py
def export_diagram(drawio_path: str, output_path: str, fmt: str = "png"):
# 1. 验证输入文件存在
if not os.path.exists(drawio_path):
raise FileNotFoundError(f"File not found: {drawio_path}")
# 2. 找到真实 draw.io 可执行文件(找不到就报错)
drawio = find_drawio()
# 3. 构建命令并执行
cmd = [drawio, "--export", drawio_path, "--output", output_path, "--format", fmt]
result = subprocess.run(cmd, capture_output=True, timeout=60)
if result.returncode != 0:
raise RuntimeError(f"Export failed: {result.stderr}")
# 4. 验证输出文件生成
if not os.path.exists(output_path):
raise RuntimeError("No output file produced")
return {"output": output_path, "file_size": os.path.getsize(output_path)}
会话管理:支持 undo/redo
class Session:
def __init__(self):
self.root = None # XML 根节点
self._undo_stack = [] # 快照栈
self._redo_stack = []
def checkpoint(self):
"""修改前调用,保存当前状态"""
snap = ET.tostring(self.root)
self._undo_stack.append(snap)
self._redo_stack.clear()
def undo(self):
if not self._undo_stack:
return False
self._redo_stack.append(ET.tostring(self.root))
self.root = ET.fromstring(self._undo_stack.pop())
return True
🎯 亮点:通过 XML 快照实现完整的 undo/redo,不需要重写整个图形引擎。
4.3 统一 REPL 界面(repl_skin.py)
所有 CLI harness 共享同一个 REPL 皮肤,保证一致的交互体验:
╔══════════════════════════════════════════╗
║ ◆ cli-anything · Draw.io ║
║ v1.0.0 ║
║ ◇ Skill: /path/to/SKILL.md ║
║ Type help for commands ║
╚══════════════════════════════════════════╝
drawio[my_project] ❯ shape add rectangle --label "Server"
✓ Added rectangle: shape_001
drawio[my_project]* ❯ export render output.png
✓ Exported to output.png (156KB)
4.4 SKILL.md:Agent 如何发现并使用这个工具
---
name: cli-anything-drawio
description: A CLI harness for Draw.io — create, edit, and export diagrams
---
# cli-anything-drawio
## For AI Agents
1. **Always use `--json` flag** for parseable output
2. **Check return codes** (0 = success)
3. **Use absolute paths** for all file operations
有了这个文件,AI 编码助手就能自动识别 cli-anything-drawio 的存在,并按照规范调用它。
五、总结:CLI-Anything 的真正价值
mindmap
root((核心价值))
方法论沉淀
将GUI转CLI的经验编码为SOP
降低重复造轮子的成本
降低门槛
任何AI编码助手用户都能构建
不需要精通底层API
生态构建
社区贡献更多CLI harness
形成可复用的工具库
Agent基础设施
让现有软件无需重写
即可被AI Agent调用
关键原则回顾
- ✅ 必须调用真实软件(不要重新实现轮子)
- ✅ 禁止优雅降级(软件是硬依赖,找不到就报错)
- ✅ 所有命令支持
--json(Agent 友好)
适用场景速查表
| 场景 | 推荐度 | 原因 |
|---|---|---|
| AI Agent 自动化工作流 | ⭐⭐⭐⭐⭐ | 核心场景,天然匹配 |
| CI/CD 流水线集成 | ⭐⭐⭐⭐⭐ | 命令行原生支持 |
| 批量文件处理 | ⭐⭐⭐⭐⭐ | 脚本化循环执行 |
| 远程服务器操作 | ⭐⭐⭐⭐⭐ | 无头运行,SSH 友好 |
| 个人日常使用 | ⭐⭐⭐ | 需要一定学习成本 |
💬 写在最后:一个开放问题
CLI-Anything 提供了一套将 GUI 软件“武装”成 AI 可调用工具的方法论。但它的上限取决于社区能贡献多少高质量的 harness。
🤔 你觉得,下一个最应该被 CLI 化的软件是什么?是 Photoshop?是 Final Cut Pro?还是某个行业专用工具?
欢迎在评论区留下你的想法——也许下一个 cli-anything-photoshop 就由你来实现!🚀