← Back to Site

Building CLI Tools with Rust


Why Rust?


The Essentials

// Cargo.toml
[dependencies]
clap = { version = "4", features = ["derive"] }
anyhow = "1"
thiserror = "1"

Argument Parsing with Clap

use clap::Parser;

#[derive(Parser)]
#[command(name = "mytool")]
struct Cli {
    /// Input file
    #[arg(short, long)]
    input: PathBuf,

    /// Verbose output
    #[arg(short, long)]
    verbose: bool,
}

Error Handling

use thiserror::Error;

#[derive(Error, Debug)]
enum AppError {
    #[error("File not found: {0}")]
    NotFound(PathBuf),

    #[error("Parse error: {0}")]
    Parse(String),
}

The ? Operator

fn process(path: &Path) -> Result<Data> {
    let content = fs::read_to_string(path)?;
    let parsed = parse(&content)?;
    let result = transform(parsed)?;
    Ok(result)
}

Clean, readable error propagation.


Testing CLIs

#[test]
fn test_cli_args() {
    let cli = Cli::try_parse_from([
        "mytool",
        "--input", "test.txt",
        "--verbose"
    ]).unwrap();

    assert!(cli.verbose);
}

Cross-Compilation

# Add targets
rustup target add x86_64-apple-darwin
rustup target add x86_64-pc-windows-gnu

# Build
cargo build --release --target x86_64-apple-darwin

Distribution


Demo: Building Vibe Site

Live coding a static site generator CLI.


Resources


Questions?

GitHub: @example Twitter: @example