CLI(Command Line Interface,命令行界面)是程序以文本命令为输入、以文本流为输出的交互接口。它既是人操作计算机的传统方式,也是 Agent 操作操作系统与外部服务时通用的一层动作面:模型生成一行命令,Harness 交给 Shell 执行,输出与退出码回到上下文。本教程从 CLI 的定义、组成与运行模型讲起,厘清它与终端、Shell、GUI、API 的边界,说明它为何适合 Agent 使用,并给出面向 Agent 的 CLI 设计与调用方法。

前置教程

如想快速开始学习本教程,你可能需要先完成以下前置教程:

1. 什么是 CLI

1.1 概念定义

CLI(Command Line Interface,命令行界面)是程序对外提供的一种交互接口:调用方以一行文本表达意图,程序解析这行文本中的程序名、子命令、选项与参数,执行后把结果写入标准输出,把诊断信息写入标准错误,并以退出码表示执行结果。

拆解这个定义,CLI 由三个要素构成:

要素 内容 作用
命令文本 程序名、子命令、选项、位置参数 表达调用意图与输入
标准流 标准输入、标准输出、标准错误 传输数据与诊断信息
退出码 一个 0 到 255 的整数 表示执行结果的成败与类别

这三个要素共同构成一份稳定的契约。调用方无需了解程序内部实现,只要按契约传入文本、读取文本、检查退出码,就能完成一次调用。脚本、CI 流水线、Agent 都建立在这份契约之上。

1.2 CLI、终端与 Shell 的边界

日常语境里,人们常把终端、Shell、CLI 混为一谈。三者在系统里处于不同层次:

概念 职责 典型代表
终端(Terminal) 承载字符输入输出的窗口或设备,负责渲染文本、接收键盘事件 Windows Terminal、iTerm2、GNOME Terminal
Shell 命令解释器,负责分词、变量展开、通配符展开、管道与重定向,并创建进程 Bash、Zsh、PowerShell、cmd
CLI 程序对外暴露的命令行接口,定义子命令、选项、输出格式与退出码 git、docker、ffmpeg、kubectl
TUI 在终端内绘制的全屏交互界面,依靠光标控制刷新画面 vim、top、htop
graph LR U[用户或 Agent] --> T[终端
字符输入输出] T --> S[Shell
解析与调度] S --> P[CLI 程序
参数与标准流] P --> K[操作系统
文件/网络/进程] style U fill:#d6eaf8,stroke:#2980b9,stroke-width:2px style T fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style S fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style P fill:#ffecd6,stroke:#b7950b,stroke-width:2px style K fill:#d5f5e3,stroke:#27ae60,stroke-width:2px

三者的替换关系说明了层次差异:终端可以从 Windows Terminal 换成 iTerm2,Shell 可以从 Bash 换成 Zsh,而 git status 的调用方式保持不变。CLI 是程序自身的接口约定,终端与 Shell 只是运行它的环境。

判断一句话属于哪个层次:出现在命令行的第一段文本是程序名,它后面的内容由该程序的 CLI 定义;把命令拆成多个进程并串联起来的语法,属于 Shell;显示这些字符的窗口属于终端。

1.3 CLI、GUI 与 API 的对比

同样是操作一个系统,三种界面形态各有适用边界:

维度 CLI GUI API
输入方式 文本命令与参数 鼠标、触控、键盘快捷键 结构化请求
输出形态 文本流与退出码 像素画面 结构化响应
自动化能力 强,可直接写入脚本 弱,依赖界面自动化 强,需编程接入
组合方式 管道、重定向、脚本 人工操作串联 代码调用与编排
可审计性 命令本身即操作记录 操作轨迹分散 请求日志
学习成本 需要记住命令与参数 界面自解释 需要理解接口文档
典型场景 批量处理、部署、运维 图形编辑、可视化 跨系统集成

CLI 与 API 经常同时存在:程序内部调用 API,外部再包一层 CLI。CLI 的价值在于把一次结构化调用压缩成一行可复制、可记录、可重复执行的文本。

