# Agent Friendly CLI

> 新建、改造或评审命令行工具（CLI）及其配套 Skill 时使用，尤其是供 AI Agent 稳定调用、同时也要给人正常使用的 CLI。覆盖命令面设计、非交互模式、JSON 输出契约、退出码分层、dry-run、幂等、鉴权安全、CLI/脚本/Skill/Agent 职责分层、事务式编排、风险授权、终态验证和验收方法。

- Skill: `x0c/agent-friendly-cli` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add x0c/agent-friendly-cli`
- Raw SKILL.md: https://api.skillmd.com/api/skills/x0c/agent-friendly-cli/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: x0c (https://skillmd.com/u/x0c)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/x0c/agent-friendly-cli

---


# 面向 Agent 的 CLI 工具开发

## 定位

这个 skill 管**跨语言的 CLI 契约设计与验收**：命令怎么分、输出怎么给、退出码怎么排、非交互怎么处理、怎么避坑、怎么验收。语言层面的实现细节（如 Go 的 cobra/flag、Python 的 argparse）交给对应语言级 skill，本 skill 不重复。

核心目标一句话：让 CLI 对 Agent **低 token、低歧义、低风险，且可审计、可复现、可回滚**；对人**默认可读、可交互**。这是同一个 CLI 的两个受众，不是两套工具。

## 什么时候读哪个 reference

- 设计命令面 / 输出契约 / 退出码，或评审一个 CLI 是否 agent-friendly → 读 [references/design-principles.md](references/design-principles.md)（P0/P1/P2 分层 + 人机双受众规范）。评审时逐条核对，缺失项就是要报告的问题。
- 动手实现，想避开真实事故 → 读 [references/pitfalls.md](references/pitfalls.md)（dry-run 真只读、幂等信号、密钥安全、测试隔离等踩坑教训）。
- 写完要验收 → 读 [references/verification.md](references/verification.md)（逐项粘证据的验收清单 + Agent 实测评测方法论）。

## 工作流

### 设计阶段

先过 **P0 七条硬性要求**——没有这些 Agent 根本用不了，细节见 design-principles.md：

| P0 | 一句话 |
|---|---|
| 非交互模式 | 检测到非 TTY 自动关交互（用 `isatty()`，stdin/stdout 分开测），不要求调用方主动传 flag |
| 结构化输出 | `--json` 统一 envelope `{ok, data, error, meta}`；失败也走 stdout JSON + 非零退出码 |
| 退出码分层 | 0 成功 / 1 一般失败 / 2 用法错误 / 3 不存在 / 4 权限鉴权 / 5 冲突 / 6 超时 |
| dry-run | 有副作用的命令能预演，输出结构与真实执行一致，且真只读、不花钱 |
| 验证命令 | 提供 `status`/`verify`/`doctor`，让调用方在退出码之外再查一遍 |
| 输入校验 | 硬拦路径逃逸、命令注入 |
| 自助安装 | 配套 Skill 找不到 CLI 时提供可信下载地址并自动安装到用户目录，再校验版本与能力 |

过完 P0 再按需要加 P1（`describe` 自描述、结构化错误带 `hint`/`next_commands`、体积控制、写前日志、自动生成 SKILL.md、可组合性）。默认采用**声明式命令**（`ensure`/`apply`）而非命令式（`create`/`delete`），天然幂等安全。

**人机双受众**贯穿始终：默认输出人类可读（表格、颜色可用），`--json` 或非 TTY 时全部剥离只留机器契约；交互向导必须有非交互等价路径（`--yes` + 全量 flag）；同一信息给双字段（程序用英文枚举 `status`，人看本地化 `status_tag`）。

### CLI 可获得性与自助安装

配套 Skill 的第一步必须探测 CLI 的绝对路径和 `version`/`capabilities`。找不到可用二进制时，不要只回复「CLI 未安装」或把安装工作推回用户；用户请求使用该能力，即授权 Agent 完成**无提权、仅用户目录**的本地安装并继续原任务，除非用户明确要求不安装。

- **提供机器可执行来源**：在 Skill、CLI 生成的 Skill 模板或 `describe` 输出中写明可信的官方仓库地址或每个平台产物下载地址；不能只给产品主页、让 Agent 搜索下载链接，或依赖不稳定的包管理器名称。
- **提供确定性安装路径**：交付非交互安装脚本或等价命令，按 OS/CPU 选择预编译产物，安装到用户可写目录，不使用 `sudo`，不修改系统目录或 shell 配置。产物已存在且不同版本时默认报冲突，只有显式 `--force`/`--replace` 才覆盖。
- **锁定并验证**：安装后记录绝对二进制路径、下载来源和不可变版本/提交；立刻运行 `version --json`、`capabilities --json` 或 `doctor --json` 验证，然后全程只使用该绝对路径。可提供校验和或签名时必须校验。
- **明确失败边界**：下载源不可达、当前平台无产物、校验失败或缺少必要的 `git`/下载工具时，再报告具体阻塞项；不得用搜索结果中的随机 URL、底层 API 或临时 `curl` 旁路 CLI。没有可信下载源和可执行安装路径的 CLI，不算完整的 Agent 可用交付物。
- **后台自更新（与安装同源时）**：若 CLI 以「官方仓库预编译产物目录」为可信来源长期分发（例如 monorepo 将各平台二进制提交进 `dist/`），安装后还应具备**静默后台自更新**：对齐同一可信源、不污染 `--json` stdout、可环境变量禁用、更新在独立进程完成以免短命令掐死。具体注入与节流约定以交付仓库的 AGENTS 共性规范为准（mc-cli 见根 `AGENTS.md`「共性规范：后台自动自更新与 skill 同步」）。
- **配套 skill 反向同步（有配套 skill 时）**：CLI 安装链解决了「机器缺 CLI 时引导 Agent 安装」，但反向链路同样要管：skill 更新后已安装机器的 Agent 不会自知。约定：CLI 后台静默执行 skill 更新命令（如 `npx skills update <名> -g -y`），不自建各 agent 目录的同步逻辑；**资格判据用 skill 管理工具自己的全局锁文件**（能证明这台机器由它分发才参与）；权威机的本地源在位时豁免，防止未推送的本地更新被仓库旧内容反向覆盖；多 CLI 并发更新同一份锁须互斥；独立节流状态与禁用开关。mc-cli 的完整落地见根 `AGENTS.md`「skill 反向同步」。

### 登录凭证的「索取一次」约定

CLI 一旦把账号密码持久化到本地（0600）并支持会话过期自动重登，配套引导必须让 Agent 形成「向用户索取**一次**，之后永不再问」的行为；能力已具备但引导少一句「仅需一次」，每个新会话都会退化成反复向用户要密码（真实事故：yapi-cli 引导只写「密码用环境变量提供」，另一个 Agent 直接把设环境变量的事推给用户）。

- CLI 侧：登录命令支持环境变量传密码（非 TTY 不卡交互）；凭证/Profile 同时保存账号密码；会话过期自动重登并刷新落盘。
- 报错侧：NEED_LOGIN 类错误的 hint 必须写明「向用户索取一次账号密码 → 环境变量运行 login → 保存后自动重登」，next_commands 给可照抄的带环境变量命令；只写「请重新登录」等于没写。
- Skill 侧：登录步骤写明「密码经环境变量提供、保存到本地后自动重登，索取一次即可；不要让用户自己设环境变量或反复索要」。
- 升级兼容：旧版落盘凭证不含密码时同样报 NEED_LOGIN，hint 里点明重新登录一次即可升级为新格式；凭证文件路径与字段名是对外契约，任何格式变更必须带旧格式的读写兼容测试（compat_test）。

### 实现阶段

对照 pitfalls.md 逐条避坑，重点：dry-run 分支拦住**所有**副作用；写命令做到第二遍收敛为 `ok`；密钥只从环境变量读、绝不进日志/输出/Git，且凭证绑定登录时的服务地址；上游业务成败判据与 HTTP 状态码解耦，写成功以回查终态为准；会话失效才重登一次、结果不确定的写请求不自动重放；测试全程重定向到临时目录、不碰真实用户资源。

### CLI 配套 Skill 的分层与事务骨架

配套 Skill 不是 CLI 命令清单，而是把用户的自然语言目标编译为一套可审计、可授权、可恢复、可验证的事务流程。设计前先写清业务终态不变量，例如“发布目标全部成功且版本一致”或“平台状态与代码严格一致”；不能把“某条命令退出码为 0”直接定义为完成。

| 层 | 应负责 | 不应负责 |
|---|---|---|
| CLI | 鉴权、目标身份校验、版本解析、业务硬门禁、计划/差集、幂等、执行、状态查询、结构化错误 | 依赖 Agent 记住关键安全规则 |
| 辅助脚本 | 跨工具适配、旧 CLI 兼容、格式转换和临时确定性组合 | 长期承载分页、快照一致性、删除顺序等高风险领域规则 |
| Skill | 意图路由、上下文取值、流程编排、风险授权、异常分支和结果表达 | 自己重写 CLI 已能确定性完成的计算或调用底层 API 绕过 CLI |
| Agent | 处理真正的语义歧义和用户决定 | 解析不稳定文案、手算差集、猜测目标或默认值 |

默认采用以下事务骨架；按任务风险删减步骤，但不要颠倒安全顺序：

```text
能力探测/登录检查 → 证据化识别目标 → 生成不可变计划
→ dry-run（离线只读）→ preflight（远程只读）→ 必要授权
→ apply → status/reconcile → verify 终态
```

- **最少提问**：能从工作区、Git remote、现有配置、登录态或平台只读接口确定的信息直接取得；仅在目标确有歧义、缺少必要业务信息、将创建新资源或执行高风险写操作时提问。
- **按风险授权**：只读探测和已明确授权的低风险动作可自动执行；生产、删除、覆盖、迁移等高风险动作只在计划和预检完成后确认一次。用户取消或改为自行处理时立即停止等待、查询、重试和再次提交。
- **以收敛定义完成**：区分 `planned`、`submitted`、`waiting_approval`、`running`、`succeeded`、`failed`、`unknown` 等状态；写入成功后必须再用 `status`、`verify` 或 `reconcile` 证明终态满足不变量。
- **安全重试**：只重试明确失败且可重试的目标；成功、审批中、运行中和未知状态不得重复提交。批量操作要保持同一计划和幂等键，第二次执行应收敛为 `unchanged` 或返回已有操作。
- **禁止旁路补洞**：CLI 能力不足时优先补 CLI 或停止并报告，不能临时改用 `curl`、直接读凭据、调用底层 API 或手工复制业务规则绕过其鉴权、审计和安全门禁。
- **先复用再扩面**：一次 Agent 失误不自动等于 CLI 缺命令。先判断能否用现有参数、结构化字段或 `--out` 闭环；若问题只是 Skill 路由或结果判读，修 Skill。已有规则仍被忽略时，先把前置条件移到关键动作之前并删除后文重复，不要叠加同义提醒。只有稳定重复且现有契约无法确定性完成的流程才新增命令或参数，并确保减少的复杂度大于新增复杂度。
- **识别下沉信号**：稳定、重复、机械、跨 Skill 复用或涉及高风险一致性的逻辑应成为 CLI 一等命令。若 Skill/脚本开始长期处理分页、差集、宽匹配、快照生命周期、删除顺序或复杂状态机，通常说明 CLI 缺少 `plan/apply/verify`、`sync`、`batch` 等复合能力；脚本可作为过渡层，但不应成为第二套业务内核。
- **批量查询也要下沉**：当 Agent 为同一目标集合重复执行相同发现、诊断或过滤命令时，CLI 应提供一次调用的 `batch`/`--all-matches`/聚合命令，内部做有界并发，并按目标返回结果、总体摘要和 partial/failures。不要把 N×M 次串行工具调用当作 Skill 编排能力。
- **不越权定义证据顺序**：工具配套 Skill 只约束该工具的安全边界、调用方式和结果判读；除非用户或业务契约明确要求，不要替用户固定数据库、基础设施、APM、审计日志等跨系统数据源的查询先后。
- **控制用户输出**：CLI 对 Agent 返回结构化细节；Skill 对用户只报告业务结论、目标/版本、真实状态和下一步，不倾倒命令、内部 ID、JSON 或无关中间过程。

### CLI 配套 Skill 与高风险写操作

当 CLI 会修改配置、发布、迁移、删除或触发外部执行时，配套 Skill 只能负责路由和编排，**不能代替 CLI 的安全边界**。模型可能读到旧文档、调用旧二进制或跳过一条文字规则；错误操作必须由 CLI 本身拒绝。

1. **先锁定二进制，再允许任何写入**：Skill 的第一步验证当前实际入口及所需能力；能力不足时构建或安装确定版本，并把绝对二进制路径保存为本次会话唯一入口。后续命令不得混用裸命令名和不同副本。
2. **已有映射默认不可覆盖**：创建命令若命中同名但内容不同的配置，必须返回冲突；只有显式 `--replace`/`--force` 才能覆盖。覆盖前由 CLI 校验目标资源的稳定身份（如仓库地址、资源 ID、版本或指纹），不能让 Agent 用默认值或占位值“先写再查”。
3. **把目标身份写进不可变计划**：高风险命令先生成计划，计划至少记录目标、环境、来源版本/提交、关键配置指纹和创建时刻。提交命令只接受该计划；发现目标或版本漂移时拒绝执行。不要让预检结果只存在于 Agent 的自然语言上下文。
4. **阶段必须互斥且可判别**：离线 `--dry-run`、远程只读 `--preflight`、真实 `--apply`/`--yes` 分成独立路径和输出状态。dry-run 不得声称远程校验已完成；preflight 不得产生业务写入；提交前必须明确显示将使用的不可变计划。
5. **版本是对象，不是文案**：用户指定分支、标签、构建号或提交时，CLI 应只读解析为实际不可变版本，再让所有同批目标复用它。不得因为“当前分支碰巧指向同一提交”就静默改用另一种版本标识。
6. **把安全前置条件做成机器可读能力探测**：提供 `version`/`capabilities`/`doctor --json`，输出当前二进制版本、可用特性、配置状态和不会泄露密钥的诊断。Skill 依据这个输出选择路径，不靠解析 help 文案或猜测 PATH；找不到可用二进制时按本节的可信来源自动安装后再探测。
7. **Skill 的写入准则**：只有在用户已授权相应高风险动作，且 CLI 已验证目标身份后，Skill 才能新增或替换本地映射。无法自动确认时保持配置原样，报告缺少的业务信息；不得通过匿名查询失败或默认配置推导出写入动作。
8. **改类/删除写操作优先用「读后写」替代 `--yes`**：对已有资源的修改和删除，比起「确认即放行」的 `--yes`，更推荐强制**先读后写**——写命令要求带 `--version`（一个读命令输出的资源指纹），CLI 写前重新读取目标、重算指纹、比对：缺失→拒绝并提示先读（`confirmation_required`/退出码 usage）；不一致→拒绝并要求重读（`conflict`/退出码 conflict）；一致才放行。价值有三：① 逼 Agent 写前先读，挡住上下文遗忘、鲁莽操作、**操作错对象**（app/id 指错，指纹自然对不上）；② 旧值留在会话历史里可核对、可回滚；③ 附带乐观锁效果（读到写之间被改过即拦）。落地要点：指纹基准优选**写操作实际提交的那份字段**（如编辑页表单），做到「读的就是写基准」零漂移，排除防伪 token / 标识字段 / 易变运行态字段后取 sha256 前若干位；服务端无版本字段时纯客户端计算即可。**新建（create）例外**：无旧值可读，改走查重校验。**语义定位**：主叙述是「约束 Agent 自身」，乐观锁只是附带收益——错误文案要讲清「为什么不让你写」并在 `next_commands` 给出可照抄的读命令（带真实参数）；写成功后在返回里回显**最新 version 令牌**与更新后对象，连续写直接复用上一步返回的令牌，不必中间再读。参考实现 `mbp-cli`/`tsp-cli` 的 `version.go` + 命令层 writeguard。**指纹算法一旦发布即是对外契约**：换算法会使历史 version 令牌全部失效（Agent 会话里的旧令牌全部被拒），只在与旧算法对照测试证明值不变时才可迁移；确实需要换时在错误 hint 里引导重新读一次而非硬拒。

### 验收阶段

按 verification.md 清单逐项**粘实际命令和真实输出**作证据，不接受「已确认」自陈。契约合规（清单）和 Agent 顺畅可用（真实 Agent 多步任务实测 + 看 transcript）都要做；实测必须用**独立上下文的无头 Agent**（用所用工具的无头/单次执行模式另起），不得由开发会话自己兼任——开发会话已知全部设计细节，测不出提示与错误是否自解释。**新建或修改（含回归）CLI/配套 Skill 都要做这种独立上下文实测**，不只是首次验收。高风险 CLI 还必须覆盖：旧二进制缺能力、同名映射覆盖、默认/占位映射、版本标识与提交不一致、阶段参数混用、计划漂移和凭据缺失等反向场景。

## 契约演进纪律

JSON envelope、退出码、已发布字段名是对外契约，发布后**只加不改不删**；破坏性变更升接口版本号并显著标注。

