#[arg()] decorates a field in a #[derive(Parser)] struct and tells clap how to parse that field from the command line. Every option inside #[arg()] is a key-value pair.
long — creates a --flag style argument. If you write #[arg(long)] with no value, it uses the field name. If you write #[arg(long = "1p")] it uses that string instead. That's why we have:
#[arg(long = "1p", ...)]
use_op: bool,Because the field is named use_op but the CLI flag is --1p.
short — creates a -f style single-character flag. #[arg(short)] uses the first letter of the field name. #[arg(short = 'f')] uses that character explicitly. You can combine both:
#[arg(short, long)]
find: Option<String>, // accepts both -f and --findalias — adds an alternative long name:
#[arg(long, alias = "substring")]
find: Option<String>, // accepts --find or --substringshort_alias — same but for short flags.
default_value — the string value used when the argument isn't provided:
#[arg(long, default_value = "ed25519")]
algorithm: String,default_value_t — like default_value but takes a typed Rust expression instead of a string, avoiding the parse step:
#[arg(long, default_value_t = 0)]
cores: usize,default_value_if — sets a default conditionally based on another argument's value:
#[arg(long, default_value_if("algorithm", "secp256k1", "some-default"))]
cores: usize,value_name — the placeholder shown in help text. Without it clap uses the uppercased field name:
#[arg(long, value_name = "SUBSTRING")]
find: Option<String>,
// shows: --find <SUBSTRING>value_parser — custom parsing logic. Can be a closure or a type implementing clap::builder::TypedValueParser:
#[arg(long, value_parser = clap::value_parser!(u16).range(1..))]
port: u16,value_enum — tells clap the type is an enum deriving clap::ValueEnum, enabling tab completion and validation automatically.
num_args — how many values the argument accepts:
#[arg(long, num_args = 1..=3)]
files: Vec<String>, // accepts 1, 2, or 3 valuesvalue_delimiter — splits a single string value on a delimiter:
#[arg(long, value_delimiter = ',')]
tags: Vec<String>, // --tags a,b,c becomes ["a", "b", "c"]required — makes the argument mandatory, overriding Option<T> inference:
#[arg(long, required = true)]
find: Option<String>,required_unless_present — required unless another named argument is present:
#[arg(long, required_unless_present = "begins")]
find: Option<String>,required_unless_present_any — required unless any of a list are present.
required_unless_present_all — required unless all of a list are present.
conflicts_with — errors if both this and another argument are provided:
#[arg(long, conflicts_with = "ends")]
begins: Option<String>,conflicts_with_all — same but a list.
requires — this argument requires another to also be present.
requires_all — requires all of a list.
action — controls what happens when the flag is encountered. The most common values are:
// SetTrue: sets bool to true when flag present (what --1p uses)
#[arg(long, action = clap::ArgAction::SetTrue)]
use_op: bool,
// SetFalse: sets bool to false when flag present
#[arg(long, action = clap::ArgAction::SetFalse)]
no_color: bool,
// Count: counts how many times the flag appears (-vvv = 3)
#[arg(short, action = clap::ArgAction::Count)]
verbose: u8,
// Append: collects multiple values into a Vec
#[arg(long, action = clap::ArgAction::Append)]
tag: Vec<String>,global — makes the argument available to subcommands automatically.
env — reads from an environment variable as a fallback when the flag isn't passed. CLI always wins over env:
#[arg(long, env = "FIND")]
find: Option<String>,
// reads $FIND if --find not providedhide_env — stops the env var name from appearing in help text.
hide_env_values — shows the env var name in help but hides its current value (useful for secrets).
help — the short description shown next to the argument in --help:
#[arg(long, help = "substring to search for in rAddress")]
find: Option<String>,long_help — shown when --help is used (some CLIs differentiate -h short vs --help long):
#[arg(long, long_help = "The substring to search for in the rAddress. \
Case insensitive by default. Must be alphanumeric.")]
find: Option<String>,hide — hides the argument from help output entirely but it still works:
#[arg(long, hide = true)]
debug_mode: bool,hide_short_help — hides from -h but shows in --help.
hide_long_help — hides from --help but shows in -h.
display_order — controls the order arguments appear in help output. Lower numbers appear first:
#[arg(long, display_order = 1)]
find: Option<String>,allow_hyphen_values — permits values that start with -, which clap would normally interpret as a flag:
#[arg(long, allow_hyphen_values = true)]
pattern: String, // allows --pattern -abcallow_negative_numbers — permits negative numeric values.
ignore_case — case-insensitive matching for value_enum types.
If you omit long and short, the argument becomes positional — it's matched by position in the command line rather than by flag name:
#[arg()]
input_file: String,
// invoked as: find-xrp-addr myfile.txt (no --input-file needed)last — marks the argument as the last positional, only valid after --:
#[arg(last = true)]
extra_args: Vec<String>,Looking at our actual fields with fresh eyes:
#[arg(long, env = "FIND")]
find: Option<String>,
// long: --find
// env: $FIND
// type: Option means not required
#[arg(long, default_value_t = true, env = "INSENSITIVE")]
insensitive: bool,
// long: --insensitive
// default_value_t: true means it's on unless --insensitive=false
// env: $INSENSITIVE
#[arg(long, default_value_t = 0, env = "CORES")]
cores: usize,
// 0 is our sentinel meaning "use all available"
#[arg(long = "1p", env = "USE_ONEPASSWORD", action = clap::ArgAction::SetTrue)]
use_op: bool,
// long = "1p": overrides field name because --use-op isn't what we want
// SetTrue: presence of --1p sets this to true, absence leaves it false
// without SetTrue on a bool, clap would require --1p=true explicitlyThe action = clap::ArgAction::SetTrue on use_op is subtle but important — without it, a bool field requires the user to write --1p=true explicitly. With SetTrue, just writing --1p is enough.