1.4 CLI 的演进与回归

计算早期,终端是主要的交互方式。图形界面普及后,CLI 退到专业场景,成为开发、运维与批量处理的工具。云计算与基础设施即代码兴起后,服务器普遍不提供图形界面,CLI 重新成为操作基础设施的主要入口。

Agent 时代给 CLI 增加了新的调用方。大语言模型以 token 为输入输出单位,CLI 以文本为接口,两者在形态上直接对接。模型无需理解像素坐标,也无需构造复杂的界面事件,生成一行命令即可完成一次真实操作。这是 CLI 在 Agent 体系中地位上升的直接原因。

2. CLI 的组成结构

2.1 一条命令的解剖

一条典型的命令行由若干段组成:

tool subcommand --output json --verbose input.txt
组成 示例 作用
程序名 tool 指定要执行的程序,由 PATH 查找
子命令 subcommand 选择程序内的功能分支
长选项 --output json 以名称指定行为开关或参数值
短选项 -v 长选项的简写形式
位置参数 input.txt 按位置顺序传入的输入对象
选项终止符 -- 其后的内容一律按位置参数处理

程序如何解析这些文本,由它自己的参数解析逻辑决定。命令行没有统一的语法标准,只有广泛遵循的惯例。

2.2 参数解析的常见惯例

惯例 形式 说明
长选项赋值 --output json 或 --output=json 两种写法常被同时支持
短选项赋值 -o json 或 -ojson 短选项通常紧跟取值
短选项合并 -abc 等价于 -a -b -c,仅限无值选项
选项终止 -- 用于传入以连字符开头的文件名
子命令嵌套 tool remote add origin URL 按名词与动词分层组织
帮助入口 -h、--help 输出用法说明
版本入口 -V、--version 输出程序版本

这些惯例来自 POSIX 与 GNU 的长期实践,不同工具之间存在差异。帮助文本是判断某个程序支持哪些写法的最终依据。

2.3 三个标准流

每个进程启动时都会获得三个标准文件描述符:

描述符 名称 默认来源或去向 用途
0 标准输入(stdin) 键盘、管道、文件 接收数据
1 标准输出(stdout) 终端、管道、文件 输出程序结果
2 标准错误(stderr) 终端、日志文件 输出诊断与错误信息

数据走 stdout、诊断走 stderr,是 CLI 的基本分工约定。它让管道只传递有用的数据,错误信息不会污染下游程序的输入:

tool list --json | tool import --stdin

上例中,前一个程序的 JSON 结果通过管道进入后一个程序的标准输入,错误提示仍然显示在终端上。

2.4 退出码

进程结束时返回一个 0 到 255 的整数,称为退出码(Exit Code)。Shell 与调用方依靠它判断执行结果:

退出码 常见含义
0 成功
1 一般性错误
2 命令用法错误
126 找到文件但无法执行
127 命令未找到
128+N 被信号 N 终止

退出码 0 表示程序完成了它认为成功的执行,业务语义仍需结合输出判断。以文本搜索工具为例:没有匹配到内容时返回 1,含义是"未找到",与"执行失败"是两回事。设计良好的 CLI 会把这类业务状态写进文档,并在输出中给出可区分的结构。

2.5 隐式输入:环境与工作目录

除了命令行文本,程序还从环境中读取大量隐式输入:

隐式输入 作用 对调用的影响
PATH 决定到哪些目录查找可执行文件 PATH 缺失时命令无法启动
工作目录(cwd) 相对路径的解析基准 同一命令在不同目录下结果不同
环境变量 配置、凭据、运行模式 决定连接哪个环境、使用哪把密钥
用户与权限 文件访问与操作范围 权限不足时操作被拒绝
区域与编码 排序、日期格式、字符集 影响输出解析
资源限制 文件描述符、内存、超时 影响长任务与并发行为

