研究报告 · 约 30,231 字 · 预计推送 4 部分

命令行界面设计:参数解析、输出格式化、退出码与可组合性(综合报告) 未开始

目录

题记与说明

本报告由同日(2026-11-05)完成的两份章节稿综合而成:纵轴章节《命令行界面设计——纵轴发展史》(output/reports/parts/2026-11-05-命令行界面设计-参数解析-输出格式化-退出码-可组合性-vertical.md)与横轴章节《命令行界面设计——横向对比报告》(同目录 -horizontal.md)。综合工作做了三件事:合并两章重复的事实与来源、消除两章间的表述分歧(校准记录见 §3.5)、在两条轴线交叉处产出单章无法得到的洞察。所有版本号与维护状态均为检索时点 2026-11-05 的快照;关键事实均附来源链接,凡未能检索验证、出自模型既有知识的断言均单独标注(见文末说明)。

最终稿修订说明(已按独立审读意见逐条修订,正文结构与未被质疑的内容未改动):① 统一退出码表述,消除"只有 0 被标准锁死"与 §1.4 shell 保留值(126/127/>128)的自相矛盾(TL;DR、§2.5、§3.1);② §1.7 中 sysexits 的"收缩到邮件领域"改为与 §2.2/§2.5/§3.6 一致的限定表述;③ 删去无出处的"128–165"上限,改为"128 以上(bash 的 128+N 约定)";④ 为 CLI Agent Spec 与 AOI-CLI 补充规范原文出处并核对原文(§2.2);⑤ 为 1971 Thompson shell、1983 GNU、1991 Linux、2001 POSIX 合并四处史实补来源链接;⑥ §2.1 竞品地图补齐 jq 与 MCP 两行;⑦ 修正 click 维护状态、选型矩阵退出码栏与 PowerShell 快照时点三处费解表述;⑧ §2.4 点破 JSONL 事件流与"被管道不自动切 JSON"的共存关系,§3.6 检查清单补"何时引入更多分类码"、风险提示补"观望判定信号"。

TL;DR

CLI 设计的四个议题——参数解析、输出格式化、退出码、可组合性——六十年只围绕一个张力展开:程序要同时伺服人与机器。参数解析从手写 argv 经 getopt、GNU 长选项、POSIX 准则走到声明式框架,2024 年 getopt_long 入 POSIX 正典;输出端确立「stdout 是数据、stderr 是话语」,TTY 检测+NO_COLOR+--json 构成人机双轨;退出码除 shell 保留值(126/127/128+N)外仅 0 被标准定义,是四要素中最欠标准化的一环;可组合性以文本管道为基线,与 PowerShell、Nushell 的结构化路线并存不替。2024 年起 AI Agent 成为 CLI 的第二用户:非交互、--json、--dry-run、可预测退出码从加分项变为硬指标,agent 规范以「机器模式叠加」的方式与 clig.dev 共存而非取而代之。给开发者的收敛建议:用成熟解析库、守住流分流、退出码 0/1/2 并文档化、在文本管道内打结构化补丁。

0. 课题界定

命令行界面(CLI)设计是一门围绕"程序如何被调用、如何说话、如何被机器判读"的工程学问,核心议题有四(纵轴章节 §0):

由于本课题不是单一产品而是一套界面设计约定,横轴章节把"同类与替代方案"拆成三个层次:规范层(POSIX Utility Conventions、GNU Coding Standards、12 Factor CLI Apps、clig.dev,以及 2025 年以来面向 AI Agent 的 CLI Agent Spec 与 AOI-CLI——这一层彼此互为竞品,争夺"开发者以谁为准");工具层(POSIX getopt/shell getopts、GNU getopt_long、Python 的 argparse/docopt/click/typer、Go 的 cobra+pflag、Rust 的 clap、Node 的 commander.js 等解析实现);范式层(Unix 文本管道 vs PowerShell 对象管道 vs Nushell 结构化管道 vs jq 式 JSON 后处理,以及把"调用别的软件"整体替换掉的 MCP)。四个议题在三个层次上各有不同的竞品集合。

这四个议题共同构成 Unix 哲学"单一职责、文本流组合"在现代的落点,也是 POSIX 与后续现代 CLI 规范(Heroku 风格指南、12 Factor CLI Apps、clig.dev)反复规定的对象。


1. 纵轴:发展脉络(1964–2026)

1.1 阶段一(1964–1979):诞生期——管道、组合哲学与流分离

