mcpField
B
better-cli

better-cli

github.com/yogin16开发1247 次安装34 周前更新
代码仓库

关于 better-cli

用于设计和审查面向终端用户及 AI Agent 的命令式 CLI 技能,强调可预测的结构化输出、可操作的错误信息和可组合命令,不涵盖全屏终端应用。

主要功能

  1. 01将数据输出与诊断信息分开
  2. 02统一提供结构化 JSON 输出
  3. 03提供可操作的成功与错误信息
  4. 04支持非交互式自动化
  5. 05根据 TTY 和管道调整输出

适用场景

  1. 01设计新的命令式 CLI
  2. 02改造现有 CLI 以便 Agent 使用
  3. 03审查命令的易用性和可组合性
  4. 04添加便于自动化的输出与错误处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yogin16/better-cli --skill better-cli

安装后在 Claude Code 中输入/better-cli确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
AGENTS.md
LICENSE
PUBLISHING.md
package.json
claw.json
.claude-plugin/
plugin.json
marketplace.json
.clinerules/
better-cli.md
.cursor/rules/
better-cli.mdc
.github/
copilot-instructions.md
.windsurf/rules/
better-cli.md
references/
composability.md
discoverability.md
agent-patterns.md
error-handling.md
interactivity.md
security.md
output-design.md
testing.md

详细介绍

更好的 CLI:为人类和 AI Agent 构建 CLI

构建命令行工具,让人类在终端中使用时乐在其中,同时让 AI Agent 在自动化流水线中可靠运行。这两个目标相辅相成,并不冲突。

本指南面向基于命令的 CLI(例如 git、docker、gh、kubectl)——这类工具包含子命令、标志和结构化输出。本指南不涉及全屏 TUI 应用或交互式仪表板。

适用场景

  • 使用任意语言构建新的 CLI 工具
  • 改进或重构现有 CLI,使其更方便人类和 Agent 使用
  • 为现有 CLI 添加命令、标志或输出格式
  • 检查 CLI 代码的易用性、可组合性或对 Agent 的就绪程度

不适用于:TUI/全屏终端应用、GUI 应用、REST/GraphQL API 设计、Shell 脚本

核心理念

人类体验(DX)注重易于发现和容错。Agent 体验(DX)注重可预测性和纵深防御。优秀的 CLI 兼顾两者。

黄金法则:输出应告诉你下一步该做什么。 每条命令的输出——无论成功还是失败——都应提供足够的上下文,让用户(人类或 AI Agent)知道下一步该做什么。读取 CLI 输出的 Agent 应能继续其工作流,而无需猜测。

flowchart LR
  H[Human at Terminal] --> TTY{stdout is TTY?}
  A[AI Agent] --> TTY
  TTY -->|Yes| RICH[Rich: colors, tables,\nprogress bars, prompts]
  TTY -->|No| CLEAN[Clean: JSON, no ANSI,\nno prompts, parseable]
  RICH --> CORE[Same data, same exit codes,\nsame semantics]
  CLEAN --> CORE

规则(按优先级排序)

P0:关键——每个 CLI 都必须做到
1. 数据输出到 stdout,其他内容输出到 stderr
stdout  ->  primary output (results, JSON, file contents) — for piping
stderr  ->  errors, warnings, progress, diagnostics, prompts — for humans

这是最重要的一条规则。它支持管道、重定向和 Agent 解析。切勿混用。

2. 成功时退出码为 0,失败时为非零

使用语义化退出码,以便脚本和 Agent 根据失败类型进行分支处理:

代码含义使用场景
0成功操作已完成
1一般失败通用错误
2用法错误参数错误、未知标志
3未找到资源文件、用户或服务不存在
4权限被拒绝身份验证失败、权限不足
5冲突资源已存在
75临时失败网络超时——重试可能有帮助
78配置错误配置缺失或无效

请记录退出码。区分 transient(75 与其他代码)至关重要——Agent 会据此决定是否重试。

3. 支持 --json 输出结构化内容

每条会产生输出的命令都必须支持 --json(或 --output json)。使用统一的封装格式:

{
  "status": "ok",
  "data": { "id": "abc-123", "name": "my-resource" },
  "warnings": []
}

所有命令使用相同的结构。Agent 只需解析一次,即可在任何地方使用。应将其视为有版本管理的 API 契约——添加可选字段是安全的;移除或重命名字段则属于破坏性变更。

