| |

Rust 48 🦀 Command-Line Interface Parsing (clap crate)

Every command-line tool has an interface. The user types the program name, the options, the positional arguments, and the subcommands, and the program must parse the input, validate it, and produce a helpful error message when something is wrong. Hand-writing this parsing is tedious and error-prone. The argument order, the short and long forms, the default values, the required fields, and the help text are all the details that the developer must get right. The clap crate is the standard library for building command-line interfaces in Rust. It generates the parser from the declarative definition, validates the input, and produces the polished help messages automatically.

The crate has two APIs: the builder API and the derive API. The builder API constructs the parser programmatically with the method calls, and it is the flexible and the explicit. The derive API defines the parser with the struct and the attributes, and it is the concise and the type-safe. The derive API is the recommended approach for most applications, because the struct documents the interface, and the compiler enforces the types. The builder API is the fallback for the dynamic interfaces and the cases the derive cannot express.

The derive API maps the struct fields to the command-line arguments. A field with the String type and the #[arg(short, long)] attribute becomes the option --name with the short form -n. A field with the bool type becomes the flag. A field without the short or the long becomes the positional argument. The Option<T> makes the argument optional, and the Vec<T> makes it repeatable. The #[command] attribute configures the program-level metadata, and the #[arg] attribute configures the individual arguments.

This chapter covers three areas. First, why clap exists — the parsing problem and the derive-versus-builder trade-off. Second, how to use the derive API — the Parser, the Args, the Subcommand, the #[arg], the #[command], the options, the flags, and the positional arguments. Third, the patterns and the advanced features — the subcommands, the validation, the ValueEnum, the custom parsers, the environment variables, and the configuration files. The chapter ends with a complete example session, a quick reference, best practices, common pitfalls, real-world examples, and diagrams showing the parsing flow.

Key point: The clap crate is the standard command-line parsing library for Rust. The derive API defines the parser with the struct and the attributes, and the builder API constructs it with the method calls. The #[derive(Parser)] generates the parser, the #[arg] configures the arguments, and the #[command] configures the program. The Option<T> makes the argument optional, the Vec<T> makes it repeatable, and the ValueEnum restricts the values to the enum.


Why clap exists

The parsing problem. The command-line arguments are the strings, and the program must decide which string is the option, which is the value, and which is the positional. The --name Alice is the option with the value, the --verbose is the flag, and the input.txt is the positional. The parsing must handle the --name=Alice form, the -n Alice form, the combined -vvv form, and the -- separator. The hand-written parsing is the many edge cases, and the clap handles them.

The help problem. The --help flag should print the usage, the options, the arguments, and the descriptions. The help text must be the accurate and the formatted. The hand-written help is the maintenance burden, and the clap generates it from the definition. The help is the documentation, and the documentation is the automatic.

The validation problem. The argument must be the valid. The port must be the number, the file must exist, the enum must be the known value. The clap validates the input at the parse time, and the error message is the clear. The value_parser attribute specifies the parser, and the ValueEnum restricts the values to the enum.

The derive-versus-builder problem. The derive API is the concise and the type-safe. The struct is the single source of the definition, and the compiler checks the types. The builder API is the flexible and the dynamic. The runtime constructs the parser, and the definition is the code. The derive is the recommended for the static interfaces, and the builder is for the dynamic.

The subcommand problem. The tools with the multiple actions (the git add, the git commit, the cargo build) use the subcommands. The clap supports the subcommands with the enum, and the derive generates the parser for each variant. The match on the enum handles the dispatch, and the compiler ensures the exhaustive.

The trade-off. The clap adds the dependency and the compile time. The derive macro generates the code, and the binary grows. The alternative is the hand-written parsing, which is the smaller but the error-prone. The trade-off is between the convenience of the generated parser and the size of the dependency, and the modern Rust tools choose the clap.


a. The derive API

The derive API defines the parser with the struct and the #[derive(Parser)] attribute.

