RustCLI
Mattakushi4322026-10-26查看 1674复制 109
何时激活:Rust CLI 工具、clap、命令行参数、子命令、配置文件、环境变量、终端输出
📘如何使用这个技能
- 1复制技能内容·点击上方「Copy SKILL.md」复制全部内容,或 Download 下载到本地
- 2打开你的 AI 客户端·支持 Claude Code、Trae、Cursor、ChatGPT、DeepSeek、Kimi 等任意 AI 助手
- 3粘贴为系统提示/知识文件·Claude Code:放入 .claude/skills/ 目录;普通对话:作为首条消息发送并说「请严格按这份技能文档执行」
- 4直接提出你的需求·AI 会按技能定义的工作流、格式和约束来处理,无需再解释背景
💡 提示:技能生效后,每次对话只需一句需求,AI 会按 SKILL.md 的流程执行。
SKILL.md4373 chars
---
name: rust-cli
description: "When to activate: Rust CLI tools, clap, command-line arguments, subcommands, config files, environment variables, terminal output"
origin: zakr
metadata:
namespace: zakr/devtools-pack
version: 1.0.0
category: engineering
language: rust
platforms: [claude-code, codex, gemini-cli, cursor, aider, windsurf]
---
# Rust CLI Patterns
## clap with Derive API
```toml
[dependencies]
clap = { version = "4", features = ["derive", "env"] }
```
```rust
use clap::{Parser, Subcommand, Args};
#[derive(Parser, Debug)]
#[command(name = "mytool", version, about = "A powerful CLI tool")]
struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
#[arg(short, long, env = "MYTOOL_CONFIG", default_value = "~/.config/mytool.toml")]
config: std::path::PathBuf,
}
#[derive(Subcommand, Debug)]
enum Commands {
/// Process files
Process(ProcessArgs),
/// Show status
Status {
#[arg(short, long)]
detailed: bool,
},
}
#[derive(Args, Debug)]
struct ProcessArgs {
#[arg(required = true)]
files: Vec<std::path::PathBuf>,
#[arg(short, long, default_value = ".")]
output: std::path::PathBuf,
#[arg(short = 'j', long, default_value_t = 4)]
jobs: usize,
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::Process(args) => process(args),
Commands::Status { detailed } => status(detailed),
}
}
```
## Progress Output with indicatif
```toml
[dependencies]
indicatif = "0.17"
```
```rust
use indicatif::{ProgressBar, ProgressStyle};
fn process_with_progress(items: Vec<String>) {
let pb = ProgressBar::new(items.len() as u64);
pb.set_style(
ProgressStyle::with_template(
"{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} {msg}"
)
.unwrap()
.progress_chars("=>-"),
);
for item in &items {
pb.set_message(format!("processing {item}"));
do_work(item);
pb.inc(1);
}
pb.finish_with_message("done");
}
```
## Colored Terminal Output
```toml
[dependencies]
colored = "2"
```
```rust
use colored::Colorize;
fn print_status(ok: bool, message: &str) {
if ok {
println!("{} {}", "✓".green().bold(), message);
} else {
eprintln!("{} {}", "✗".red().bold(), message);
}
}
```
## Config File Handling
```toml
[dependencies]
config = "0.14"
serde = { version = "1", features = ["derive"] }
```
```rust
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Settings {
database_url: String,
port: u16,
workers: usize,
}
fn load_settings() -> anyhow::Result<Settings> {
let settings = config::Config::builder()
.set_default("port", 8080)?
.set_default("workers", 4)?
.add_source(config::File::with_name("config").required(false))
.add_source(config::Environment::with_prefix("APP").separator("__"))
.build()?;
Ok(settings.try_deserialize::<Settings>()?)
}
```
## Interactive Prompts
```toml
[dependencies]
dialoguer = "0.11"
```
```rust
use dialoguer::{Confirm, Input, Select};
fn interactive_setup() -> anyhow::Result<()> {
let name: String = Input::new()
.with_prompt("Project name")
.default("my-project".into())
.interact_text()?;
let framework = Select::new()
.with_prompt("Select framework")
.items(&["axum", "actix-web", "warp"])
.default(0)
.interact()?;
let confirmed = Confirm::new()
.with_prompt(format!("Create project '{name}'?"))
.default(true)
.interact()?;
if confirmed { create_project(name, framework)?; }
Ok(())
}
```
## Exit Codes and Error Reporting
```rust
fn main() {
if let Err(e) = run() {
eprintln!("error: {e:#}");
std::process::exit(1);
}
}
```
## Common Anti-Patterns
- **Parsing args manually** — use `clap`; it handles edge cases and generates help
- **Writing errors to stdout** — errors go to `stderr`; use `eprintln!` or a logger
- **Hard-coding config values** — support env vars and config files from the start
- **No progress feedback for long ops** — users need to know the tool is working
- **Panicking on invalid input** — validate early with `clap` validators or early returns