4. 输出必须指引下一步操作

这是让 CLI 适用于 AI Agent 的关键。每条命令的输出都应易于理解且便于操作——读者无需猜测就能知道下一步该做什么。

成功时——确认已完成的操作并建议后续步骤:

Created deployment 'web-app' (ID: deploy-xyz)

Next steps:
  View logs:      mycli logs deploy-xyz
  Check status:   mycli status deploy-xyz

失败时——说明出了什么问题以及如何修复:

Error: Cannot deploy — 2 failing health checks.

Fix: mycli health check web-app --verbose
     mycli deploy --env staging --force   (skip health checks)

结果不完整时——指出缺少什么以及如何获取更多内容:

Showing 20 of 142 results. Next page: mycli list --cursor eyJpZCI6IDIwfQ==

这种模式能让 Agent 自主运行——它读取输出,看到建议的命令,然后执行该命令。缺少这种模式时,Agent 会停滞不前或臆测下一步操作。

5. 支持 --help 和 --version

--help 必须包含:描述、用法格式、带类型和默认值的标志列表,以及 2–3 个符合实际的示例。示例是阅读最多的部分——请将它们放在前面。

EXAMPLES
  $ mycli deploy --env staging          Deploy to staging
  $ mycli deploy --env prod --dry-run   Preview production deployment
  $ mycli deploy --env prod --yes       Deploy without confirmation
6. 绝不要求交互式输入

每个交互式提示都必须有对应的标志。如果 stdin 不是 TTY,绝不显示提示——应给出清晰的错误信息或使用默认值。

提示类型对应标志
确认--yes / --force
选择--type=value
文本输入--name=value
密码--password-file=path 或通过 stdin 管道传入

Agent 无法在提示中输入“y”。如果 CLI 挂起并等待输入,Agent 的工作流就会中断。

P1:高优先级——优秀与卓越的区别
7. 检测 TTY 并进行适配

当 stdout 是 TTY 时:使用颜色、表格、进度条和交互式提示。 当 stdout 不是 TTY 时:输出纯文本,不使用 ANSI 代码、加载动画或提示。

遵循以下环境信号:

信号含义
NO_COLOR(任意非空值)禁用 ANSI 颜色
TERM=dumb最简终端——不使用格式化
CI=true正在 CI 中运行——不启用交互功能
MYCLI_NO_INPUT=1应用专属的非交互模式覆盖设置
8. 错误必须提供可执行的解决方案

每个错误都需要包含以下四个部分:

  1. 问题——发生的错误
  2. 上下文——涉及哪个资源、执行了什么操作、输入是什么
  3. 修复方法——用于解决问题的确切命令或操作
  4. 参考资料——文档 URL 或 mycli help <topic>

不好的示例:Error: EACCES 好的示例:Error: Cannot write to /etc/config — permission denied. Try: sudo mycli config set key=value

启用 --json 时,错误必须采用结构化格式:

{
  "status": "error",
  "error": {
    "code": "AUTH_EXPIRED",
    "message": "API token has expired",
    "fix": "Run: mycli auth login --refresh",
    "transient": false
  }
}

code 字段可供机器读取(Agent 会根据它进行分支处理)。transient 字段告知 Agent 是否应该重试。

9. 配置优先级

始终遵循:标志 > 环境变量 > 项目配置 > 用户配置 > 默认值

层级示例用途
标志--port 8080一次性覆盖
环境变量MYCLI_PORT=8080CI/CD、容器
项目配置仓库根目录中的 .mycli.yaml团队共享设置
用户配置~/.config/mycli/config.yaml个人默认值
默认值硬编码开箱即用的合理设置

绝不要通过标志接收密钥——它们会泄露到 ps 输出和 shell 历史记录中。请使用环境变量、配置文件或 --password-file。

10. 为管道和组合式使用而设计
  • 支持 --fields name,status,id,以限制输出列(提升 Agent 的令牌使用效率)
  • 支持从标准输入读取:cat ids.txt | mycli get --stdin
  • 对流式或分页数据使用 NDJSON(每行一个 JSON 对象)
  • 创建资源时,输出其标识符,以便后续命令串联使用
# This pipeline must work
mycli create --json | jq -r '.data.id' | xargs mycli deploy --id
11. 绝不破坏现有契约

改进现有 CLI 时,应将其当前行为视为契约。用户和脚本都依赖这些行为。

