关于 domain-cli
domain-cli 是面向 Rust 命令行工具设计的技能,涵盖输出规范、配置优先级、错误处理和中断响应,并介绍常用 crate 与设计模式。
主要功能
- 01使用 clap 派生解析参数
- 02分层配置优先级
- 03数据写入 stdout、错误写入 stderr
- 04错误时返回非零退出码
- 05处理 Ctrl+C 信号
- 06提供终端提示与进度显示
适用场景
- 01设计类型安全的命令层级
- 02支持命令行、环境变量和文件配置覆盖
- 03让命令输出可供脚本管道处理
- 04为长时间操作显示进度
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ actionbook/ rust-skills --skill domain-cli安装后在 Claude Code 中输入/domain-cli确认已加载。
详细介绍
CLI 领域
第 3 层:领域约束
领域约束 → 设计影响
| 领域规则 | 设计约束 | Rust 影响 |
|---|---|---|
| 用户体验 | 清晰的帮助信息和错误提示 | clap 派生宏 |
| 配置优先级 | CLI > 环境变量 > 文件 | 分层加载配置 |
| 退出码 | 出错时返回非零值 | 正确处理 Result |
| 标准输出/标准错误 | 数据与错误分流 | 使用 eprintln! 输出错误 |
| 可中断 | 处理 Ctrl+C | 信号处理 |
关键约束
用户沟通
RULE: Errors to stderr, data to stdout
WHY: Pipeable output, scriptability
RUST: eprintln! for errors, println! for data
配置优先级
RULE: CLI args > env vars > config file > defaults
WHY: User expectation, override capability
RUST: Layered config with clap + figment/config
退出码
RULE: Return non-zero on any error
WHY: Script integration, automation
RUST: main() -> Result<(), Error> or explicit exit()
向下追溯 ↓
从约束追溯到设计(第 2 层):
"Need argument parsing"
↓ m05-type-driven: Derive structs for args
↓ clap: #[derive(Parser)]
"Need config layering"
↓ m09-domain: Config as domain object
↓ figment/config: Layer sources
"Need progress display"
↓ m12-lifecycle: Progress bar as RAII
↓ indicatif: ProgressBar
关键 Crate
| 用途 | Crate |
|---|---|
| 参数解析 | clap |
| 交互式提示 | dialoguer |
| 进度条 | indicatif |
| 彩色输出 | colored |
| 终端 UI | ratatui |
| 终端控制 | crossterm |
| 控制台工具 | console |
设计模式
| 模式 | 用途 | 实现方式 |
|---|---|---|
| Args 结构体 | 类型安全的参数 | #[derive(Parser)] |
| 子命令 | 命令层级结构 | #[derive(Subcommand)] |
| 配置层 | 覆盖优先级 | CLI > 环境变量 > 文件 |
| 进度 | 向用户反馈 | ProgressBar::new(len) |
代码模式:CLI 结构
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "myapp", about = "My CLI tool")]
struct Cli {
/// Enable verbose output
#[arg(short, long)]
verbose: bool,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Initialize a new project
Init { name: String },
/// Run the application
Run {
#[arg(short, long)]
port: Option<u16>,
},
}
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Commands::Init { name } => init_project(&name)?,
Commands::Run { port } => run_server(port.unwrap_or(8080))?,
}
Ok(())
}
常见错误
| 错误 | 违反的领域约束 | 修复方法 |
|---|---|---|
| 将错误输出到标准输出 | 破坏管道 | eprintln! |
| 缺少帮助文本 | 用户体验差 | #[arg(help = "...")] |
| 出错时 panic | 退出码不正确 | Result + 正确处理 |
| 长时间操作没有进度提示 | 用户不确定 | indicatif |
追溯到第 1 层
| 约束 | 第 2 层模式 | 第 1 层实现 |
|---|---|---|
| 类型安全的参数 | 派生宏 | clap Parser |
| 错误处理 | Result 传播 | anyhow + 退出码 |
| 用户反馈 | 进度 RAII | indicatif ProgressBar |
| 配置优先级 | Builder 模式 | 分层来源 |
相关技能
| 场景 | 参阅 |
|---|---|
| 错误处理 | m06-error-handling |
| 类型驱动参数 | m05-type-driven |
| 进度生命周期 | m12-lifecycle |
| 异步 CLI | m07-concurrency |
评论
支持 Markdown