title: CLI with Clap

Boilerplate for a command-line application using clap with the derive API.

Cargo.toml

[package]
name = "my-cli"
version = "0.1.0"
edition = "2021"
 
[dependencies]
clap = { version = "4", features = ["derive"] }

Basic CLI with subcommands

use clap::{Parser, Subcommand};
 
#[derive(Parser)]
#[command(name = "my-cli")]
#[command(about = "A simple CLI tool", long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}
 
#[derive(Subcommand)]
enum Commands {
    /// Add a new item
    Add {
        /// Name of the item to add
        name: String,
 
        /// Optional description
        #[arg(short, long)]
        description: Option<String>,
    },
 
    /// List all items
    List {
        /// Show verbose output
        #[arg(short, long)]
        verbose: bool,
    },
}
 
fn main() {
    let cli = Cli::parse();
 
    match cli.command {
        Commands::Add { name, description } => {
            println!("Adding: {name}");
            if let Some(desc) = description {
                println!("Description: {desc}");
            }
        }
        Commands::List { verbose } => {
            if verbose {
                println!("Listing all items (verbose)...");
            } else {
                println!("Listing all items...");
            }
        }
    }
}

Usage

my-cli add "foo"
my-cli add "foo" --description "bar"
my-cli list
my-cli list --verbose
my-cli --help
my-cli add --help

Global flags

Add flags to the top-level Cli struct to make them available to all subcommands:

#[derive(Parser)]
struct Cli {
    /// Enable debug output
    #[arg(short, long, global = true)]
    debug: bool,
 
    #[command(subcommand)]
    command: Commands,
}

Common arg types

/// A required positional argument
name: String,
 
/// An optional positional argument
name: Option<String>,
 
/// A flag (--verbose or -v)
#[arg(short, long)]
verbose: bool,
 
/// An option with a value (--output file.txt or -o file.txt)
#[arg(short, long)]
output: Option<String>,
 
/// A required option
#[arg(short, long)]
config: String,
 
/// Repeatable flag (--verbose -v -v counts occurrences)
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,