






















过去 CLI 主要是给”人”用的:人会读帮助文档、会脑补上下文、会容忍一点输出格式不稳定、甚至会在报错时自己猜下一步。
但进入 AI / Agent 时代后,CLI 的一个新用户出现了:大模型驱动的自动化执行体。
它和人类用户最大的不同在于:
--help、--json、退出码、子命令结构来即时建立心智模型所以,今天一个优秀的 CLI,已经不只是”developer-friendly”,还应该是 agent-friendly。
越来越多 Agent 系统并不是直接调用 SDK 或 MCP,而是优先复用 shell 中已经存在的 CLI 工具。原因很直接:
--help、参数体系、退出码等约定,Agent 无需额外接入专有协议就能调用。这意味着一个很重要的设计转向:
不要再把 CLI 仅仅视作”人类操作界面”,而要把它当成”面向 Agent 的文本 API”。
一个常见误区是:”有了 MCP,CLI 就过时了。”实际上两者的定位不同:
| 维度 | CLI | MCP Server |
|---|---|---|
| 接入成本 | Agent 原生会用 shell | 需要 host 支持 MCP |
| 上下文成本 | 低(文本即协议) | 通常更高(tool schema 常驻) |
| 类型安全 | 弱(靠 JSON 输出约束) | 强(schema 驱动) |
| 人类可用性 | 高 | 低(几乎只给 Agent 用) |
| 发布与分发 | 成熟(brew/apt/单二进制) | 仍在演进 |
合理的产品策略通常是:先做好 agent-friendly CLI,再在此基础上薄薄包一层 MCP。 CLI 是 source of truth,MCP 只是”更贵但更结构化”的壳。反过来做通常会付出额外的维护代价。
stdout 是机器通道,stderr 是人类通道这是最值得被写进规范的一条。
对 Agent 来说,最理想的契约不是”输出尽量清晰”,而是:
stdout:只放机器可消费的数据stderr:只放提示、日志、警告、进度、解释性文本❌ 反例
1 | $ mycli resource get |
Agent 必须写正则去剥离首尾噪音,且任何一次日志格式微调都会让解析失败。
✅ 正例
1 | $ mycli resource get --json |
即使 stderr 里有日志,stdout > data.json 也能保证是纯 JSON。
isatty(stdout) 为 false 时,默认关闭彩色与动画(NO_COLOR 公约见第九节)。--quiet 是要求 stderr 静默,不是关闭 stdout 数据。--verbose 只增加 stderr 信息量,绝不污染 stdout。--json,而且把 JSON 当正式接口来维护不是”能输出 JSON”就够了,而是要像对待 HTTP API 那样对待它:稳定、完整、版本化、可演进。
--json不仅是 list,get / create / update / delete / status / validate / diff / logs 全部都该支持。
❌ 反例
1 | { "message": "User created successfully" } |
Agent 得继续猜:ID 呢?状态呢?真的成功了吗?
✅ 正例
1 | { |
❌ 反例:一会儿 []、一会儿 {}、一会儿 "No results"。
✅ 正例
1 | { "ok": true, "data": [], "meta": { "count": 0 } } |
1 | { |
Agent 可以基于 code 精确分支,比读自然语言可靠得多。
一旦 --json 成为接口,任何字段重命名都是破坏性变更。
meta.schema_version 中声明版本。--json-version=v2,旧版继续兼容至少一个大版本。2026-04-21T09:30:00Z),不要 “2 days ago”、”yesterday”。active/failed/pending),在 --help 或 mycli status --list-values 可枚举。“stdout 纯 JSON” 的原则遇到长任务(构建、部署、训练、日志拉取)会不够用——一次性吐一个 JSON 意味着过程中 Agent 什么都看不到。
更好的做法是 NDJSON(Newline-Delimited JSON):stdout 每行是一个独立 JSON 事件。
1 | $ mycli release deploy --env prod --json |
好处:
type: result 或 type: error),让消费者知道什么时候停。ts(ISO-8601 UTC),方便后排序/去重。--json=single / --json=stream 二选一。把进度信息用文本夹在 JSON 前后:
1 | Building... |
这对人类看着没毛病,对 Agent 是灾难。
这是面向 Agent 最容易被忽略、却最影响实际效果的一点。 一个 kubectl get pods -A -o json 动辄几 MB,塞进上下文等于直接爆窗口。
默认截断 + 显式分页
1 | { |
--limit 和 --cursor 是一对组合拳。
字段投影:--fields id,name,status 让 Agent 只要它要的列,可以减少 80% 以上的 token。
过滤优先于分页:提供 --filter status=failed --since 7d,比让 Agent 拉全量再过滤省得多。
摘要模式:--summary 只返回计数、分组等聚合结果。
明确告知被截断:永远不要沉默地丢数据,必须有 truncated: true 之类的信号。
一条命令返回 200MB JSON,没有分页,也没有截断提示。Agent 要么 OOM 要么被迫上 head/jq 做二次加工,而 head 截断会破坏 JSON 语法。
人类用户经常只看一眼报错文案;Agent 更依赖退出码来决定下一步。
退出码不是礼节,而是状态机接口。
sysexits.h 64–78)| 码 | 含义 | Agent 典型响应 |
|---|---|---|
| 0 | 成功 | 继续 |
| 1 | 通用失败(兜底) | 查 stderr |
| 2 | 参数错误(EX_USAGE=64) |
重新读 --help |
| 3 | 认证失败(EX_NOPERM=77) |
检查 env / 重新登录 |
| 4 | 资源不存在 | 跳过或重建 |
| 5 | 权限不足 | 转人工 |
| 6 | 网络/临时失败 | 指数退避重试 |
| 7 | 冲突,需人工确认 | 转人工或加 --force |
| 8 | 前置依赖未满足 | 先装依赖/先建资源 |
注:具体数值可以沿用 sysexits 的 64+,也可以用上表的 2–8。关键不是数字,而是团队内一致 + 每个码文档化 + mycli --help 里写清楚。
无论什么错都退出 1,Agent 只能靠匹配 stderr 文本来分支——一次文案改动就能打爆它。
CLI 对 Agent 最大的优势之一,是天然具备自描述能力:--help、子命令层级、参数说明,本质上都是工具的即时 schema。
1 | mycli --help |
让 Agent 能逐层探索,而不是一次性暴露 2000 行帮助。
1 | Output: |
每个高频子命令至少给一条最短成功路径:
1 |
|
1 | mycli --list |
为 bash/zsh/fish 生成补全(mycli completion bash),本质上给 Agent 也提供了”有哪些参数可选”的 source of truth——很多 Agent harness 已经会读补全脚本。
AGENTS.md:从命令级 discoverability 到任务级 strategy社区事实标准正在向 AGENTS.md 收敛(Cursor、Aider、Zed、OpenAI Codex 等都在读它);Anthropic 的 Skills 是另一套机制。CLI 作者可以提供以下三层中的任意一层或多层:
AGENTS.md(推荐起步):随仓库分发的 Agent 使用手册。mycli agent-prompt 命令:打印一段可直接注入 Agent 系统提示的精简说明。--help 告诉 Agent:这个命令怎么调;AGENTS.md 告诉 Agent:遇到某类任务,应该先调哪个命令、再调哪个命令、哪些坑要避开。
1 | # MyCLI Agent Guide |
CLI 的未来:不只是有帮助文档,而是能主动”教会 Agent 怎么用自己”。
传统 CLI 很喜欢:首次运行弹登录、删除前 Are you sure?、参数缺失进表单、spinner、Press any key——对人类友好,对 Agent 是灾难。
| 交互(TTY) | 非交互(CI/Agent) | |
|---|---|---|
| 彩色 | ✅ | ❌(遵守 NO_COLOR) |
| 进度条/spinner | ✅ | ❌(改用 NDJSON 事件) |
| 二次确认弹窗 | ✅ | ❌(需要时显式要 --yes) |
| 参数缺失进表单 | ✅ | ❌(直接退 2) |
| 首次运行登录向导 | ✅ | ❌(报错并提示 env 变量) |
判断依据:isatty(stdin) && isatty(stdout) + 环境变量 CI / MYCLI_NON_INTERACTIVE。
NO_COLOR 环境变量(no-color.org)存在即关闭所有 ANSI 色彩,不论 TTY。TERM=dumb 同样应关闭彩色与光标控制。| head -n 10 被关闭管道时不要报错退出。面向 Agent 的 CLI,安全不能只靠 README 里的”请谨慎使用”。
read:直接执行。write:需 --yes(非交互场景)。dangerous:需 --force,关键操作再加 --confirm <resource-id> 要求 Agent 复述 ID。1 | mycli config update --file prod.yaml --yes |
参考 kubectl delete 与 terraform destroy:前者用 --force --grace-period=0,后者强制交互确认除非 -auto-approve——都是把风险编码进参数的好例子。
让 Agent 具备可验证的安全边界。很多系统失败,并不是模型不会推理,而是工具给了它”过度自由”。
Agent 会天然地重试。只要你给它一个”可能是临时失败”的信号,它大概率会再次执行。
1 | mycli invoice create --request-id req_20260421_abc --json |
服务端用 request_id 去重 24h,第二次调用返回同一结果而不是创建新记录。
--dry-run1 | mycli release deploy --env prod --dry-run --json |
plan / apply 二阶段(参考 Terraform)1 | mycli infra plan --out plan_123.json |
把”理解变化”和”执行变化”拆开,Agent 可以先读 plan、让人类或另一个模型审一遍,再 apply。
1 | { |
❌ 反例
1 | NAME STATUS CREATED |
问题:相对时间无法稳定比较;名称可能不唯一;列宽表格难以解析。
✅ 正例
1 | { |
prj_、usr_、rel_),便于 Agent 一眼识别类型。LC_ALL / 时区影响。mycli project get --id prj_123 而不是只能 --name)。❌ 反例:tool do -x -m fast
✅ 正例:tool convert --input in.md --output out.html --mode fast
规则:
-h/-v 除外)。判断标准:脱离文档时,模型能不能大致猜中用途?
| 方式 | 推荐度 | 说明 |
|---|---|---|
环境变量(MYCLI_TOKEN) |
⭐⭐⭐ | CI/Agent 默认 |
stdin(--token-stdin) |
⭐⭐⭐ | 避免进 shell history |
配置文件(~/.mycli/config) |
⭐⭐ | 人类日常使用 |
命令行参数(--token xxx) |
❌ | 会进 ps/history,不要做 |
并且:
--verbose 模式)。mycli auth whoami --json 让 Agent 自检当前身份。Agent 对环境脆弱性的容忍度远低于人类开发者——人类会手动修,Agent 往往只会”再试一次”。
优先目标:
mycli --version 输出 semver + commit hash + build date。mycli doctor 自检:依赖、认证、网络、权限一次性扫描并结构化报告。ImportError。1 | $ mycli doctor --json |
工具质量不只靠单元测试,还要靠系统化评测——尤其是让真实 Agent 去跑一遍。
1)语法层:参数一致性、--help 完整性、所有核心命令 --json 覆盖、错误码稳定。
2)契约层:stdout/stderr 不混、JSON schema 无漂移、non-TTY 不阻塞、错误可恢复、NDJSON 终态事件必有。
3)Agent 实战层:给真实 Agent 一组任务,统计指标。
1 |
|
每次发版跑一遍,退化立即可见。
大部分读者不是新写 CLI,而是改老的。一口气重写成本过高,建议按下列顺序 retrofit(每步都能单独发布、独立收益):
--json,字段按 {ok, data, meta} 结构。retryable 字段。--limit。--yes、不弹任何向导)。AGENTS.md、建评测集、每版本跑一遍。反模式:一次性推倒重来、把所有命令都加 --json 但 schema 不稳定、AGENTS.md 写了但不跟代码同步演进。
学习最快的方式是看业界做对和做错的地方。
kubectl:-o json / -o yaml / -o jsonpath 是典范;缺点是 kubectl apply 的输出一会儿人类文本一会儿结构化,非 -o 场景 stderr/stdout 也有混用。gh(GitHub CLI):--json field1,field2 字段投影做得极好,极大压缩 Agent 上下文;gh api 暴露底层 REST 兜底;AGENTS.md 式引导欠缺。stripe CLI:--api-key 和 env var 组合清晰,stripe events resume 幂等支持好;错误 JSON 结构稳定。terraform:plan/apply 二阶段、-auto-approve、-json 流式输出是 Agent 友好模板级案例。aws CLI v2:--output json 默认结构化、分页 --max-items/--starting-token 完善;但帮助文档过长、子命令数量巨大,Agent 首次建模成本高——提醒我们 discoverability 要配合 AGENTS.md 裁剪。docker:历史包袱重,docker ps 默认输出表格且列不稳定,--format '\{\{json \.\}\}' 是事实标准但不直观——反面教材:JSON 不该是隐藏档。npm/pnpm:--json 覆盖不全、错误信息人机混排是典型反例。很多人以为”面向 Agent 友好 = 多加个 --json“。
真正让人眼前一亮的 CLI,不是”让 Agent 能调”,而是:
它会主动降低 Agent 的推理负担。
具体表现:
AGENTS.md + workflow 示例retryable 字段--confirm把复杂性消解在工具设计里,而不是丢给模型。 这是 AI 时代 CLI 设计真正的升级方向。
--json{ok, data, meta} 或等价的稳定结构meta.schema_version 字段存在"No results"--json=stream)并以终态事件收尾code / message / hint / retryable--help 中文档化--limit,支持 --cursor 分页--fields 字段投影--filter / --since 等过滤truncated: true 信号NO_COLOR 公约--yes / --force--confirm <resource-id> 复述--help,每个子命令都有mycli doctor 自检mycli --version 含 commit hashAGENTS.md在 GUI 时代,软件的核心竞争力常常体现在界面。
但在 Agent 时代,很多系统首先被消费的,不再是界面,而是:
从这个意义上说,CLI 正在重新变得重要——不是因为大家回到了终端,而是因为 Agent 天生适合终端。
所以面向 AI / Agent 开发 CLI,最值得记住的一句话是:
把你的 CLI 当成一个给模型调用的 API 来设计,而不是一个给人临时敲一下的命令。
这样做,CLI 才会从”脚手架工具”进化成”Agent 基础设施”。
NO_COLOR 环境变量公约sysexits.h — 退出码约定kubectl -o json、GitHub gh --json — 值得研究的工业级 agent-friendly 实现SKILL.md → AGENTS.md,补充社区标准说明此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。