CLI 的"可组合性"基因早于 Unix 本身。1964 年,贝尔实验室的 Douglas McIlroy 在一份内部备忘录中提出:程序应当像园浇水管一样彼此插接、可互换组合。这份备忘录被视为管道思想的起源(toroid.org 存档的备忘录影印件、Wikipedia: Pipeline (Unix)))。1971 年 Ken Thompson 发布第一版 Unix shell(Wikipedia: Thompson shell:随 1971 年 Unix 第一版引入、为首个 Unix shell),确立了"命令 + 空白分隔的参数"这一基本调用语法。1973 年 1 月,Thompson 在"一个狂热的夜晚"实现了 pipe() 系统调用、shell 管道语法与一批配套工具,并于同年 2 月随 Version 3 Unix 手册发布;由此 grep | sort | wc 式的组合成为日常(Unix Heritage Wiki: pipes)。McIlroy 后来在 1978 年 Bell System Technical Journal 的前言中把这一哲学总结为名言:"让每个程序的输出成为另一个尚不存在的程序的输入……不要在输出中掺杂无关信息"(转引见 Wikipedia: Unix philosophy)。

这一时期还埋下了另外两个议题的种子。其一是流分离:1970 年代中后期,stderr 从 stdout 中分离出来成为独立的标准流,使"数据"与"报错"得以分开处理(此为一般性共识,精确版本节点未检索验证)。其二是退出码:shell 的 $? 参数把子进程的结束状态暴露给脚本,1979 年 Version 7 Unix 携带的 Bourne shell 使 0 = 成功 的约定广泛传播(模型既有知识,未单独检索验证)。在输出端,1976 年 ECMA-48 与 1979 年 ANSI X3.64 定义的控制序列(含颜色)为日后终端彩色输出提供了底层协议(Wikipedia: ANSI escape code)。

驱动因素:小型机内存与 CPU 极其有限,逼出"每个程序只做一件事、用文本流拼接";多用户分时系统让交互式 shell 取代批处理作业卡。

1.2 阶段二(1980–1985):早期工程化——getopt 与 sysexits

随着 Unix 工具数量膨胀,各程序"手写 argv 循环"的错误处理开始失控。1980 年 5 月 16 日的 System III 手册页显示,getopt(1) 已作为解析命令行选项的标准工具出现;AT&T 在 1985 年 UNIFORUM 会议(达拉斯)上将其源码对外公开发布,随后演化为 C 库函数 getopt(3)(System III getopt(1) 手册页影印件、Wikipedia: Getopt);1986 年,SVR3 的 Bourne shell 又引入内建的 getopts(Wikipedia: Getopts)。"选项解析"第一次从每个程序的家务事,变成了一项可复用的基础设施。

同一时期,退出码体系开始分化。sendmail(Eric Allman)为了在邮件投递代理与守护进程之间传递更细粒度的失败原因,形成了一组 64–78 的扩展退出码;这套编码后来固化为 BSD 的 <sysexits.h>(EX_USAGE=64、EX_NOINPUT=66、EX_TEMPFAIL=75 等)。一个常被搞错的细节:sysexits(3) 手册页自己承认该文件"出现在 4.3BSD 之后的某个版本",而非常被引用的"4.3BSD 首见"(Mac OS X sysexits(3) 手册页、staticdata.dev exit-codes 数据集)。

驱动因素:Unix 的 BSD / System V 两大支系分裂,同一工具的行为差异催生了对统一约定的需求;邮件系统等"无人值守"的服务程序需要比 0/1 更丰富的机器可判读状态。

1.3 阶段三(1983–1991):GNU 与长选项——--help、--version 与路线之争

1983 年 Richard Stallman 发起 GNU 计划(1983 年 9 月 27 日 Usenet 公告,FSF: About GNU),给 CLI 带来一次至今仍在生效的范式升级:长选项。GNU 软件普遍支持 --help、--version 以及形如 --verbose 的自描述长选项,并把这套约定写进 GNU Coding Standards(Command-Line Interfaces 节);配套的 getopt_long 在 GNU/glibc 生态中普及(确切入库年份未检索验证),长选项随 Linux 的崛起(1991 年 Linus 发布内核——8 月 25 日宣告、9 月 17 日发布 0.01,Wikipedia: Linux kernel,GNU 用户态工具随之铺开)成为事实标准。

1986 年,Rob Pike 与 Brian Kernighan 发表《Program Design in the UNIX Environment》(即著名的 "cat -v considered harmful"),批评 GNU/MIT 式给 cat 塞入 -v 等选项的做法违背"单一职责"——这是 CLI 设计史上第一次高调的"克制 vs 膨胀"路线之争(全文存档;事件年份为模型既有知识)。

驱动因素:GNU 工具要在各 Unix 上保持一致体验,自描述的长选项降低学习成本;Linux 诞生后 GNU 工具链借助发行版获得空前的分发规模。

1.4 阶段四(1992–2017):POSIX 时代——语法准则与退出码的法定化

1992 年 IEEE Std 1003.2-1992(POSIX.2,Shell and Utilities)发布,与 X/Open Curses and Utilities Issue 4 在相应技术上等同(The Open Group: Commands and Utilities Issue 4)。它把散落在各工具间的习惯固化成 Utility Syntax Guidelines(12 条):命令名 2–9 字符、选项用单字母并前置 -、无参选项可分组、-- 终止选项解析、- 代表 stdin/stdout 等(POSIX.1-2017 XBD 第 12 章);其中最关键的 Guideline 12 要求"选项相对于操作数的顺序不应影响工具功能"。2001 年起 POSIX.1 与 POSIX.2 合并为统一的基础规范(POSIX.1-2001 / SUSv3,Linux man-pages standards(7):对 POSIX.1、POSIX.2 与 SUS 的 2001 年修订与合并),第 12 章"Utility Conventions"沿用至今。