use clap::Parser;

/// A simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// Name of the person to greet
    #[arg(short, long)]
    name: String,

    /// Number of times to greet
    #[arg(short, long, default_value_t = 1)]
    count: u8,
}

fn main() {
    let args = Args::parse();

    for _ in 0..args.count {
        println!("Hello, {}!", args.name);
    }
}

The #[derive(Parser)] generates the parse method, and the Args::parse() reads the std::env::args and returns the struct. The #[command] attribute configures the program metadata: the author from the Cargo.toml, the version from the Cargo.toml, and the about from the doc comment. The #[arg] configures the individual fields.

The doc comment. The doc comment on the struct is the about, and the doc comment on the field is the help for the argument.

/// A simple program to greet a person
#[derive(Parser)]
struct Args {
    /// Name of the person to greet
    #[arg(short, long)]
    name: String,
}

The --help output uses the doc comments:

A simple program to greet a person

Usage: my_tool [OPTIONS] --name <NAME>

Options:
  -n, --name <NAME>    Name of the person to greet
  -h, --help           Print help
  -V, --version        Print version

The parse and the try_parse. The parse exits the process on the error, and the try_parse returns the Result:

fn main() {
    let args = Args::parse();
    // ...
}

fn main() {
    let args = match Args::try_parse() {
        Ok(args) => args,
        Err(e) => {
            e.print().unwrap();
            std::process::exit(1);
        }
    };
}

The parse is the convenience, and the try_parse is the testable.


b. The arguments

The positional arguments. The field without the short or the long is the positional.

#[derive(Parser)]
struct Args {
    /// The input file
    input: String,

    /// The optional output file
    output: Option<String>,
}

The input is the required positional, and the output is the optional. The usage is my_tool <INPUT> [OUTPUT].

The options. The field with the #[arg(short, long)] is the option.

#[derive(Parser)]
struct Args {
    /// The configuration file
    #[arg(short, long)]
    config: Option<String>,

    /// The port number
    #[arg(short, long, default_value_t = 8080)]
    port: u16,
}

The --config and the -c are the option, and the --port and the -p are the option with the default. The usage is my_tool [OPTIONS].

The flags. The bool field is the flag.

#[derive(Parser)]
struct Args {
    /// Enable the verbose output
    #[arg(short, long)]
    verbose: bool,

    /// Suppress the output
    #[arg(short, long)]
    quiet: bool,
}

The --verbose and the -v are the flag, and the --quiet and the -q are the flag. The flag is the false by default and the true when present.

The repeatable. The Vec<T> field is the repeatable.

#[derive(Parser)]
struct Args {
    /// The files to process
    #[arg(short, long)]
    files: Vec<String>,
}

The --files a.txt --files b.txt collects the ["a.txt", "b.txt"].

The required. The Option<T> is the optional, and the plain type is the required.

#[derive(Parser)]
struct Args {
    /// The required name
    #[arg(short, long)]
    name: String,  // the required

    /// The optional email
    #[arg(short, long)]
    email: Option<String>,  // the optional
}

The value_enum. The enum with the ValueEnum restricts the values.

use clap::ValueEnum;

#[derive(Clone, Debug, ValueEnum)]
enum Color {
    Auto,
    Always,
    Never,
}

#[derive(Parser)]
struct Args {
    /// When to use the color
    #[arg(long, value_enum, default_value_t = Color::Auto)]
    color: Color,
}

The --color always accepts the always, the never, and the auto, and the invalid value is the error.


c. The subcommands

The subcommands are the enum with the Subcommand derive.

use clap::{Parser, Subcommand};

#[derive(Parser)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Add a new item
    Add {
        /// The item name
        name: String,
    },
    /// Remove an item
    Remove {
        /// The item id
        id: u32,
    },
    /// List all the items
    List,
}