这些输入不出现在命令行里,却直接影响执行结果。脚本与 Agent 调用命令时,必须显式控制工作目录、环境变量与超时,才能获得可复现的结果。

2.6 一次命令的完整执行链路

graph LR A[命令行文本] --> B[Shell 解析
分词/展开/重定向] B --> C[PATH 查找
定位可执行文件] C --> D[创建子进程
继承环境与工作目录] D --> E[程序执行] E --> F[stdout 数据流] E --> G[stderr 诊断流] E --> H[退出码] F --> I[管道/文件/终端] G --> I H --> J[Shell 与调用方判断结果] style A fill:#d6eaf8,stroke:#2980b9,stroke-width:2px style B fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style C fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style D fill:#fdebd0,stroke:#e67e22,stroke-width:2px style E fill:#ffecd6,stroke:#b7950b,stroke-width:2px style F fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style G fill:#fadbd8,stroke:#c0392b,stroke-width:2px style H fill:#fdebd0,stroke:#e67e22,stroke-width:2px style I fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style J fill:#d6eaf8,stroke:#2980b9,stroke-width:2px

链路中有两个容易被忽略的环节。PATH 查找决定了命令能否启动;子进程继承的环境与工作目录决定了命令在什么上下文中运行。同一行命令在两台机器上结果不同,原因通常落在这两个环节。

3. CLI 的设计惯例

3.1 单一职责与组合

Unix 哲学对 CLI 的影响可以概括为三条:

  • 一个程序只做好一件事,功能边界清晰,行为容易预期;
  • 以文本流作为通用接口,不同程序之间无需约定二进制协议;
  • 通过管道与重定向组合,用简单工具的串联完成复杂任务。
tool export --format json | filter --query "status=active" | tool import --stdin

这条管道由三个独立程序组成,每个程序只关心自己的输入与输出。组合能力来自接口的稳定性,与程序之间是否认识彼此无关。

3.2 子命令树

功能较多的 CLI 通常按"名词加动词"组织子命令:

tool remote add origin URL
tool remote remove origin
tool branch create feature/login
设计原则 说明
名称自解释 子命令名直接表达动作,减少查阅文档的次数
层级稳定 同类操作放在同一层,避免深层嵌套
选项一致 相同含义的选项在各子命令中保持同名同义
帮助分层 主命令、子命令、子命令组各自提供帮助

子命令树的直接收益是降低记忆负担。调用方只需记住主命令,其余信息可以逐层通过帮助文本获取。

3.3 配置优先级

同一项配置常有多个来源,常见约定是按以下顺序覆盖:

优先级 来源 特点
最高 命令行参数 只影响当前这次调用
高 环境变量 影响当前进程及其子进程
中 项目级配置文件 随项目版本管理
低 用户级配置文件 影响当前用户的所有项目
最低 内置默认值 程序自带的保守设置

越靠近单次调用的来源优先级越高,这样既能在全局设置默认行为,也能在单次执行时临时覆盖。

3.4 输出格式

输出模式 适用对象 设计要点
人类可读 终端前的用户 对齐、颜色、分页可以提升可读性
机器可读 脚本、管道、Agent 字段稳定、无装饰、一条记录一行
静默模式 自动化流程 只输出关键结果或完全不输出
详细模式 排查问题 把过程信息写入 stderr

机器可读输出通常通过 --json、--format、--porcelain 一类选项开启。字段名与结构一旦公开,就应当保持稳定;破坏性变更需要版本化,否则下游脚本会集体失效。

3.5 交互与自动化

CLI 面临两类调用方:坐在终端前的人,以及没有交互能力的脚本与 Agent。设计时需要区分:

  • TTY 检测:检测标准输入是否连接到终端,决定是否弹出交互提示;
  • 非交互开关:提供 --yes、--no-input、--non-interactive 一类选项;
  • 默认安全:在非交互环境中,遇到需要确认的操作直接失败并给出提示,避免静默执行;
  • 超时控制:长任务提供超时参数,避免调用方无限等待。