退出码同样被"法定化":POSIX shell 规定命令找不到退出码为 127、找到但不可执行为 126、因信号终止则大于 128;标准措辞谨慎地只要求"大于 128",128+信号号 是 glibc/bash 等实现的可移植实践(POSIX.1-2024 XCU 2.8.2 Exit Status)。

这一阶段,POSIX 语法准则成为几乎所有语言解析库的隐形模板:Perl 的 Getopt::Long、Python 2.3 引入的 optparse,都在复刻"短选项 + 长选项 + --"的模型。2009 年 Python 通过 PEP 389 把第三方库 argparse 收编进标准库(随 Python 2.7/3.2 发布),官方宣布 optparse 进入弃用状态;argparse 首次把子命令(git add 式)与可变参数 nargs 做成标准库能力(PEP 389)。2006 年微软 PowerShell 1.0 发布,管道里流动的不再是文本而是对象——这是对"文本流可组合性"的一次正面替代尝试(Wikipedia: PowerShell;事件年份为模型既有知识)。2003 年 Eric Raymond 的《The Art of UNIX Programming》则把"Rule of Silence""Rule of Separation"等 CLI 设计法则成文化(模型既有知识)。

驱动因素:企业采购要求跨 Unix(AIX/HP-UX/Solaris/…)可移植,标准化的命令行为成为合同级需求;脚本化运维(cron、CI 前身)要求退出码可编程判读。

1.5 阶段五(2011–2019):现代 CLI 文艺复兴——声明式框架与"体验优先"

2010 年代,云与 DevOps 让 CLI 从"系统管理员的附属品"变成产品的一等门面,专用解析框架大爆发:

设计规范也在快速成文。Heroku 以自家 CLI 为样板发布 CLI Style Guide,规定 help 结构、输出与错误的处理(devcenter.heroku.com)。2018 年 10 月,Heroku CLI 前负责人 Jeff Dickey 发表 "12 Factor CLI Apps",把 12-Factor App 方法论移植到 CLI:涵盖设计、配置、退出码(0 成功、1 失败、2 用法错误)、输出、错误、help、版本化等 12 条(jdx.dev 原文;镜像:Medium)。输出端则出现去干扰运动:2017 年提出的 NO_COLOR 约定(no-color.org),配合 TERM=dumb 检测与 --no-color 标志,"颜色必须可被关闭"成为礼貌底线;--json / --output json 也在这一时期成为各大云 CLI(AWS CLI 等)的通用出口。2019 年 8 月 Nushell 诞生,把"表格/结构化数据管道"推向 shell 本体(诞生博客、github.com/nushell/nushell)。

驱动因素:云计算与 CI/CD 把 CLI 嵌入人机与机机两条交互链路;开源框架间的竞争使"自动生成 help、补全、类型校验"成为框架标配,参数解析彻底从手写循环变为声明式工程。

1.6 阶段六(2020–2026):clig.dev 集大成与智能体时代

2020 年 12 月,由 Aanand Prasad、Ben Firshman(Docker Compose 共同作者)、Carl Tashian、Eva Parish 撰写的 Command Line Interface Guidelines(clig.dev) 上线,被广泛视为 Unix 时代设计原则的"现代更新版"(clig.dev、InfoQ 2020 年 12 月访谈)。它在四个议题维度上都给出了可执行条款(细则展开见 §2.2、§2.4):

2024 年是规范层面的大年:POSIX Issue 8(IEEE Std 1003.1-2024)于 2024 年 6 月发布,其中一项标志性变化是把 GNU 系的 getopt_long / getopt_long_only 连同 option 结构体与 no_argument / required_argument / optional_argument 常量一并收编进 <getopt.h>——"长选项"这一延宕三十余年的事实标准终于入法(IEEE 1003.1-2024、The Open Group Base Specifications Issue 8、Open Group POSIX.1-2024 FAQ;Issue 8 还新增了 readlink、realpath、timeout 等实用工具,见 HN 讨论)。同年 11 月,Anthropic 发布 Model Context Protocol(MCP),为工具调用提供结构化接口(anthropic.com/news/model-context-protocol)。

2025 年以来,编码智能体(Claude Code、Codex CLI、Gemini CLI 等,均为模型既有知识、未逐项检索验证)让"机器调用 CLI"的规模空前放大,这反过来重塑四个议题的优先级:退出码从"提示人类"变为"agent 的控制流信号";--json 与幂等、非交互从加分项变为 agent 兼容性硬指标。横轴章节还检索到面向 Agent 的 CLI 规范开始成文——CLI Agent Spec 与 AOI-CLI(Machine Mode)(machinemode.io/compare,详见 §2.2、§2.5)。而"人类可读输出优先"的原则并未被推翻——clig.dev 式双轨设计(TTY 时取悦人,管道时取悦机器)成为最稳妥的答案。