fn main() {
    let cli = Cli::parse();

    match cli.command {
        Commands::Add { name } => println!("Adding {}", name),
        Commands::Remove { id } => println!("Removing {}", id),
        Commands::List => println!("Listing"),
    }
}

The #[command(subcommand)] on the field makes it the subcommand. The Commands enum has the three variants: the Add, the Remove, and the List. The usage is my_tool <COMMAND>, and the my_tool add Alice runs the Add variant.

The nested subcommands. The subcommands can be nested.

#[derive(Subcommand)]
enum Commands {
    /// Manage the users
    User {
        #[command(subcommand)]
        action: UserAction,
    },
}

#[derive(Subcommand)]
enum UserAction {
    /// Create a user
    Create { name: String },
    /// Delete a user
    Delete { id: u32 },
}

The my_tool user create Alice runs the nested Create variant.

The optional subcommand. The Option<Commands> makes the subcommand optional.

#[derive(Parser)]
struct Cli {
    #[command(subcommand)]
    command: Option<Commands>,
}

The my_tool without the subcommand runs the default behavior.

The flatten. The #[command(flatten)] includes the fields of another struct.

#[derive(Parser)]
struct Cli {
    #[command(flatten)]
    verbose: Verbosity,

    #[command(subcommand)]
    command: Commands,
}

#[derive(clap::Args)]
struct Verbosity {
    /// Increase the verbosity
    #[arg(short, long, action = clap::ArgAction::Count)]
    verbose: u8,
}

The Verbosity struct is flattened into the Cli, and the --verbose is the global option.


Complete Example Session

// ============================================
// PART 1: THE BASIC PARSER
// ============================================

use clap::Parser;

/// A simple program to greet a person
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// Name of the person to greet
    #[arg(short, long)]
    name: String,

    /// Number of times to greet
    #[arg(short, long, default_value_t = 1)]
    count: u8,
}

fn main() {
    let args = Args::parse();

    for _ in 0..args.count {
        println!("Hello, {}!", args.name);
    }
}


// ============================================
// PART 2: THE POSITIONAL AND THE OPTIONS
// ============================================

use clap::Parser;

/// A file processing tool
#[derive(Parser, Debug)]
#[command(version, about)]
struct Args {
    /// The input file
    input: String,

    /// The output file
    #[arg(short, long)]
    output: Option<String>,

    /// The number of the threads
    #[arg(short, long, default_value_t = 4)]
    threads: usize,
}

fn main() {
    let args = Args::parse();
    println!("Input: {}", args.input);
    println!("Output: {:?}", args.output);
    println!("Threads: {}", args.threads);
}


// ============================================
// PART 3: THE FLAGS
// ============================================

use clap::Parser;

#[derive(Parser, Debug)]
struct Args {
    /// The input file
    input: String,

    /// Enable the verbose output
    #[arg(short, long)]
    verbose: bool,

    /// Suppress the output
    #[arg(short, long)]
    quiet: bool,
}

fn main() {
    let args = Args::parse();

    if args.verbose {
        println!("Verbose mode enabled");
    }
    if args.quiet {
        println!("Quiet mode enabled");
    }
}


// ============================================
// PART 4: THE REPEATABLE
// ============================================

use clap::Parser;

#[derive(Parser, Debug)]
struct Args {
    /// The files to process
    #[arg(short, long)]
    files: Vec<String>,
}

fn main() {
    let args = Args::parse();

    for file in &args.files {
        println!("Processing: {}", file);
    }
}

// The usage: my_tool --files a.txt --files b.txt


// ============================================
// PART 5: THE VALUE ENUM
// ============================================

use clap::{Parser, ValueEnum};

#[derive(Clone, Debug, ValueEnum)]
enum Color {
    Auto,
    Always,
    Never,
}

#[derive(Parser, Debug)]
struct Args {
    /// The input file
    input: String,

    /// When to use the color
    #[arg(long, value_enum, default_value_t = Color::Auto)]
    color: Color,
}