交互提示在人的手里是保护,在 Agent 手里是阻塞。命令在非 TTY 环境下等待输入,会让调用方一直挂起,直到超时。

3.6 安全惯例

惯例 目的
密钥不进入命令行参数 参数会出现在进程列表与 Shell 历史中
优先使用环境变量或凭据库 降低泄漏面
危险操作二次确认 删除、覆盖、发布等动作需要明确意图
提供干跑模式 先展示将要发生的变化,再执行
最小权限运行 只授予完成当前任务所需的权限

4. CLI 为什么适合 Agent

4.1 文本接口与模型的输入输出同构

大语言模型以 token 序列为输入,以 token 序列为输出。CLI 的输入是文本命令,输出是文本流,两者在同一种介质上衔接。模型不需要视觉模型解析截图,也不需要专用 SDK 构造请求,生成一行命令就能表达一次操作。

4.2 组合性让单步能力变成流程

管道、重定向、子命令与脚本把大量单一职责的小工具组合成流程。Agent 可以把多个命令串成一次任务,也可以把常用组合固化成脚本,减少每一步的决策成本。

4.3 自描述带来的可发现性

CLI 自带三层自描述信息:

信息 获取方式 内容
用法说明 --help 子命令、选项、参数与示例
执行反馈 stdout 与 stderr 结果与诊断
结果状态 退出码 成功、失败、未找到等类别

调用方遇到不熟悉的命令时,可以先读帮助、再小范围执行、最后根据反馈修正。这种"查、试、改"的循环与 Agent 的多轮执行天然契合。

4.4 可审计与可复现

一行命令完整记录了操作意图与参数。把它写入日志、脚本或文档,其他人可以原样复现。图形界面的操作轨迹难以完整记录,API 调用需要额外的日志设施,CLI 的命令行本身就是一份可读的操作记录。

4.5 进程边界带来的隔离能力

每次 CLI 调用都是一个独立进程,拥有自己的参数、环境、工作目录与权限。操作系统与沙箱可以在进程边界上施加限制:限制可访问的目录、禁止网络、限定运行时长。Agent 的高危操作因此可以被约束在可控范围内。

4.6 CLI 的局限

局限 影响 缓解方式
交互式提示 无 TTY 时阻塞或失败 提供非交互模式
全屏 TUI 输出是光标控制序列,难以解析 改用非交互子命令或 API
输出冗长 占用上下文窗口 过滤、分页、结构化输出
隐式环境依赖 结果难以复现 显式指定工作目录、环境与超时
破坏性操作 误执行代价高 干跑、确认、权限与沙箱

5. Agent 如何使用 CLI

5.1 发现:PATH 决定可执行,上下文决定可知

PATH 与上下文作用于两个不同层面:

层面 决定因素 缺失后的表现
进程层 PATH 与可执行权限 Shell 报"命令未找到",进程无法启动
模型层 上下文中的工具清单、约定文件、历史与帮助 模型不知道这条命令存在,不会主动生成

两者彼此独立。PATH 配置完整,模型仍可能完全不调用;上下文反复提到一条命令,PATH 没配好时调用必然失败。排查"Agent 为什么不用某个命令"时,先确认缺的是哪一层。

PATH 让命令跑得起来,上下文让模型想得到。前者是操作系统的能力,后者是提示工程的对象。

5.2 训练先验与上下文注入

模型能写出命令行,来自两段训练:

  • 预训练:代码仓库、终端会话、README 与技术文档中的命令共现关系进入权重,形成对常见命令与参数的统计直觉;
  • 后训练:带工具调用的任务轨迹强化"在合适时机执行命令"的倾向。

这两段训练覆盖的都是公开语料中的常见工具。自定义命令、内部脚本、新版本参数不在训练分布内,模型对它们的全部认知只能来自上下文:

