Back to Skills

clap-patterns

verified

Common Clap patterns and idioms for argument parsing, validation, and CLI design. Use when implementing CLI arguments with Clap v4+.

View on GitHub

Marketplace

geoffjay-claude-plugins

geoffjay/claude-plugins

Plugin

rust-cli-developer

languages

Repository

geoffjay/claude-plugins
7stars

plugins/rust-cli-developer/skills/clap-patterns/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/geoffjay/claude-plugins/blob/main/plugins/rust-cli-developer/skills/clap-patterns/SKILL.md -a claude-code --skill clap-patterns

Installation paths:

Claude
.claude/skills/clap-patterns/
Powered by add-skill CLI

Instructions

# 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

```rust
#[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

```rust
fn build_cli() -> Command {
    Command::new("app")
        .arg(Arg::new("input").short('i'))
}
```

## Common Patterns

### Global Options with Subcommands

```rust
#[derive(Parser)]
struct Cli {
    #[arg(short, long, global = true, action = ArgAction::Count)]
    verbose: u8,

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

### Argument Groups for Mutual Exclusivity

```rust
#[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

```rust
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

```rust
#[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

```rust
#[derive(Args)]
struct CommonOpts {
    #[arg(short, long)]
    ver

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
4301 chars