破坏性更改(没有主版本升级时绝不可进行):

  • 移除或重命名标志、子命令或环境变量
  • 更改现有故障场景的退出代码
  • 移除或重命名 --json 输出中的字段
  • 更改现有命令的默认行为
  • 更改位置参数的顺序或含义

安全的增量更改(始终可以进行):

  • 添加默认值能保持旧行为的新标志
  • 在 JSON 输出中添加新的可选字段
  • 添加新的子命令
  • 在原先不支持的地方添加 --json 支持
  • 为原先返回 1 的场景添加新的退出代码
  • 添加 --fields、--quiet、--dry-run 等新标志

如有疑问,只添加,不修改。移除旧行为前,先通过 stderr 中的警告将其弃用。

12. 优先使用标志,而非位置参数

标志可自我说明、顺序无关且面向未来。

不好的示例:mycli deploy production v2.1.0 好的示例:mycli deploy --env production --version v2.1.0

一个位置参数是可以接受的(“主要对象”——文件路径、资源名称)。两个就值得警惕。三个则是错误做法。

P2:中等——打磨细节,建立信任
13. 长时间操作时在 stderr 中显示进度

对于 TTY:显示加载动画、进度条和预计剩余时间。 对于管道:完全不显示,或向 stderr 输出结构化进度信息。 绝不要将进度指示发送到 stdout——这会破坏数据流。

14. 为会修改数据的命令支持 --dry-run

准确显示将发生的更改,但不实际执行。使用 --json 时,以结构化格式输出计划中的更改。这是 AI Agent 必不可少的安全保障——它们可以在执行前进行验证。

15. 使操作具备幂等性

mycli config set key=value 必须支持安全地运行两次。创建命令应支持 --if-not-exists。Agent 会在遇到暂时性故障时重试——设计时应考虑这一点。

16. 提供 Shell 补全

通过 mycli completions <shell> 支持 bash、zsh 和 fish。大多数框架会自动生成补全(Cobra、Click、oclif、clap)。

17. 统一命令语法

选择一种模式,并在所有命令中保持一致:

  • 名词-动词:mycli pod list、mycli pod delete(kubectl 风格)
  • 动词-名词:mycli list pods、mycli delete pod(docker 风格)

统一使用常见动词:list、get/show、create、update、delete。

Agent 就绪度决策树

评审或构建 CLI 时,按以下步骤进行:

flowchart TD
  START[New CLI command] --> OUT{Produces output?}
  OUT -->|Yes| JSON[Add --json with consistent envelope]
  OUT -->|No| EXIT[Ensure meaningful exit code]
  JSON --> MUT{Mutates state?}
  EXIT --> MUT
  MUT -->|Yes| DRY[Add --dry-run]
  MUT -->|No| PIPE{Usable in pipes?}
  DRY --> CONFIRM{Needs confirmation?}
  CONFIRM -->|Yes| FORCE[Add --yes/--force bypass]
  CONFIRM -->|No| IDEM[Make idempotent if possible]
  FORCE --> IDEM
  IDEM --> PIPE
  PIPE --> FIELDS[Add --fields for column selection]
  FIELDS --> ERR[Structured errors with code + fix + transient]
  ERR --> DONE[Agent-ready]

反模式

将数据和诊断信息混在 stdout 中

新手:“把所有内容都打印到 stdout,用户会看到。” 专家:如果警告也输出到 stdout,mycli list | jq . 就会出错。数据输出到 stdout,其他所有内容输出到 stderr。没有例外。 时间线:自 1977 年以来就是 Unix 惯例。至今仍是新 CLI 中最常见的错误。

在管道输出中使用颜色和 ANSI 转义码