驱动因素:LLM 智能体成为 CLI 的新"用户群体",无 GUI、无交互、依赖退出码与结构化输出;POSIX 组织(Austin Group)持续运维标准,把三十年间工业界自发形成的约定回灌进正式规范。

1.7 四条议题的演化曲线(纵轴小结)

议题起点关键节点当下状态
参数解析1971 Thompson shell 手写 argv;1980 System III getoptGNU 长选项(1980s)→ POSIX.2-1992 语法准则 → argparse(PEP 389)/Cobra/Click/clap 声明式框架 → 2024 年 Issue 8 收编 getopt_long解析库化、子命令化、长选项入标准
输出格式化stdout/stderr 分离(1970s);ECMA-48 控制序列(1976)TTY 检测 + --no-color 惯例 → NO_COLOR(2017)→ --json/--plain 双轨人机双轨:TTY 取悦人,管道时纯文本或 JSON
退出码Bourne shell $?;sendmail 的 sysexits(64–78)POSIX 127/126/>128 法定化;12 Factor CLI 的 0/1/2 简化约定简约 0/1/2 为主流,sysexits 在主流人工 CLI 中少见,但被 AOI-CLI 等 agent 规范重新采用(§2.2、§2.5);agent 规范反向加码
可组合性1964 McIlroy 备忘录;1973 管道落地"文本流 + -- + -" 哲学 → jq(2012)/Nushell(2019)结构化管道 → 智能体把管道消费方换成 LLM文本流仍是通用语,结构化输出成为新方言

2. 横轴:横向对比(2026-11-05 时点)

2.1 总览:三个层次的竞品地图

层次对比对象定位一句话差异
规范POSIX Utility Conventions国际标准(IEEE Std 1003.1)只约束"是什么合法",不管"什么是好体验"
规范GNU Coding Standards事实标准(GNU 生态)在 POSIX 之上叠加长选项、--help/--version 强制
规范12 Factor CLI Apps(2018)经验文章来自 Heroku CLI/oclif 的工程实践,无合规工具
规范clig.dev(2020,持续维护)当代事实标准指南覆盖四子课题全部,社区引用度最高
规范CLI Agent Spec / AOI-CLI(2025+)新竞品为 AI Agent 而非人类重定义输出与退出码
工具getopt / getopts解析原语无长选项、无子命令框架,靠 shell 手写
工具docopt声明式解析已成弃养软件(Python 版 2014 年后停更)
工具click / typer(Python)程序式 / 类型驱动解析typer 以类型注解换样板代码
工具cobra + pflag(Go)框架式解析kubectl/docker/gh/helm 的共同底座
工具clap(Rust)声明式 derive 解析最流行但增大二进制体积
范式Unix 文本管道可组合性基线文本即通用语,解析脆弱
范式PowerShell 对象管道结构化替代.NET 对象直接流动,重但免解析
范式Nushell 结构化管道第三条路线Unix 手感 + PowerShell 式结构,尚未到 1.0
范式jq / JSON 后处理结构化补丁管道内查询语言(详见 §2.6)
范式MCP机器调用的替代通道绕开 CLI 的结构化调用通道(详见 §2.6)

2.2 规范层正面对决:POSIX vs GNU vs 12 Factor vs CLIG vs Agent 规范

依据 machinemode.io/compare 与各规范原文。两份 agent 规范的原始出处(2026-11-05 已核对原文,下表相应细节均与原文相符):CLI Agent Spec v1.16 原文见 cli-agent-spec.github.io(仓库 github.com/cli-agent-spec/cli-agent-spec);AOI-CLI v1.0-alpha(Machine Mode 标准的 CLI profile)原文见 machinemode.io/spec(组织 github.com/agentoperable)。唯一例外是下表 AOI-CLI 行的合规工具 aoi-probe——该工具仅见于对比页、未出现在规范原文中,其余细节(15 具名码、retryable/side_effects、JSON 信封、--format jsonl、167 条要求、sysexits 兼容、JSONL 事件流、aoi-lint)均已对上原文:

规范年代面向对象成功信号错误/退出码合规工具
POSIX Utility Conventions1992 年成文(POSIX.2-1992)标准制定者(不涉及输出设计)不规定无
GNU Coding Standards1990sGNU 开发者不涉及不系统规定无
12 Factor CLI Apps2018终端前的人exit 00/1/2 简化约定(原文如此)无
CLIG2020 发布、持续维护终端前的人exit 0/非零0–255、映射主要失败模式无(纯指南)
CLI Agent Spec v1.162025+AI AgentJSON 信封 ok 字段 + 退出码15 具名码(0–14)+ retryable/side_effects确定性合规套件,167 条要求
AOI-CLI 1.0-alpha2025+AI Agentaoi:summary 收尾事件sysexits 兼容(64–78)+ 124/130/141aoi-lint、aoi-probe