注入通道 位置 主要作用
工具与技能清单 系统提示中的工具定义与技能描述 让模型知道命令存在与用途
项目约定文件 会话启动时加载的说明文件 规定何时用、用哪个模板
会话内轨迹 对话历史中的调用记录 提供可模仿的成功与失败样例
运行时探测 命令自身的帮助与报错 补齐参数、纠正错误

5.3 选择:描述与任务匹配

模型在多个可用命令之间做选择时,主要依据描述文本与当前任务的匹配度。影响选择的因素包括命令名的可读性、描述中是否包含用户常用的说法、工具之间职责是否重叠。职责重叠越严重,误选率越高。

5.4 执行:参数与运行上下文

Agent 执行 CLI 时,需要准备的不只是命令文本:

执行要素 内容 常见错误
参数数组 程序名、子命令、选项、位置参数 引号与空格处理错误
标准输入 需要从 stdin 读取的数据 忘记关闭 stdin,进程挂起
工作目录 相对路径的基准目录 在错误目录执行,读写错位置
环境变量 配置、凭据、运行模式 连接了错误的环境
超时 单次执行的最长等待时间 长任务拖死整个会话
权限 运行用户与可访问范围 权限过大或不足

5.5 观察:解析输出与状态

一次调用的结果由三部分组成,缺一不可:

  • stdout:业务数据,优先选择 JSON 等结构化格式;
  • stderr:诊断信息,用于理解失败原因;
  • 退出码:结果类别,决定是否需要重试或上报。

只读取 stdout 而忽略退出码,会把失败当成成功;只检查退出码而不读 stderr,会在失败后缺少修正依据。

5.6 纠错:报错回读与多轮收敛

命令执行失败时,Harness 把 stderr 与退出码写回上下文,模型据此调整参数或换用其他命令。纠错效率取决于错误信息的可读性:包含问题、原因与下一步建议的报错,通常能在一到两轮内收敛;只返回 invalid input 的报错,会让模型在同一个错误上反复尝试。

5.7 一次完整调用

sequenceDiagram participant U as 用户 participant H as Harness participant M as LLM participant S as Shell participant C as CLI 程序 U->>H: 提交任务 H->>M: 上下文(工具清单/约定/历史) M-->>H: 生成命令与参数 H->>H: 权限校验与参数检查 H->>S: 执行命令(cwd/env/timeout) S->>C: 创建进程 C-->>S: stdout/stderr/退出码 S-->>H: 结果 H->>M: 结果写回上下文 alt 退出码非 0 M-->>H: 修正命令后重试 else 退出码为 0 M-->>U: 汇总结果 end

6. 面向 Agent 的 CLI 设计

6.1 非交互优先

命令应当默认支持无人工介入的执行。交互提示只在检测到 TTY 时出现,非交互环境直接失败并给出明确提示。批量操作提供 --yes 一类选项,让调用方显式表达确认意图。

6.2 机器可读输出

设计项 要求
结构化格式 提供 JSON 或行分隔的记录格式
字段稳定 字段名与类型跨版本保持兼容
数据与诊断分离 结果走 stdout,日志与进度走 stderr
无装饰输出 机器模式下关闭颜色、表格边框与动画
分页可控 支持关闭分页,避免等待键盘输入

6.3 语义化退出码

退出码应当区分不同的结果类别,而不仅表达"成功"与"失败":

类别 建议
成功 0
业务未命中 独立退出码,与错误区分
输入错误 独立退出码,提示修正参数
权限或认证失败 独立退出码,提示检查凭据
外部依赖失败 独立退出码,提示稍后重试

6.4 错误信息三段式

一条面向调用方的错误信息包含三部分:

错误:目标文件不存在
原因:路径 build/output.bin 未生成
下一步:先执行 build --target output,再重试当前命令

问题、原因、下一步各自独立成行,便于模型快速定位并生成修正命令。

6.5 帮助文本分层

  • 主命令帮助列出子命令与全局选项;
  • 子命令帮助列出该命令的选项、参数与示例;
  • 每个帮助页给出一个最小可用示例;
  • 复杂参数说明默认值与可选值。