fn main() {
    let args = Args::parse();
    println!("Color: {:?}", args.color);
}


// ============================================
// PART 6: THE SUBCOMMANDS
// ============================================

use clap::{Parser, Subcommand};

#[derive(Parser, Debug)]
#[command(version, about)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
    /// Add a new item
    Add {
        /// The item name
        name: String,

        /// The item quantity
        #[arg(short, long, default_value_t = 1)]
        quantity: u32,
    },
    /// Remove an item
    Remove {
        /// The item id
        id: u32,
    },
    /// List all the items
    List,
}

fn main() {
    let cli = Cli::parse();

    match cli.command {
        Commands::Add { name, quantity } => {
            println!("Adding {} x{}", name, quantity);
        }
        Commands::Remove { id } => {
            println!("Removing {}", id);
        }
        Commands::List => {
            println!("Listing");
        }
    }
}


// ============================================
// PART 7: THE NESTED SUBCOMMANDS
// ============================================

use clap::{Parser, Subcommand};

#[derive(Parser, Debug)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
    /// Manage the users
    User {
        #[command(subcommand)]
        action: UserAction,
    },
    /// Manage the items
    Item {
        #[command(subcommand)]
        action: ItemAction,
    },
}

#[derive(Subcommand, Debug)]
enum UserAction {
    /// Create a user
    Create {
        /// The user name
        name: String,
    },
    /// Delete a user
    Delete {
        /// The user id
        id: u32,
    },
}

#[derive(Subcommand, Debug)]
enum ItemAction {
    /// Add an item
    Add { name: String },
    /// Remove an item
    Remove { id: u32 },
}

fn main() {
    let cli = Cli::parse();

    match cli.command {
        Commands::User { action } => match action {
            UserAction::Create { name } => println!("Creating user {}", name),
            UserAction::Delete { id } => println!("Deleting user {}", id),
        },
        Commands::Item { action } => match action {
            ItemAction::Add { name } => println!("Adding item {}", name),
            ItemAction::Remove { id } => println!("Removing item {}", id),
        },
    }
}


// ============================================
// PART 8: THE VALIDATION
// ============================================

use clap::Parser;

#[derive(Parser, Debug)]
struct Args {
    /// The port number
    #[arg(short, long, value_parser = clap::value_parser!(u16).range(1..=65535))]
    port: u16,

    /// The log level
    #[arg(long, value_parser = ["debug", "info", "warn", "error"])]
    log_level: String,
}

fn main() {
    let args = Args::parse();
    println!("Port: {}", args.port);
    println!("Log level: {}", args.log_level);
}


// ============================================
// PART 9: THE ENVIRONMENT VARIABLES
// ============================================

use clap::Parser;

#[derive(Parser, Debug)]
struct Args {
    /// The API key
    #[arg(long, env = "API_KEY")]
    api_key: String,

    /// The database URL
    #[arg(long, env = "DATABASE_URL", default_value = "postgres://localhost")]
    database_url: String,
}

fn main() {
    let args = Args::parse();
    println!("API key: {}", args.api_key);
    println!("Database: {}", args.database_url);
}

// The env attribute reads the environment variable.


// ============================================
// PART 10: THE COMPLETE EXAMPLE
// ============================================

use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;

/// A file management tool
#[derive(Parser, Debug)]
#[command(name = "filetool", version, about, long_about = None)]
struct Cli {
    /// Increase the verbosity
    #[arg(short, long, action = clap::ArgAction::Count)]
    verbose: u8,

    /// The configuration file
    #[arg(short, long, default_value = "config.toml")]
    config: PathBuf,

    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
    /// Copy a file
    Copy {
        /// The source file
        source: PathBuf,

        /// The destination
        destination: PathBuf,

        /// Overwrite the existing file
        #[arg(short, long)]
        force: bool,
    },
    /// Move a file
    Move {
        /// The source file
        source: PathBuf,

        /// The destination
        destination: PathBuf,
    },
    /// List the files
    List {
        /// The directory
        #[arg(default_value = ".")]
        directory: PathBuf,

        /// The output format
        #[arg(long, value_enum, default_value_t = Format::Table)]
        format: Format,
    },
}