新手:“始终显示颜色,带来更好的 UX。” 专家:LLM 会将 ANSI 转义序列(\x1b[38;2;...m)作为文本进行分词,浪费上下文窗口并破坏解析。输出任何 ANSI 代码前,先检查 isatty(stdout) 和 NO_COLOR。 检测:将输出通过管道传给 cat -v——如果看到 ^[[ 序列,就说明存在问题。

交互式提示没有跳过方式

新手:“为了安全,始终确认破坏性操作。” 专家:Agent 无法输入“y”。每个提示都必须提供 --yes/--force 跳过方式。如果 stdin 不是 TTY,且未提供跳过标志,则应显示明确错误并退出——绝不要挂起。 检测:在 CI 中运行命令,或将 stdin 通过管道连接到 /dev/null 时,命令会挂起。

成功时不打印任何内容

新手:“Unix 的传统是静默表示成功。” 专家:对人类来说,静默会让人觉得出了问题——应显示简短确认信息(“已创建资源 abc123”)。对 Agent 来说,静默含义不明——应以退出码 0 退出,并支持 --json 返回结果。脚本明确要求静默时,使用 -q/--quiet。

只为人类或机器设计,而非兼顾两者

新手:“我们的用户都是开发者,他们会解析文本。”或“始终只输出 JSON。” 专家:检测上下文(TTY 与管道),并自动调整。终端中默认输出便于人类阅读的内容;通过管道输出或传入 --json 时,则输出机器可读内容。同一条命令即可服务两类用户。

输出没有说明接下来该做什么

新手:“只打印结果,然后退出。” 专家:每条输出都应指引下一步。成功时,建议合理的下一条命令;失败时,建议修复命令;结果不完整时,说明如何获取更多信息。Agent 依赖这些提示自主继续操作——没有它们,Agent 就会停滞、盲目重试或臆造命令。 检测:成功运行一条命令后,问自己:“输出是否告诉我接下来该做什么?”如果没有,就添加“后续步骤”部分。

以“改进”为名破坏现有 CLI 契约

新手:“这个标志名不好,我来改一下。”或“我来调整 JSON 输出结构,让它更简洁。” 专家:现有用户和脚本依赖当前契约——标志名、退出码、输出结构和默认行为。添加新功能时应保留旧功能。移除功能前,先弃用并通过 stderr 发出警告。重命名标志或移除 JSON 字段,可能会破坏数千个下游脚本和 Agent 工作流。 检测:任何 PR 若在未提升主版本号的情况下,移除、重命名或更改现有标志、退出码或输出字段的类型,都应引起警惕。

默认输出冗长,浪费 Agent 上下文

新手:“信息越多越好。” 专家:一次 vitest 运行会生成 419KB 的输出。Agent 只需要 5 个数字。应支持 --fields 选择列、--quiet 输出最少内容,以及 --json 输出结构化数据。stdout 中每个不必要的字节都会消耗 Agent 的 token。

Agent 就绪度检查清单

快速审查任意 CLI:

[ ] Every command supports --json with consistent envelope
[ ] stdout has ONLY data; stderr has everything else
[ ] Exit codes are semantic (not just 0/1)
[ ] Every prompt has a --yes / --force / --flag bypass
[ ] Errors include: code, message, fix suggestion, transient flag
[ ] --dry-run available for all mutating commands
[ ] Progress/spinners go to stderr, never stdout
[ ] NO_COLOR and TTY detection implemented
[ ] --fields flag limits output to requested columns
[ ] Create commands output the created resource identifier
[ ] Mutating commands are idempotent or have --if-not-exists
[ ] --help includes examples, not just flag descriptions
[ ] Secrets never accepted via flags (use env vars or files)
[ ] Piped output contains zero ANSI escape codes
[ ] Success output includes "next steps" with exact follow-up commands
[ ] Error output includes the exact command to fix or diagnose the issue
[ ] No debug traces or stack traces in default output (use --debug)
[ ] Existing flags, exit codes, and output fields are never removed or renamed (additive only)

参考资料

如需深入了解,请查阅以下资料——默认情况下不会加载:

文件查阅时机
references/output-design.md设计 JSON 信封、NDJSON 流式传输、字段选择、输出版本管理和令牌高效格式
references/agent-patterns.md了解 AI Agent 如何使用 CLI、MCP 封装、架构自省和动态工具发现
references/error-handling.md查看完整的退出代码表(sysexits.h)、结构化错误格式规范和错误分类设计
references/interactivity.md查看 TTY 检测代码示例(Node/Python/Go/Rust)、NO_COLOR 实现、进度条模式和提示词设计
references/composability.md查看适合管道的模式、stdin 约定、跨命令链接和 NDJSON 流式传输
references/discoverability.md查看帮助文本结构、Shell 补全生成、man 手册,以及用于 Agent 自省的 --help-json
references/security.md查看机密信息处理、Agent 上下文的输入验证(路径遍历、注入)和权限范围控制
references/testing.md查看输出契约测试、CLI 集成测试模式、快照测试和 CI 中的架构验证

评论

支持 Markdown