该对比页面的结论值得直接引用:面向人的指南(CLIG、12 Factor)与面向 Agent 的规范不冲突——默认输出遵循前者,机器模式叠加后者。另一处值得强调的共识是流分流:CLIG 与 12 Factor CLI 在"主数据走 stdout、消息与错误走 stderr"上完全一致,且默认不要给 stderr 加 ERR:/WARN: 日志级别标签(verbose 模式除外),来源:clig.dev、12 Factor CLI Apps、galligan 的 Console vs. Logger 摘录。

2.3 参数解析:POSIX/GNU 基线与九个实现

基线:POSIX.1-2017 第 12 章定义 12 条 Utility Syntax Guidelines——短选项以 - 前缀、操作数(operand)与选项区分、-abc 可组合、-o arg 与 -oarg 两种传参方式、-- 终结选项;--name=val 形式的长选项在该章 rationale 中出现(正式条目仅规定以 -- 开头避免冲突);最关键的 Guideline 12 要求选项与操作数的相对顺序不影响功能。来源:POSIX.1-2017 Chapter 12;最新版标准已推进到 IEEE 1003.1-2024。

GNU 对 POSIX 的"加法":GNU Coding Standards 在 POSIX 之上做了三件关键加法——必须用 getopt_long 为每个短选项提供等价长选项;长选项命名跨程序统一("任何 GNU 程序中 verbose 选项必须拼写为 --verbose");每个程序必须支持 --version 与 --help,且普通参数只作输入文件、输出文件应走 -o/--output。GNU 的 getopt 还"通常允许选项出现在任意位置",比 POSIX 更宽松。来源:GNU Coding Standards — Command-Line Interfaces。

解析库对比表(维护状态为检索时点快照):

库语言范式子命令类型校验Shell 补全维护状态代表采用者/来源
getopt/getoptsPOSIX shell原语无无无标准,永续所有 shell 脚本
GNU getopt_longC过程式无弱无标准GNU coreutils 全系
docopt语言无关声明式(usage 字符串即规格)弱无有(各移植版参差)弃养:Python 版 0.6.2 停于 2014,仓库 2018 年后无更新docopt.org、弃养状态 issue #519、types-docopt 说明
argparsePython 标准库过程式有弱有随 CPython 永续Python 全生态(PEP 389)
clickPython装饰器/程序式有手写转换器有活跃,文档跟踪 8.5.xWhy Click?(自述为何不沿用 optparse/argparse 行为)
typerPython类型注解驱动(基于 click)有强(Pydantic 可选)有活跃FastAPI 作者出品
cobra + pflagGo框架式(命令树)一等公民手写自动生成活跃:v1.10.2(2025-12 发布,pkg.go.dev)kubectl、gh、docker、helm、hugo;cobra README 自述 pflag 为 POSIX/GNU 风格
clapRust声明式 derive + builder有强(类型系统)自动生成活跃:v4.6.7(约检索前 2 个月,docs.rs/clap)Rust CLI 首选,代价是二进制体积
commander.jsNode程序式有弱(JS 天然弱)有活跃commander.js 仓库

逐项判断:

2.4 输出格式化:双轨制的细则与三种机器通道

无争议的底座是流分流(见 §2.2)。在此基础上必须厘清一个容易混淆的点:TTY 检测管的是"颜色与花哨格式",不管"自动切 JSON"。Prisma CLI 的输出规范文档指出一个事实——没有任何主流 CLI(gh/aws/kubectl)会在"被管道时"自动切换成 JSON;人类面向的部署输出应走 stderr,--json 才是 stdout 上的机器通道(来源:Prisma CLI Output Conventions;"CLI 的第二个用户是 Agent"的论述见 jedarden.com)。

机器可读输出的三种实现路径:

方案机制粒度控制特色来源
GitHub CLI(gh)--json <字段列表>字段级白名单,避免输出过肥内置 -q/--jq 内联过滤与 -t/--template Go 模板gh help formatting、GitHub 官方博客 Scripting with gh
kubectl-o json|yaml|wide|jsonpath|custom-columns输出格式+查询语言分离jsonpath 是"管道内查询"的最早大规模实践kubectl 官方文档
AWS CLI--output json|yaml|yaml-stream|text|table|off配置文件/env/旗标三级覆盖yaml-stream 为大结果流式设计;off 格式为结构化错误输出AWS CLI 输出文档、AWS CLI v2 新输出格式公告

CLIG 的双轨细则:人类可读优先,靠 TTY 检测猜测读者是谁;输出要保证 | grep 行为符合直觉;花式格式会破坏按行解析时提供 --plain(每行一条记录);传 --json 时输出格式化 JSON 以接入 jq;禁色条件四条——非 TTY、NO_COLOR 非空、TERM=dumb、--no-color。来源:clig.dev。NO_COLOR 本身是 2017 年发起的非正式标准,精确触发条件是"该环境变量存在且非空串时(无论取值),阻止添加 ANSI 颜色",来源:no-color.org。