#[derive(Clone, Debug, ValueEnum)]
enum Format {
    Table,
    Json,
    Plain,
}

fn main() {
    let cli = Cli::parse();

    match cli.verbose {
        0 => {}
        1 => println!("Verbose mode"),
        _ => println!("Very verbose mode"),
    }

    println!("Config: {:?}", cli.config);

    match cli.command {
        Commands::Copy {
            source,
            destination,
            force,
        } => {
            if force {
                println!("Force copying {:?} to {:?}", source, destination);
            } else {
                println!("Copying {:?} to {:?}", source, destination);
            }
        }
        Commands::Move {
            source,
            destination,
        } => {
            println!("Moving {:?} to {:?}", source, destination);
        }
        Commands::List { directory, format } => {
            println!("Listing {:?} as {:?}", directory, format);
        }
    }
}

The ten parts show the basic parser, the positional and the options, the flags, the repeatable, the ValueEnum, the subcommands, the nested subcommands, the validation, the environment variables, and the complete example.


Quick Reference

The Attributes

AttributePurpose
#[derive(Parser)]The derive the parser
#[derive(Subcommand)]The derive the subcommand
#[derive(Args)]The derive the args group
#[derive(ValueEnum)]The derive the value enum
#[command(...)]The program-level config
#[arg(...)]The argument-level config

The Common #[arg] Options

OptionPurpose
shortThe short form -n
longThe long form --name
default_value_tThe default value
default_valueThe default string
value_parserThe parser
value_enumThe enum values
envThe environment variable
requiredThe required
action = ArgAction::CountThe repeatable counter
action = ArgAction::SetTrueThe flag

The Field Types

TypeThe meaning
StringThe required string
Option<String>The optional string
Vec<String>The repeatable
boolThe flag
u8 / u16 / u32The number
PathBufThe file path
T: ValueEnumThe enum

The Program Attributes

AttributePurpose
nameThe program name
versionThe version
authorThe author
aboutThe short description
long_aboutThe long description

The Commands

CommandThe usage
my_tool --helpThe help
my_tool --versionThe version
my_tool <POSITIONAL>The positional
my_tool --option valueThe option
my_tool --flagThe flag
my_tool <SUBCOMMAND>The subcommand

Best Practices

✅ Do This:

// Use the derive API
#[derive(Parser)]
struct Args { ... }                                                       // ✅
// Use the doc comments for the help
/// The name of the person
#[arg(short, long)]
name: String,                                                             // ✅
// Use the Option<T> for the optional
output: Option<String>,                                                   // ✅
// Use the Vec<T> for the repeatable
files: Vec<String>,                                                       // ✅
// Use the ValueEnum for the constrained values
#[arg(long, value_enum)]
color: Color,                                                             // ✅
// Use the subcommands for the multiple actions
#[command(subcommand)]
command: Commands,                                                        // ✅
// Use the env attribute for the environment
#[arg(long, env = "API_KEY")]
api_key: String,                                                          // ✅
// Use the value_parser for the validation
#[arg(long, value_parser = clap::value_parser!(u16).range(1..))]
port: u16,                                                                // ✅

❌ Don’t Do This:

// Don't hand-write the parsing
let args: Vec<String> = std::env::args().collect(); // the manual          // ❌
// Don't forget the doc comment
#[arg(short, long)]
name: String,  // the missing help                                        // ❌
// Don't use the String for the optional
output: String,  // the required; use the Option                          // ❌
// Don't use the plain String for the enum
color: String,  // the invalid values possible                            // ❌
// Don't forget the default
#[arg(short, long)]
count: u8,  // the required; add the default_value_t                     // ❌
// Don't parse the env var manually
let key = std::env::var("API_KEY"); // the env attribute is the better    // ❌
// Don't use the builder for the static interface
// The derive is the concise and the type-safe                            // ❌