6.6 幂等与干跑

  • 幂等:同一命令重复执行不产生额外副作用,重试安全;
  • 干跑:只展示将要执行的动作,不真正修改系统;
  • 分段执行:把高风险操作拆成准备、确认、执行三个阶段。

6.7 最小权限与密钥处理

CLI 运行在进程边界上,权限与密钥的处理直接影响安全:

做法 风险 改进
密钥写在参数里 进程列表、Shell 历史可读 改用环境变量或凭据库
使用管理员权限执行 影响范围过大 按任务授予最小权限
在共享目录存放配置 凭据泄漏 限制文件权限
日志打印完整命令 参数中的敏感信息落盘 对敏感参数脱敏

6.8 可靠性分级

等级 手段 漏调风险 适用场景
L1 仅依靠模型训练先验 极高 广泛使用的公共命令
L2 工具与技能描述 中 日常开发工具
L3 描述、约定文件、示例与结果校验 低 团队内部流程
L4 Harness 层强制触发 无,确定性执行 合规、发布、审计

模型输出是概率采样的结果,上下文注入只能提高命中率。要求每次都必须执行的动作,应当交给 Hook、Workflow 或包装脚本在 Harness 层完成。

7. CLI 与相关概念

7.1 与 Shell

Shell 是 CLI 的调用者与编排者。它负责把一行文本拆成程序名与参数,处理管道与重定向,创建进程并等待结果。CLI 程序只关心自己收到的参数与标准流。Shell 还提供内建命令,如 cd、export,它们不创建独立进程。

7.2 与 GUI

GUI 面向交互式探索,CLI 面向批量与自动化。图形界面把可用操作呈现在屏幕上,降低发现成本;CLI 把操作压缩成文本,降低重复执行与编排成本。两者长期共存,同一产品常同时提供图形客户端与命令行工具。

7.3 与 API、SDK

维度 CLI API 与 SDK
边界 进程边界 网络边界或库边界
接入方式 执行命令 编写代码或发送请求
组合方式 管道与脚本 代码编排
适合场景 运维、批处理、Agent 操作 系统集成、应用开发

CLI 经常作为 API 的封装层存在:命令行负责参数解析与输出格式化,内部调用 API 完成实际业务。

7.4 与 Tool Calling、MCP

Tool Calling 规定模型如何表达一次调用,MCP 规定工具如何被标准化接入。CLI 是工具的一种实现形态:它可以被直接执行,也可以被包装成 MCP 工具。三者的分工是模型侧表达、协议侧连接、进程侧执行。

7.5 与 Harness、Sandbox

Harness 负责组装上下文、执行命令、回写结果,是模型与 CLI 之间的调度层。Sandbox 在进程边界上施加限制,控制 CLI 能访问的文件、网络与系统调用。CLI 的隔离能力来自进程模型,沙箱把这种能力变成可配置的策略。

7.6 与 Workflow、Hook

Workflow 把多个 CLI 调用编排成固定步骤,Hook 在调用前后执行确定性校验。三者组合后的典型结构是:Workflow 定义步骤顺序,CLI 执行具体动作,Hook 在关键节点拦截或补充。

7.7 概念定位

graph LR User[用户或 Agent] --> Harness[Harness
上下文与执行] Harness --> Shell[Shell
解析与调度] Shell --> CLI[CLI
命令接口] CLI --> OS[操作系统
文件/网络/进程] ToolCalling[Tool Calling
模型侧调用表达] --> Harness MCP[MCP
工具接入协议] --> CLI Sandbox[Sandbox
进程隔离] --> CLI Workflow[Workflow
步骤编排] --> Harness Hook[Hook
确定性校验] --> Harness style User fill:#d6eaf8,stroke:#2980b9,stroke-width:2px style Harness fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style Shell fill:#e8f4f8,stroke:#1a6b8a,stroke-width:2px style CLI fill:#ffecd6,stroke:#b7950b,stroke-width:2px style OS fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style ToolCalling fill:#fdebd0,stroke:#e67e22,stroke-width:2px style MCP fill:#fadbd8,stroke:#c0392b,stroke-width:2px style Sandbox fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style Workflow fill:#fdebd0,stroke:#e67e22,stroke-width:2px style Hook fill:#fadbd8,stroke:#c0392b,stroke-width:2px