2025 年后的新竞品维度:为 Agent 输出:

小结:输出格式的竞品格局已从"文本 vs JSON"二元,演化为"人类双轨(TTY 检测 + --plain)+ 机器单轨(--json)+ agent 三轨(信封或事件流)"的三层结构。

需要点破一个看似冲突之处:agent 的 JSONL 事件流属于显式机器通道(由 --format jsonl/--stream 这类旗标开启,见上文 CLI Agent Spec 的 REQ-O-004),与上文"被管道时不自动切 JSON"(Prisma 归纳的 gh/aws/kubectl 现状)并不矛盾——前者是调用方显式要求,后者只是禁止按 TTY 状态隐式切换输出格式。因此 TTY 双轨与 agent 流式输出可以共存于同一工具:TTY 上取悦人、被管道时输出纯文本、被 agent 以显式旗标调用时输出 JSON 信封或事件流。

2.5 退出码:四要素中标准化程度最低的一环

体系取值范围语义来源
POSIX/Shell 基线0=成功,1–255=失败;仅 0 被标准严格定义具体失败码靠各工具自定POSIX.1-2017、staticdata.dev 退出码汇编
Shell 特殊保留值126=找到但不可执行;127=命令不存在;128+N=被信号 N 杀死(130=SIGINT,137=SIGKILL)POSIX 只要求 >128,128+N 是 bash/glibc 等实现的强约定POSIX.1-2024 XCU 2.8.2、Unix & Linux SE、brandur.org、ditig.com 列表
BSD sysexits.h64–78(EX__BASE 起):EX_USAGE=64、EX_DATAERR=65、EX_NOINPUT=66、EX_UNAVAILABLE=69、EX_SOFTWARE=70、EX_IOERR=74、EX_TEMPFAIL=75、EX_CONFIG=78用法错误、数据错误等分类sysexits.h(3head) man 页、OpenBSD 源码
CLIG0=成功,非零=失败;要求把非零码映射到"最重要的失败模式",不规定数字指南级clig.dev
CLI Agent Spec15 个具名退出码(0–14),每个附带 retryable 与 side_effects 标志为 Agent 自动重试设计CLI Agent Spec v1.16 原文、对比页
AOI-CLIsysexits 兼容(64–78)+ 124/130/141进程级信号(SIGINT/SIGPIPE 等)保留在退出码层、不塞进 payloadAOI-CLI v1.0-alpha 原文、对比页
调和说明:表中"仅 0 被标准严格定义"说的是工具自身的退出语义——这是标准对工具作者的唯一定义;而 126/127/>128 是 POSIX shell(XCU 2.8.2)对命令查找失败与信号终止的规定(见 §1.4),属于 shell 层保留值,不是工具自定义的空间。两句话并不矛盾;本文 TL;DR 与 §3.1 统一采用"除 shell 保留值外仅 0 被标准定义"的措辞。

逐项判断:

2.6 可组合性:文本管道、对象管道、结构化管道与 MCP

范式数据模型解析成本与外部工具互通成熟度(检索时点)来源
Unix 文本管道字节流/文本高(awk/sed/grep 脆弱解析)原生(文本是通用语)50 年,永远在线经典;痛点讨论见 Unix SE: Unix equivalent of PowerShell?
PowerShell 对象管道.NET 对象(内存)零(免解析)外部命令退化为文本成熟:PowerShell 7.x 开源(MIT)、跨平台,检索时点(2026-11)处于 7.x 稳定线PowerShell 仓库、StackShare 对比
Nushell 结构化管道类型化表格/记录/列表(流式)零(内建结构化)外部为文本、内建为结构活跃但未到 1.0:检索时最新 0.116.1Nushell 诞生博客(自述融合 Unix 管道哲学与 PowerShell 结构化)、Atomic Object 解读
jq/JSON 后处理JSON 文档中(需学 jq DSL)任何带 --json 的工具成熟,已是事实标准 gluegh -q/--jq、CircleCI CLI 内置 --jq
MCP(替代调用方式)协议层结构化工具调用零(协议保证)与 CLI 在"机器调用"通道上构成替代竞争2025 年快速扩张xpander: MCP vs CLI for AI Agents(指出 CLI 在 token 效率上仍占优)

逐项判断:

2.7 横轴小结:三条收敛、两条分化

收敛:

  1. 语法收敛到 POSIX+GNU。无论 cobra 的 pflag、click 还是 clap,实现的都是"POSIX 短选项 + GNU 长选项"的并集;GNU 的 --help/--version 强制已被 CLIG 吸收为通用约定。
  2. --json 成为机器可读的事实标准,但实现粒度三派不同:gh 的字段白名单、kubectl 的格式+查询分离、AWS 的多级格式菜单。
  3. stdout/stderr 分流零争议,所有规范(POSIX 时代到 agent 规范)完全一致。

