Claude-skill-registry clap-patterns
Common Clap patterns and idioms for argument parsing, validation, and CLI design. Use when implementing CLI arguments with Clap v4+.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/clap-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-clap-patterns && rm -rf "$T"
manifest:
skills/data/clap-patterns/SKILL.mdsource content
Clap Patterns Skill
Common patterns and idioms for using Clap v4+ effectively in Rust CLI applications.
Derive API vs Builder API
When to Use Derive API
- CLI structure known at compile time
- Want type safety and compile-time validation
- Prefer declarative style
- Standard CLI patterns are sufficient
#[derive(Parser)] #[command(version, about)] struct Cli { #[arg(short, long)] input: PathBuf, }
When to Use Builder API
- CLI needs to be built dynamically at runtime
- Building plugin systems
- Arguments depend on configuration
- Need maximum flexibility
fn build_cli() -> Command { Command::new("app") .arg(Arg::new("input").short('i')) }
Common Patterns
Global Options with Subcommands
#[derive(Parser)] struct Cli { #[arg(short, long, global = true, action = ArgAction::Count)] verbose: u8, #[command(subcommand)] command: Commands, }
Argument Groups for Mutual Exclusivity
#[derive(Parser)] #[command(group( ArgGroup::new("format") .required(true) .args(&["json", "yaml", "toml"]) ))] struct Cli { #[arg(long)] json: bool, #[arg(long)] yaml: bool, #[arg(long)] toml: bool, }
Custom Value Parsers
fn parse_port(s: &str) -> Result<u16, String> { let port: u16 = s.parse() .map_err(|_| format!("`{s}` isn't a valid port"))?; if (1024..=65535).contains(&port) { Ok(port) } else { Err(format!("port not in range 1024-65535")) } } #[derive(Parser)] struct Cli { #[arg(long, value_parser = parse_port)] port: u16, }
Environment Variable Fallbacks
#[derive(Parser)] struct Cli { #[arg(long, env = "API_TOKEN")] token: String, #[arg(long, env = "API_ENDPOINT", default_value = "https://api.example.com")] endpoint: String, }
Flattening Shared Options
#[derive(Args)] struct CommonOpts { #[arg(short, long)] verbose: bool, #[arg(short, long)] config: Option<PathBuf>, } #[derive(Parser)] struct Cli { #[command(flatten)] common: CommonOpts, #[command(subcommand)] command: Commands, }
Multiple Values
#[derive(Parser)] struct Cli { /// Tags (can be specified multiple times) #[arg(short, long)] tag: Vec<String>, /// Files to process files: Vec<PathBuf>, } // Usage: myapp --tag rust --tag cli file1.txt file2.txt
Subcommand with Shared Arguments
#[derive(Parser)] struct Cli { #[command(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { Build(BuildArgs), Test(TestArgs), } #[derive(Args)] struct BuildArgs { #[command(flatten)] common: CommonOpts, #[arg(short, long)] release: bool, }
Argument Counting (Verbosity Levels)
#[derive(Parser)] struct Cli { /// Verbosity (-v, -vv, -vvv) #[arg(short, long, action = ArgAction::Count)] verbose: u8, } // Usage: -v (1), -vv (2), -vvv (3)
Help Template Customization
#[derive(Parser)] #[command( after_help = "EXAMPLES:\n \ myapp --input file.txt\n \ myapp -i file.txt -vv\n\n\ For more info: https://example.com" )] struct Cli { // ... }
Value Hints
#[derive(Parser)] struct Cli { #[arg(short, long, value_name = "FILE", value_hint = ValueHint::FilePath)] input: PathBuf, #[arg(short, long, value_name = "DIR", value_hint = ValueHint::DirPath)] output: PathBuf, #[arg(short, long, value_name = "URL", value_hint = ValueHint::Url)] endpoint: String, }
Default Values with Functions
fn default_config_path() -> PathBuf { dirs::config_dir() .unwrap() .join("myapp") .join("config.toml") } #[derive(Parser)] struct Cli { #[arg(long, default_value_os_t = default_config_path())] config: PathBuf, }
Best Practices
- Use
for clearer help textvalue_name - Provide both short and long flags where appropriate
- Add help text to all arguments
- Use
for fixed set of choicesValueEnum - Validate early with custom parsers
- Support environment variables for sensitive data
- Use argument groups for mutually exclusive options
- Document with examples in
after_help - Use semantic types (PathBuf, not String for paths)
- Test CLI parsing with integration tests