Rust CLI Tooling AI Skill Guide
Overview & Engine Architecture
Rust CLIs are Cargo binary crates (often in a workspace) that parse args with clap, report errors with anyhow at the binary edge and thiserror in libraries, and exit with meaningful codes. Agents keep I/O fallible, avoid unwrap in non-demo paths, and design subcommands that compose well in scripts (stdout data, stderr diagnostics).
cargo run -p tool
|
clap::Parser
|
subcommands -> library crates
|
ExitCode + stderr messages
When to use this skill
- Building command-line tools in Rust
- Adding subcommands, flags, and env-backed defaults
- Structuring library + bin crates for reuse
- Preparing release builds and cross-compilation basics
Operational directives
- Derive
clap::Parser/Subcommand; document help strings for every flag. - Use
anyhow::Resultinmain; map to librarythiserrortypes underneath. - Write machine-friendly stdout when the tool is meant for pipes; put progress on stderr.
- Prefer
std::fs/std::process::Commandwith explicit error context (.with_context). - Run
cargo fmtandcargo clippy -D warningsbefore calling a change done.
CLI sketch
use anyhow::{Context, Result};
use clap::{Parser, Subcommand};
use std::path::PathBuf;
#[derive(Parser)]
#[command(name = "inventory", version, about = "Inventory helper CLI")]
struct Cli {
#[command(subcommand)]
cmd: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Count lines in a file
Count { path: PathBuf },
}
fn main() -> Result<()> {
let cli = Cli::parse();
match cli.cmd {
Commands::Count { path } => {
let data = std::fs::read_to_string(&path)
.with_context(|| format!("read {}", path.display()))?;
println!("{}", data.lines().count());
}
}
Ok(())
}
Commands
cargo new inventory --bin
cargo add clap --features derive
cargo add anyhow
cargo run -- count ./README.md
cargo build --release
cargo clippy -- -D warnings
Common pitfalls
| Pitfall | Why it hurts | Fix |
|---|---|---|
unwrap in main paths |
Hostile UX on bad input | ? + context |
| Logging on stdout | Breaks pipes | stderr / tracing |
| Giant single crate | Slow compile, weak reuse | workspace libs |
| Ignoring exit codes | Bad CI scripting | ExitCode / Main Result |
Best practices
- Support
--format jsonfor automation when output grows complex. - Add a
tests/CLI smoke test withassert_cmd/predicateswhen stable. - Document required env vars in
--helpand README. - Pin MSRV in
Cargo.tomlif you support older toolchains.
Limitations
- Cross-compiling needs target toolchains and sometimes zig/linker setup.
- Async CLIs (tokio) add complexity - use only when concurrent I/O dominates.
- Signal handling and TTY color detection are OS-sensitive.
Related skills
@python-packaging- shipping CLIs in Python instead@go-services- Go alternative for simple static binaries@docker- distributing CLIs in images when needed