Rust CLI Scaffold
Create a Rust CLI the way an experienced Rust engineer would start one: argument parsing with clap, ergonomic error handling, a testable core separated from main, and CI ready to go.
Step 1 — Confirm the basics
Ask (or infer) the binary name, a one-line description, and the first subcommand or core operation. Keep the scaffold focused on one real command rather than empty boilerplate.
Step 2 — Create the project
cargo new <name> --bin
cd <name>
cargo add clap --features derive
cargo add anyhow
Add thiserror instead of / alongside anyhow if the tool is library-like and needs typed errors. Use anyhow for the binary's top level.
Step 3 — Lay out testable structure
Separate the CLI shell from the logic so the logic can be unit-tested without spawning a process:
src/
├── main.rs # parse args, call run(), map errors to exit codes
├── cli.rs # clap Parser/Subcommand definitions
└── lib logic... # pure functions that do the actual work
main.rs stays thin:
use anyhow::Result;
use clap::Parser;
mod cli;
fn main() -> Result<()> {
let args = cli::Cli::parse();
cli::run(args)
}
cli.rs holds the #[derive(Parser)] struct, the Subcommand enum, and a run() that dispatches to pure functions. Those pure functions are what your tests target.
Step 4 — Apply conventions
- Use
#[derive(Parser)]with#[command(version, about)]so--help/--versionwork for free. - Return
Result<T>and use?; neverunwrap()/expect()on recoverable errors in shipped paths. - Add
#[derive(Debug)]to public types. - Read config from flags first, env second, defaults last.
- Map errors to meaningful process exit codes in
mainif the tool is meant to be scripted.
Step 5 — Tests and CI
- Add
#[cfg(test)]unit tests for the pure logic functions (the easy wins). - Add one integration test under
tests/usingassert_cmd+predicatesto exercise the built binary end-to-end. Runcargo add --dev assert_cmd predicates. - Generate a
cargo fmt --check+cargo clippy -D warnings+cargo testGitHub Actions workflow (hand off to theci-pipelineskill if available).
Step 6 — Verify
Run cargo build and cargo test and confirm both pass. Show the user the tree, the --help output shape, and the next command to implement. Hand off to tdd-loop to build the real behavior test-first.
Source: HM-IT-CODE/forge-skills — distributed by TomeVault.