Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
bobmatnyc avatar

Clap

  • 221 installs
  • 63 repo stars
  • Updated July 18, 2026
  • bobmatnyc/claude-mpm-skills

Scaffold Rust CLI binaries with clap derive or developer APIs for flags, subcommands, env overrides, and help text in tools, agents, and internal dev utilities.

About

Teaches Rust CLI development with the clap crate: defining commands and subcommands, typed arguments, env and config precedence, validation hooks, autogenerated help, and testing patterns for robust terminal tools and agent-side utilities.

  • Rust clap crate patterns
  • Derive and builder APIs
  • Subcommands and flags
  • Validation and help generation
  • CLI UX for Rust tools

Clap by the numbers

  • 221 all-time installs (skills.sh)
  • Ranked #53 of 121 Rust skills by installs in the Skillselion catalog
  • Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill clap

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs221
repo stars63
Last updatedJuly 18, 2026
Repositorybobmatnyc/claude-mpm-skills

What it does

Scaffold Rust CLI binaries with clap derive or developer APIs for flags, subcommands, env overrides, and help text in tools, agents, and internal dev utilities.

Files

SKILL.mdMarkdownGitHub ↗

Clap (Rust) - Production CLI Patterns

Overview

Clap provides declarative command-line parsing with strong help output, validation, and subcommand support. Use it to build CLIs with predictable UX and testable execution paths.

Quick Start

Minimal CLI

Correct: derive Parser

use clap::Parser;

#[derive(Parser, Debug)]
#[command(name = "mytool", version, about = "Example CLI")]
struct Args {
    /// Enable verbose output
    #[arg(long)]
    verbose: bool,

    /// Input file path
    #[arg(value_name = "FILE")]
    input: String,
}

fn main() {
    let args = Args::parse();
    if args.verbose {
        eprintln!("verbose enabled");
    }
    println!("input={}", args.input);
}

Wrong: parse multiple times

fn main() {
    let _a = Args::parse();
    let _b = Args::parse(); // duplicate parsing and inconsistent behavior
}

Subcommands (real tools)

Model multi-mode CLIs with subcommands and shared global flags.

Correct: global flags + subcommands

use clap::{Parser, Subcommand, ValueEnum};

#[derive(Parser, Debug)]
struct Args {
    #[arg(long, global = true)]
    verbose: bool,

    #[arg(long, global = true, env = "MYTOOL_CONFIG")]
    config: Option<String>,

    #[command(subcommand)]
    cmd: Command,
}

#[derive(Subcommand, Debug)]
enum Command {
    Serve { #[arg(long, default_value_t = 3000)] port: u16 },
    Migrate { #[arg(long, value_enum, default_value_t = Mode::Up)] mode: Mode },
}

#[derive(Copy, Clone, Debug, ValueEnum)]
enum Mode { Up, Down }

fn main() {
    let args = Args::parse();
    match args.cmd {
        Command::Serve { port } => println!("serve on {}", port),
        Command::Migrate { mode } => println!("migrate: {:?}", mode),
    }
}

Config layering (CLI + env + config file)

Prefer explicit precedence:

1. CLI flags 2. Environment variables 3. Config file 4. Defaults

Correct: merge config with CLI overrides

use clap::Parser;
use serde::Deserialize;

#[derive(Parser, Debug)]
struct Args {
    #[arg(long, env = "APP_PORT")]
    port: Option<u16>,
}

#[derive(Deserialize)]
struct FileConfig {
    port: Option<u16>,
}

fn effective_port(args: &Args, file: &FileConfig) -> u16 {
    args.port.or(file.port).unwrap_or(3000)
}

Exit codes and error handling

Map failures to stable exit codes. Return Result from command handlers and centralize printing.

Correct: command returns Result

use std::process::ExitCode;

fn main() -> ExitCode {
    match run() {
        Ok(()) => ExitCode::SUCCESS,
        Err(e) => {
            eprintln!("{e}");
            ExitCode::from(1)
        }
    }
}

fn run() -> Result<(), String> {
    Ok(())
}

Testing (assert_cmd)

Test the binary surface (arguments, output, exit codes) without coupling to internals.

Correct: integration test

use assert_cmd::Command;

#[test]
fn shows_help() {
    Command::cargo_bin("mytool")
        .unwrap()
        .arg("--help")
        .assert()
        .success();
}

Shell completions (optional)

Generate completions for Bash/Zsh/Fish.

Correct: emit completions

use clap::{CommandFactory, Parser};
use clap_complete::{generate, shells::Zsh};
use std::io;

fn print_zsh_completions() {
    let mut cmd = super::Args::command();
    generate(Zsh, &mut cmd, "mytool", &mut io::stdout());
}

Anti-Patterns

  • Parse arguments in library code; parse once in main and pass a typed config down.
  • Hide failures behind unwrap; return stable exit codes and structured errors.
  • Overload one command with flags; use subcommands for distinct modes.

Resources

  • Clap: https://docs.rs/clap
  • assert_cmd: https://docs.rs/assert_cmd
  • clap_complete: https://docs.rs/clap_complete

Related skills

Rustbackenddevopsintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.