分化:

  1. 管道数据模型三派并存:文本字节流(Unix)、内存对象(PowerShell)、类型化结构流(Nushell)互不兼容,且没有一派胜出——CLI 设计者只能"在文本管道内打结构化补丁"。
  2. 退出码是四要素中最欠标准化的一环,而 agent 规范正在此维度反向加码(15 具名码、retryable 标志),2025 年后新出现的 envelope(JSON 信封)vs stream(JSONL 事件流)之争尚未收敛。

最大外部冲击:AI Agent 成为 CLI 的"第二用户",把 1970 年代为人类设计的四要素逐一推向双轨制——这是本课题在 2026-11-05 时点上最重要的横向格局变化。


3. 交叉洞察:两轴结合说明了什么

3.1 四要素停在不同的标准化台阶上

纵轴揭示了一条规律:每个议题都走过"个人习惯 → 公共基础设施(getopt、管道)→ 正式标准(POSIX)→ 框架与指南"四级台阶。把横轴的 2026 年快照对上去,会发现四要素恰好停在不同的台阶上:参数解析站在"框架+标准"双台阶上,收敛基本完成(2024 年 getopt_long 入法是收官动作);输出格式化停在"指南+事实标准"台阶,双轨成形但信封/事件流未定;退出码仍停在"习惯+shell 强约定"台阶,除 shell 保留值外仅 0 被标准定义;可组合性则停在"范式分歧",三条管道路线并存。

台阶高低与"读者是谁"强相关:读者越单一,标准化越彻底——解析器的读者最终是程序自己,所以最快收敛;退出码同时被 shell、人类、agent 三方读取,语义最难统一。这解释了为什么四要素的标准化程度呈阶梯状分布,而不是齐头并进。

3.2 收敛的都是语法,分化的都是语义

把横轴"三条收敛、两条分化"再抽象一层:收敛的三条(POSIX+GNU 语法并集、--json 事实标准、流分流)都是形式层;分化的两条(管道数据模型、退出码语义)都是含义层。形式收敛因为有网络效应——一次学习处处可用,框架也乐于复用同一套心智模型;语义分化因为它绑定具体场景——shell 的 126/127 是 shell 的场景,sysexits 是邮件的场景,15 具名码是 agent 重试的场景。

给设计者的推论:不要指望"退出码大战"会出现一个赢家。正确姿势是遵守共同底线(0/非 0、避开 126/127 及 128 以上的 shell 保留区间——POSIX 只要求"大于 128",bash 按 128+N 映射致命信号,见 §1.4 与 §2.5),再在文档里定义自己的语义——CLIG"不规定数字、映射最重要失败模式"的克制正是因为看到了这一点。

3.3 六十年三次"人机再平衡"

纵轴的三段式与横轴的规范对决互为印证,合起来是三次"人机再平衡":

  1. 第一次(1964–1992):为机器立约。POSIX 用语法准则与退出码把接口交给机器判读,人靠记忆适应机器。
  2. 第二次(1983–2020):为人补偿。GNU 的长选项与 --help、clig.dev 的颜色与人类可读输出,让机器(解析器、TTY 检测)反过来适应人。
  3. 第三次(2024 起):为机器第二次立约。Agent 规范要求非交互、--json、稳定 schema、可重试退出码——但这次用的是"叠加"而非"推翻":machinemode 对比页的结论是默认输出遵循 CLIG、机器模式叠加 agent 规范。

每一次再平衡都留下沉淀:长选项、--help/--version、NO_COLOR、--json。AI 没有推翻任何一层,这正是 clig.dev 双轨设计(TTY 时取悦人、管道时取悦机器)被证明稳健的原因——它天生就是为"两种读者"设计的。

3.4 两场"克制 vs 膨胀"之争的重演