8. 常见误区

误区 实际情况 改进方向
CLI 就是终端 终端负责显示,CLI 是程序的接口约定 区分终端、Shell 与程序接口
CLI 只适合程序员 批量处理、部署、运维都依赖 CLI 从任务场景判断是否需要
输出给人看就够了 脚本与 Agent 需要稳定结构 提供 JSON 等机器可读格式
退出码 0 就是业务成功 0 只表示程序完成了执行 为业务状态定义独立退出码
交互确认更安全 非交互环境下会造成阻塞 干跑、显式确认参数与权限控制
命令越多能力越强 选择空间变大,误选率上升 按任务域分组,按需暴露
参数写全就安全 密钥出现在参数中会泄漏 改用环境变量或凭据库
MCP 会取代 CLI 两者处于不同层,长期共存 用 MCP 连接,用 CLI 执行

9. 总结

9.1 核心内容回顾

  • CLI 是程序以文本命令为输入、以标准流为输出、以退出码表示结果的交互接口。
  • 终端负责显示,Shell 负责解析与调度,CLI 是程序自身的接口约定,三者处于不同层次。
  • 一条命令由程序名、子命令、选项与位置参数组成,运行结果由 stdout、stderr 与退出码共同表达。
  • PATH、工作目录、环境变量与权限是 CLI 的隐式输入,直接决定执行结果。
  • CLI 的文本接口、组合能力、自描述信息、可审计性与进程隔离,使它成为 Agent 通用的动作面。
  • Agent 使用 CLI 分为发现、选择、执行、观察、纠错五个环节;PATH 决定可执行,上下文决定可知。
  • 面向 Agent 的 CLI 应具备非交互模式、机器可读输出、语义化退出码、可读报错、幂等与干跑能力。

9.2 常见问题与解答

问:CLI 和 Shell 是同一样东西吗?

答:两者处于不同层次。Shell 是命令解释器,负责解析命令行、处理管道与创建进程;CLI 是程序对外提供的命令行接口。git 是 CLI 程序,Bash 是运行它的 Shell。

问:Agent 为什么更倾向使用 CLI?

答:CLI 的输入输出都是文本,与模型的 token 序列直接对接;命令可以被完整记录、复制与重放;每次调用都是独立进程,便于施加权限与沙箱限制。图形界面依赖像素与坐标,自动化的稳定性与可审计性都更弱。

问:交互式命令为什么会让 Agent 卡住?

答:Agent 执行命令时通常没有 TTY,程序如果等待键盘输入,就会一直阻塞到超时。面向自动化的命令应在非 TTY 环境下直接失败,或提供 --yes、--no-input 一类选项。

问:命令已经装好,模型为什么不调用?

答:安装只解决进程层能否执行,模型层还需要上下文告知这条命令存在。把命令写进工具清单、项目约定文件或会话示例中,模型才有稳定生成它的依据。

问:为什么建议 CLI 提供 --json 输出?

答:人类可读的表格与颜色对解析不友好,字段位置或措辞一旦变化,下游脚本就会失效。JSON 输出提供稳定字段名与结构,便于脚本与 Agent 可靠提取结果。

问:退出码应该设计得多细?

答:至少区分成功、输入错误、权限失败与外部依赖失败。业务上的"未命中"也应有独立退出码,避免与真正的执行错误混淆。

问:MCP 普及后还需要 CLI 吗?

答:需要。MCP 解决工具如何被标准化连接,CLI 解决操作如何在进程内执行。大量现有工具只提供 CLI,MCP 服务器也常在内部调用 CLI 完成实际工作。