Common Pitfalls

PitfallWhy It HappensFix
The argument is not recognizedThe missing #[arg]Add the attribute
The help is emptyThe missing doc commentAdd the ///
The optional is requiredThe plain typeUse the Option<T>
The default is ignoredThe wrong attributeUse the default_value_t
The enum value failsThe missing value_enumAdd the value_enum
The subcommand is requiredThe plain typeUse the Option<Commands>
The env var is not readThe missing envAdd the env = "NAME"

Real-World Examples

1. The Basic Parser

#[derive(Parser)]
struct Args { #[arg(short, long)] name: String }

2. The Positional

#[derive(Parser)]
struct Args { input: String }

3. The Optional

#[derive(Parser)]
struct Args { output: Option<String> }

4. The Flag

#[derive(Parser)]
struct Args { #[arg(short, long)] verbose: bool }

5. The Repeatable

#[derive(Parser)]
struct Args { #[arg(short, long)] files: Vec<String> }

6. The ValueEnum

#[derive(ValueEnum)]
enum Color { Auto, Always, Never }

7. The Subcommand

#[derive(Subcommand)]
enum Commands { Add { name: String }, List }

8. The Validation

#[arg(long, value_parser = clap::value_parser!(u16).range(1..))]

9. The Environment

#[arg(long, env = "API_KEY")]

10. The Complete

#[derive(Parser)]
#[command(name = "tool", version, about)]
struct Cli { #[command(subcommand)] command: Commands }

Visual

The Derive API Flow

┌──────────────────────────────────────────────────────────────┐
│  THE DERIVE API FLOW                                         │
│                                                              │
│  The struct:                                                 │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  #[derive(Parser)]                                   │    │
│  │  struct Args {                                       │    │
│  │    /// The name                                      │    │
│  │    #[arg(short, long)]                               │    │
│  │    name: String,                                     │    │
│  │    /// The count                                     │    │
│  │    #[arg(short, long, default_value_t = 1)]          │    │
│  │    count: u8,                                        │    │
│  │  }                                                   │    │
│  └──────────────────────────────────────────────────────┘    │
│    │                                                         │
│    │  The derive macro generates the parser                  │
│    ▼                                                         │
│  The generated:                                              │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  impl Args {                                         │    │
│  │    fn parse() -> Self { ... }                        │    │
│  │    fn try_parse() -> Result<Self, Error> { ... }     │    │
│  │  }                                                   │    │
│  │                                                       │    │
│  │  The help generator, the validator, the error.       │    │
│  └──────────────────────────────────────────────────────┘    │
│    │                                                         │
│    ▼                                                         │
│  The runtime:                                                │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  let args = Args::parse();                           │    │
│  │  println!("{}", args.name);                          │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
└──────────────────────────────────────────────────────────────┘

The Argument Types

┌──────────────────────────────────────────────────────────────┐
│  THE ARGUMENT TYPES                                          │
│                                                              │
│  THE POSITIONAL:                                             │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  input: String                                       │    │
│  │  → my_tool input.txt                                 │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
│  THE OPTION:                                                 │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  #[arg(short, long)]                                 │    │
│  │  config: Option<String>                              │    │
│  │  → my_tool --config file.toml                        │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
│  THE FLAG:                                                   │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  #[arg(short, long)]                                 │    │
│  │  verbose: bool                                       │    │
│  │  → my_tool --verbose                                 │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
│  THE REPEATABLE:                                             │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  #[arg(short, long)]                                 │    │
│  │  files: Vec<String>                                  │    │
│  │  → my_tool --files a.txt --files b.txt               │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
└──────────────────────────────────────────────────────────────┘

The Subcommands

┌──────────────────────────────────────────────────────────────┐
│  THE SUBCOMMANDS                                             │
│                                                              │
│  #[derive(Subcommand)]                                       │
│  enum Commands {                                             │
│    Add { name: String },                                     │
│    Remove { id: u32 },                                       │
│    List,                                                     │
│  }                                                           │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  my_tool add Alice                                   │    │
│  │    → the Commands::Add { name: "Alice" }             │    │
│  │                                                       │    │
│  │  my_tool remove 42                                   │    │
│  │    → the Commands::Remove { id: 42 }                 │    │
│  │                                                       │    │
│  │  my_tool list                                        │    │
│  │    → the Commands::List                              │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
│  The match on the enum dispatches the action.                │
│                                                              │
└──────────────────────────────────────────────────────────────┘

The Help Generation

┌──────────────────────────────────────────────────────────────┐
│  THE HELP GENERATION                                         │
│                                                              │
│  /// A simple program to greet a person                      │
│  #[derive(Parser)]                                           │
│  #[command(version, about)]                                  │
│  struct Args {                                               │
│      /// Name of the person to greet                         │
│      #[arg(short, long)]                                     │
│      name: String,                                           │
│  }                                                           │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  $ my_tool --help                                    │    │
│  │                                                       │    │
│  │  A simple program to greet a person                  │    │
│  │                                                       │    │
│  │  Usage: my_tool [OPTIONS] --name <NAME>              │    │
│  │                                                       │    │
│  │  Options:                                            │    │
│  │    -n, --name <NAME>  Name of the person to greet    │    │
│  │    -h, --help         Print help                     │    │
│  │    -V, --version      Print version                  │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
│  The help is generated from the doc comments and the         │
│  attributes.                                                 │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Summary

ItemValue
clapThe command-line parsing library
#[derive(Parser)]The derive the parser
#[derive(Subcommand)]The derive the subcommand
#[derive(ValueEnum)]The derive the value enum
#[arg]The argument config
#[command]The program config
Args::parse()The parse the args
Option<T>The optional
Vec<T>The repeatable
boolThe flag
value_enumThe enum values
envThe environment variable

Key takeaways:

  • The clap crate is the standard command-line parsing library for Rust. It handles the parsing, the validation, and the help generation. The #[derive(Parser)] generates the parser, and the Args::parse() returns the struct .
  • The derive API maps the struct fields to the arguments. The field with the #[arg(short, long)] is the option, the bool is the flag, and the field without the short or the long is the positional. The doc comments are the help text .
  • The Option<T> is the optional, and the plain type is the required. The Vec<T> is the repeatable. The default_value_t provides the default. The value_enum restricts the values to the enum .
  • The #[command] configures the program, and the #[arg] configures the arguments. The #[command] sets the name, the version, the author, and the about. The #[arg] sets the short, the long, the default, the value parser, and the environment variable .
  • The subcommands use the enum with the #[derive(Subcommand)]. The #[command(subcommand)] on the field makes it the subcommand. The match on the enum dispatches the action, and the compiler ensures the exhaustive .
  • The value_parser validates the input. The clap::value_parser!(u16).range(1..) validates the range, and the ["debug", "info"] restricts the values. The invalid input is the clear error .
  • The env attribute reads the environment variable. The #[arg(long, env = "API_KEY")] reads the API_KEY when the option is not provided. The environment variable is the fallback .
  • The --help and the --version are generated automatically. The #[command(version, about)] enables them, and the doc comments are the content. The help is the documentation, and the documentation is the automatic .

Remember: The clap crate is the standard command-line parsing library for Rust. The derive API defines the parser with the struct and the attributes, and the builder API constructs it with the method calls. The #[derive(Parser)] generates the parser, the #[arg] configures the arguments, and the #[command] configures the program. The result is the polished command-line interface with the validation and the help, without the hand-written parsing.



Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!