1986 年的 "cat -v considered harmful" 与 2025 年的"JSON vs 自然语言"之辩(HN #48052333、Rethinking CLI interfaces for AI)是同一辩论的两次重演:接口该为调用方塞多少信息。第一次的结论——克制、单一职责——由 clig.dev 继承成文;第二次还没有结论:小数据量下自然语言对 LLM 可能优于 JSON,表格反而干扰模型。

这提示 agent 时代的输出设计不要押注单一格式:横轴 §2.4 的小结——人类双轨(TTY 检测 + --plain)+ 机器单轨(--json)+ 可选 agent 三轨(信封或事件流)的三层结构——是当前风险最小的落点。

3.5 两轴分歧的校准记录

综合过程中发现并消除了两章之间的五处不一致,处置如下:

  1. NO_COLOR 的触发条件:纵轴写"无论值为何",横轴写"存在且非空串"。采用 no-color.org 原文的精确定义:环境变量存在且非空字符串时(无论取值)必须禁色(no-color.org)。本报告全文按此表述。
  2. POSIX Utility Syntax Guidelines 条数:纵轴小节标题作"14 条语法准则",横轴与 POSIX.1-2017 第 12 章原文均为 12 条。采纳 12 条,纵轴标题系笔误。
  3. MCP 与 CLI 的关系:横轴范式表称"替代而非叠加",纵轴称"互补而非替代"。校准为分范围表述:在"机器如何调用工具"这一狭窄通道上,MCP 与 CLI 争夺同一类调用、构成替代竞争;在整体工程版图上互补共存——MCP 管工具发现与类型化调用,CLI 管执行与人类交互,且 xpander 的分析指出 CLI 在 token 效率上仍占优。两种说法各自在限定范围内成立,不存在绝对对错;本报告统一采用限定表述。
  4. Utility Conventions 的年代:横轴总览表记"1988 起(随 POSIX)",纵轴以 IEEE Std 1003.2-1992 为成文节点。本报告统一以 1992 年 POSIX.2-1992 为"法定化节点"表述,1980 年代仅指 POSIX 系列标准开始酝酿的时期。
  5. 12 Factor CLI 的退出码 0/1/2:纵轴把 0/1/2 明确归到 12 Factor CLI Apps 名下(其原文如此),横轴退出码表未收录该体系。两者并不矛盾:12 Factor 是"建议的简化约定",CLIG 是"不规定数字的指南",本报告两处均保留并注明出处。

3.6 对用户的判断与建议

选型矩阵(检索时点 2026-11-05):

你的处境参数解析输出退出码可组合性
写一次性 shell 脚本getoptsstdout/stderr 分流0/1;126/127 等保留码由 shell 决定,脚本不必自定义文本管道
写跨平台通用小工具语言内事实标准(cobra/clap/typer/commander)--json + --plain + NO_COLOR0/1/2 文档化文本管道 + jq
写云原生平台级 CLI(如 kubectl 类)cobra(Go)或 clap(Rust)多格式 -o + jsonpath0/1/2 + 文档化以 JSON 为中心的管道
写给 AI Agent 调用的工具解析库 + 全命令非交互--json 或 agent 规范信封/事件流sysexits 或 15 具名码稳定 schema + --dry-run

Agent 友好设计的共性建议(非交互、结构化输出、--dry-run、可预测退出码)来源:Speakeasy、linkly.ai。

九条检查清单:

  1. 参数解析用成熟解析库,不手写 argv 循环(clig.dev;库顺带解决帮助文本与拼写建议);
  2. 全量提供长选项,命名随大流(--verbose、--all、--dry-run、--json),--help/--version 不可缺席(GNU Coding Standards、CLIG);
  3. 数据进 stdout,日志与错误进 stderr;stderr 默认不加日志级别标签(12 Factor CLI);
  4. 颜色与动画按四条件禁用:非 TTY、NO_COLOR 非空、TERM=dumb、--no-color;不要在被管道时自动切 JSON——机器通道永远是显式 --json(Prisma 输出规范);
  5. 机器输出提供字段级白名单或 --plain,避免输出过肥与破坏按行解析(gh 的做法);
  6. 退出码守住底线:0 成功、非 0 失败、用法错误 2、避开 126/127 及 128 以上的 shell 保留区(bash 的 128+N 约定),语义写进文档(POSIX、12 Factor CLI、CLIG)。何时才在 0/1/2 之上引入更多分类码:仅当工具主要被程序化调用、且调用方确有失败分类需求(如需要区分"可重试/不可重试")时——此时才引入 sysexits 或 agent 规范的具名码并写进文档;人用为主的工具停在 0/1/2 即可。12 Factor 的 0/1/2、CLIG 的"不规定数字"与 sysexits/15 具名码三套建议并不冲突:它们面向的调用方不同(人、通用脚本、机器编排);
  7. 面向 agent 补齐:非交互(不依赖 TTY 提问)、幂等、--dry-run、稳定 schema、可预测退出码(Speakeasy);
  8. 密码与敏感信息不进 flag(会泄漏进 ps),走环境变量或配置(clig.dev);
  9. 不押注单一管道范式:文本管道仍是通用语,结构化输出是增值方言;PowerShell/Nushell 路线按团队生态选,不必整体迁移(§2.6)。

三条风险提示:


4. 参考来源

以下为两章参考来源合并去重后的清单,按主题分组;正文中均已就地引用。

发展史与管道起源

标准与规范

解析库与工具

退出码

输出与机器可读格式

可组合性与 shell 范式

AI Agent 与 CLI

未单独检索验证、出自模型既有知识的断言(承自纵轴章节的原始标注,综合时保留):stderr 与 stdout 分离的精确版本节点;Bourne shell 0=成功 约定的传播;"cat -v considered harmful" 事件年份(1986);PowerShell 1.0 发布年份(2006);《The Art of UNIX Programming》出版年份(2003);getopt_long 入库的确切年份;Claude Code、Codex CLI、Gemini CLI 等编码智能体的具体名录。其余事实均以上列来源为准,版本号与维护状态为 2026-11-05 检索快照。
← 资料库今日播报 →