面向 AI / Agent 友好的 CLI 开发建议
内容提要
本文提出AI时代CLI应面向Agent设计,核心原则包括:stdout只输出机器可解析数据、stderr处理日志;默认提供稳定JSON接口并版本化;长任务用NDJSON流式输出;控制输出体积避免爆上下文;退出码分层可编排;帮助信息便于Agent建模;提供AGENTS.md指导任务策略;区分交互与非交互模式;命令幂等可重试;安全分级编码;凭证走安全通道;环境可移植;系统化评测。最终将CLI视为可组合的文本协议,降低Agent推理负担。
延伸解读
CLI 与 MCP 的定位差异
文章指出,CLI 与 MCP Server 并非二选一,而是各有优劣:CLI 接入成本低、上下文成本低、人类可用性高,但类型安全弱;MCP 则相反。合理策略是先做好 agent-friendly CLI,再在其上封装 MCP,CLI 作为 source of truth,MCP 只是更结构化的壳。这提醒开发者,在引入 MCP 之前,应优先夯实 CLI 的机器可读性。
输出纪律:stdout 与 stderr 的严格分离
文章强调,面向 Agent 的 CLI 必须将 stdout 作为机器通道,只输出可解析数据;stderr 用于日志、提示等人类信息。反例中,将进度信息混入 stdout 会导致 Agent 解析失败。工程纪律包括:进度、spinner 等一律走 stderr;TTY 检测关闭彩色;--quiet 只静默 stderr,不关闭 stdout 数据。这要求开发者重新审视现有 CLI 的输出习惯。
上下文预算:控制输出体积
文章指出,Agent 的上下文窗口是稀缺资源,一次命令返回几 MB JSON 会直接爆掉窗口。因此,CLI 应默认截断、支持分页(--limit/--cursor)、字段投影(--fields)、过滤(--filter)和摘要模式(--summary),并明确告知截断(truncated: true)。这提示开发者,面向 Agent 的 CLI 不仅要输出结构化数据,还要考虑数据量对 token 消耗的影响。
安全分级与幂等设计
文章建议将命令按 read/write/dangerous 分级,危险操作需 --force 和 --confirm 复述资源 ID,以给 Agent 可验证的安全边界。同时,命令应幂等、可重试,支持 --dry-run 和 plan/apply 二阶段,错误信息中标注 retryable 字段。这些设计让 Agent 能安全地自动执行任务,减少人工介入。
Q&A
为什么在AI时代CLI需要面向Agent设计?
因为AI Agent作为新的CLI用户,需要稳定解析输出、可预测地恢复错误、将CLI作为工具链节点接入更大工作流,并且其上下文窗口是稀缺资源,冗余输出会消耗token。因此CLI需要从“终端入口”变成“系统接口”,即面向Agent的文本API。
面向Agent的CLI中,stdout和stderr应该分别输出什么?
stdout只输出机器可解析的数据(如JSON),stderr只输出日志、警告、进度等人类可读的提示信息。退出码表达最终状态。这样Agent可以稳定解析stdout,而不受日志干扰。
为什么CLI需要提供--json参数,并且要像维护API一样维护JSON输出?
因为Agent需要稳定、结构化的数据来解析,而不是自然语言文本。提供--json并维护其稳定性(如版本化、字段一致、错误结构化)可以让Agent可靠地处理输出,避免因格式变化而失败。
长任务中,为什么推荐使用NDJSON流式输出?
因为长任务一次性输出JSON会让Agent在过程中无法获取进度,而NDJSON每行一个JSON事件,Agent可以边读边决策,人类也能看到进度,且容器/CI日志采集友好。设计要点是最后一行必须是终态事件,每条事件带时间戳。
如何控制CLI输出体积,避免塞爆Agent的上下文窗口?
通过默认截断+显式分页(--limit和--cursor)、字段投影(--fields)、过滤优先(--filter)、摘要模式(--summary)以及明确告知截断(truncated: true)来控制输出体积,减少token消耗。
面向Agent的CLI,退出码应该如何设计?
退出码应分层,区分成功、通用失败、参数错误、认证失败、资源不存在、权限不足、网络/临时失败、冲突、前置依赖未满足等,并文档化。这样Agent可以根据退出码决定下一步操作,而不是依赖解析stderr文本。
AGENTS.md文件在Agent友好的CLI中起什么作用?
AGENTS.md是随仓库分发的Agent使用手册,提供任务级策略,告诉Agent遇到某类任务应该先调哪个命令、再调哪个命令、哪些坑要避开。它补充了--help的命令级信息,帮助Agent高效完成任务。
CLI如何区分交互模式和非交互模式?
通过检测isatty(stdin)和isatty(stdout)以及环境变量CI或MYCLI_NON_INTERACTIVE来区分。交互模式可以有彩色、进度条、二次确认等;非交互模式必须禁用这些,遵守NO_COLOR,不等待输入,需要确认时显式使用--yes。
面向Agent的CLI,安全分级如何编码进命令语义?
将命令分为read、write、dangerous三级。read直接执行;write需--yes;dangerous需--force,关键操作再加--confirm <resource-id>要求复述ID。这样Agent有明确的安全边界,避免过度自由导致事故。
为什么CLI命令应该幂等、可重试、可预演?
因为Agent会天然地重试,如果命令不是幂等的,重试可能导致重复创建或副作用。通过幂等key、--dry-run、plan/apply二阶段、显式标注retryable,可以让Agent安全地重试和预演,提高可靠性。