logo
pub struct Command { /* private fields */ }
Expand description

Build a command-line interface.

This includes defining arguments, subcommands, parser behavior, and help output. Once all configuration is complete, the Command::get_matches family of methods starts the runtime-parsing process. These methods then return information about the user supplied arguments (or lack thereof).

When deriving a Parser, you can use CommandFactory::command to access the Command.

Examples

let m = Command::new("My Program")
    .author("Me, me@mail.com")
    .version("1.0.2")
    .about("Explains in brief what the program does")
    .arg(
        Arg::new("in_file")
    )
    .after_help("Longer explanation to appear after the options when \
                 displaying the help information from --help or -h")
    .get_matches();

// Your program logic starts here...

Implementations

Creates a new instance of an Command.

It is common, but not required, to use binary name as the name. This name will only be displayed to the user when they request to print version or help and usage information.

See also command! and crate_name!.

Examples
Command::new("My Program")
Examples found in repository?
examples/multicall-busybox.rs (line 8)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn applet_commands() -> [Command; 2] {
    [
        Command::new("true").about("does nothing successfully"),
        Command::new("false").about("does nothing unsuccessfully"),
    ]
}

fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
More examples
Hide additional examples
examples/derive_ref/hand_subcommand.rs (line 54)
53
54
55
56
57
58
59
60
61
62
    fn augment_subcommands(cmd: Command) -> Command {
        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
            .subcommand_required(true)
    }
    fn augment_subcommands_for_update(cmd: Command) -> Command {
        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
            .subcommand_required(true)
    }
examples/derive_ref/augment_subcommands.rs (line 12)
11
12
13
14
15
16
17
18
19
20
21
fn main() {
    let cli = Command::new("Built CLI");
    // Augment with derived subcommands
    let cli = Subcommands::augment_subcommands(cli);

    let matches = cli.get_matches();
    let derived_subcommands = Subcommands::from_arg_matches(&matches)
        .map_err(|err| err.exit())
        .unwrap();
    println!("Derived subcommands: {:#?}", derived_subcommands);
}
examples/tutorial_builder/02_apps.rs (line 4)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main() {
    let matches = Command::new("MyApp")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg(arg!(--two <VALUE>).required(true))
        .arg(arg!(--one <VALUE>).required(true))
        .get_matches();

    println!(
        "two: {:?}",
        matches.get_one::<String>("two").expect("required")
    );
    println!(
        "one: {:?}",
        matches.get_one::<String>("one").expect("required")
    );
}
examples/multicall-hostname.rs (line 4)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
examples/tutorial_builder/03_04_subcommands.rs (line 9)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let matches = command!() // requires `cargo` feature
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("add")
                .about("Adds files to myapp")
                .arg(arg!([NAME])),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("add", sub_matches)) => println!(
            "'myapp add' was used, name is: {:?}",
            sub_matches.get_one::<String>("NAME")
        ),
        _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
    }
}

Adds an argument to the list of valid possibilities.

Examples
Command::new("myprog")
    // Adding a single "flag" argument with a short and help text, using Arg::new()
    .arg(
        Arg::new("debug")
           .short('d')
           .help("turns on debugging mode")
    )
    // Adding a single "option" argument with a short, a long, and help text using the less
    // verbose Arg::from()
    .arg(
        arg!(-c --config <CONFIG> "Optionally sets a config file to use")
    )
Examples found in repository?
examples/tutorial_builder/03_03_positional.rs (line 5)
3
4
5
6
7
8
9
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(Arg::new("name"))
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
More examples
Hide additional examples
examples/tutorial_builder/03_02_option.rs (line 5)
3
4
5
6
7
8
9
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(Arg::new("name").short('n').long("name"))
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
examples/tutorial_builder/03_03_positional_mult.rs (line 5)
3
4
5
6
7
8
9
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(Arg::new("name").action(ArgAction::Append))
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
examples/tutorial_builder/05_01_assert.rs (lines 15-19)
13
14
15
16
17
18
19
20
fn cmd() -> clap::Command {
    command!() // requires `cargo` feature
        .arg(
            arg!(<PORT>)
                .help("Network port to use")
                .value_parser(value_parser!(usize)),
        )
}
examples/tutorial_builder/03_02_option_mult.rs (lines 5-10)
3
4
5
6
7
8
9
10
11
12
13
14
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(
            Arg::new("name")
                .short('n')
                .long("name")
                .action(ArgAction::Append),
        )
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
examples/tutorial_builder/03_01_flag_count.rs (lines 5-10)
3
4
5
6
7
8
9
10
11
12
13
14
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(
            Arg::new("verbose")
                .short('v')
                .long("verbose")
                .action(ArgAction::Count),
        )
        .get_matches();

    println!("verbose: {:?}", matches.get_count("verbose"));
}

Adds multiple arguments to the list of valid possibilities.

Examples
Command::new("myprog")
    .args([
        arg!("[debug] -d 'turns on debugging info'"),
        Arg::new("input").help("the input file to use")
    ])
Examples found in repository?
examples/find.rs (lines 15-18)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn cli() -> Command {
    command!()
        .group(ArgGroup::new("tests").multiple(true))
        .next_help_heading("TESTS")
        .args([
            arg!(--empty "File is empty and is either a regular file or a directory").group("tests"),
            arg!(--name <NAME> "Base of file name (the path with the leading directories removed) matches shell pattern pattern").group("tests"),
        ])
        .group(ArgGroup::new("operators").multiple(true))
        .next_help_heading("OPERATORS")
        .args([
            arg!(-o - -or "expr2 is not evaluate if exp1 is true").group("operators"),
            arg!(-a - -and "Same as `expr1 expr1`").group("operators"),
        ])
}
More examples
Hide additional examples
examples/git.rs (line 40)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn cli() -> Command {
    Command::new("git")
        .about("A fictional versioning CLI")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("clone")
                .about("Clones repos")
                .arg(arg!(<REMOTE> "The remote to clone"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("diff")
                .about("Compare two commits")
                .arg(arg!(base: [COMMIT]))
                .arg(arg!(head: [COMMIT]))
                .arg(arg!(path: [PATH]).last(true)),
        )
        .subcommand(
            Command::new("push")
                .about("pushes things")
                .arg(arg!(<REMOTE> "The remote to target"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("add")
                .about("adds things")
                .arg_required_else_help(true)
                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
        )
        .subcommand(
            Command::new("stash")
                .args_conflicts_with_subcommands(true)
                .args(push_args())
                .subcommand(Command::new("push").args(push_args()))
                .subcommand(Command::new("pop").arg(arg!([STASH])))
                .subcommand(Command::new("apply").arg(arg!([STASH]))),
        )
}

Allows one to mutate an Arg after it’s been added to a Command.

This can be useful for modifying the auto-generated help or version arguments.

Panics

If the argument is undefined

Examples

let mut cmd = Command::new("foo")
    .arg(Arg::new("bar")
        .short('b')
        .action(ArgAction::SetTrue))
    .mut_arg("bar", |a| a.short('B'));

let res = cmd.try_get_matches_from_mut(vec!["foo", "-b"]);

// Since we changed `bar`'s short to "B" this should err as there
// is no `-b` anymore, only `-B`

assert!(res.is_err());

let res = cmd.try_get_matches_from_mut(vec!["foo", "-B"]);
assert!(res.is_ok());

Allows one to mutate a Command after it’s been added as a subcommand.

This can be useful for modifying auto-generated arguments of nested subcommands with Command::mut_arg.

Panics

If the subcommand is undefined

Examples

let mut cmd = Command::new("foo")
        .subcommand(Command::new("bar"))
        .mut_subcommand("bar", |subcmd| subcmd.disable_help_flag(true));

let res = cmd.try_get_matches_from_mut(vec!["foo", "bar", "--help"]);

// Since we disabled the help flag on the "bar" subcommand, this should err.

assert!(res.is_err());

let res = cmd.try_get_matches_from_mut(vec!["foo", "bar"]);
assert!(res.is_ok());

Adds an ArgGroup to the application.

ArgGroups are a family of related arguments. By placing them in a logical group, you can build easier requirement and exclusion rules.

Example use cases:

  • Make an entire ArgGroup required, meaning that one (and only one) argument from that group must be present at runtime.
  • Name an ArgGroup as a conflict to another argument. Meaning any of the arguments that belong to that group will cause a failure if present with the conflicting argument.
  • Ensure exclusion between arguments.
  • Extract a value from a group instead of determining exactly which argument was used.
Examples

The following example demonstrates using an ArgGroup to ensure that one, and only one, of the arguments from the specified group is present at runtime.

Command::new("cmd")
    .arg(arg!("--set-ver [ver] 'set the version manually'"))
    .arg(arg!("--major 'auto increase major'"))
    .arg(arg!("--minor 'auto increase minor'"))
    .arg(arg!("--patch 'auto increase patch'"))
    .group(ArgGroup::new("vers")
         .args(["set-ver", "major", "minor","patch"])
         .required(true))
Examples found in repository?
examples/find.rs (line 13)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn cli() -> Command {
    command!()
        .group(ArgGroup::new("tests").multiple(true))
        .next_help_heading("TESTS")
        .args([
            arg!(--empty "File is empty and is either a regular file or a directory").group("tests"),
            arg!(--name <NAME> "Base of file name (the path with the leading directories removed) matches shell pattern pattern").group("tests"),
        ])
        .group(ArgGroup::new("operators").multiple(true))
        .next_help_heading("OPERATORS")
        .args([
            arg!(-o - -or "expr2 is not evaluate if exp1 is true").group("operators"),
            arg!(-a - -and "Same as `expr1 expr1`").group("operators"),
        ])
}
More examples
Hide additional examples
examples/tutorial_builder/04_03_relations.rs (lines 14-18)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
fn main() {
    // Create application like normal
    let matches = command!() // requires `cargo` feature
        // Add the version arguments
        .arg(arg!(--"set-ver" <VER> "set version manually"))
        .arg(arg!(--major         "auto inc major").action(ArgAction::SetTrue))
        .arg(arg!(--minor         "auto inc minor").action(ArgAction::SetTrue))
        .arg(arg!(--patch         "auto inc patch").action(ArgAction::SetTrue))
        // Create a group, make it required, and add the above arguments
        .group(
            ArgGroup::new("vers")
                .required(true)
                .args(["set-ver", "major", "minor", "patch"]),
        )
        // Arguments can also be added to a group individually, these two arguments
        // are part of the "input" group which is not required
        .arg(
            arg!([INPUT_FILE] "some regular input")
                .value_parser(value_parser!(PathBuf))
                .group("input"),
        )
        .arg(
            arg!(--"spec-in" <SPEC_IN> "some special input argument")
                .value_parser(value_parser!(PathBuf))
                .group("input"),
        )
        // Now let's assume we have a -c [config] argument which requires one of
        // (but **not** both) the "input" arguments
        .arg(
            arg!(config: -c <CONFIG>)
                .value_parser(value_parser!(PathBuf))
                .requires("input"),
        )
        .get_matches();

    // Let's assume the old version 1.2.3
    let mut major = 1;
    let mut minor = 2;
    let mut patch = 3;

    // See if --set-ver was used to set the version manually
    let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
        ver.to_owned()
    } else {
        // Increment the one requested (in a real program, we'd reset the lower numbers)
        let (maj, min, pat) = (
            matches.get_flag("major"),
            matches.get_flag("minor"),
            matches.get_flag("patch"),
        );
        match (maj, min, pat) {
            (true, _, _) => major += 1,
            (_, true, _) => minor += 1,
            (_, _, true) => patch += 1,
            _ => unreachable!(),
        };
        format!("{}.{}.{}", major, minor, patch)
    };

    println!("Version: {}", version);

    // Check for usage of -c
    if matches.contains_id("config") {
        let input = matches
            .get_one::<PathBuf>("INPUT_FILE")
            .unwrap_or_else(|| matches.get_one::<PathBuf>("spec-in").unwrap())
            .display();
        println!(
            "Doing work using input {} and config {}",
            input,
            matches.get_one::<PathBuf>("config").unwrap().display()
        );
    }
}

Adds multiple ArgGroups to the Command at once.

Examples
Command::new("cmd")
    .arg(arg!("--set-ver [ver] 'set the version manually'"))
    .arg(arg!("--major         'auto increase major'"))
    .arg(arg!("--minor         'auto increase minor'"))
    .arg(arg!("--patch         'auto increase patch'"))
    .arg(arg!("-c [FILE]       'a config file'"))
    .arg(arg!("-i [IFACE]      'an interface'"))
    .groups([
        ArgGroup::new("vers")
            .args(["set-ver", "major", "minor","patch"])
            .required(true),
        ArgGroup::new("input")
            .args(["c", "i"])
    ])

Adds a subcommand to the list of valid possibilities.

Subcommands are effectively sub-Commands, because they can contain their own arguments, subcommands, version, usage, etc. They also function just like Commands, in that they get their own auto generated help, version, and usage.

A subcommand’s Command::name will be used for:

  • The argument the user passes in
  • Programmatically looking up the subcommand
Examples
Command::new("myprog")
    .subcommand(Command::new("config")
        .about("Controls configuration features")
        .arg(arg!("<config> 'Required configuration file to use'")))
Examples found in repository?
examples/derive_ref/hand_subcommand.rs (line 54)
53
54
55
56
57
58
59
60
61
62
    fn augment_subcommands(cmd: Command) -> Command {
        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
            .subcommand_required(true)
    }
    fn augment_subcommands_for_update(cmd: Command) -> Command {
        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
            .subcommand_required(true)
    }
More examples
Hide additional examples
examples/multicall-hostname.rs (line 9)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
examples/tutorial_builder/03_04_subcommands.rs (lines 8-12)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let matches = command!() // requires `cargo` feature
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("add")
                .about("Adds files to myapp")
                .arg(arg!([NAME])),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("add", sub_matches)) => println!(
            "'myapp add' was used, name is: {:?}",
            sub_matches.get_one::<String>("NAME")
        ),
        _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
    }
}
examples/cargo-example.rs (lines 5-10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let cmd = clap::Command::new("cargo")
        .bin_name("cargo")
        .subcommand_required(true)
        .subcommand(
            clap::command!("example").arg(
                clap::arg!(--"manifest-path" <PATH>)
                    .value_parser(clap::value_parser!(std::path::PathBuf)),
            ),
        );
    let matches = cmd.get_matches();
    let matches = match matches.subcommand() {
        Some(("example", matches)) => matches,
        _ => unreachable!("clap should ensure we don't get here"),
    };
    let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
    println!("{:?}", manifest_path);
}
examples/repl.rs (lines 71-75)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/multicall-busybox.rs (lines 16-31)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}

Adds multiple subcommands to the list of valid possibilities.

Examples
.subcommands( [
       Command::new("config").about("Controls configuration functionality")
                                .arg(Arg::new("config_file")),
       Command::new("debug").about("Controls debug functionality")])
Examples found in repository?
examples/multicall-busybox.rs (line 30)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}

Catch problems earlier in the development cycle.

Most error states are handled as asserts under the assumption they are programming mistake and not something to handle at runtime. Rather than relying on tests (manual or automated) that exhaustively test your CLI to ensure the asserts are evaluated, this will run those asserts in a way convenient for running as a test.

Note:: This will not help with asserts in ArgMatches, those will need exhaustive testing of your CLI.

Examples
fn cmd() -> Command {
    Command::new("foo")
        .arg(
            Arg::new("bar").short('b').action(ArgAction::SetTrue)
        )
}

#[test]
fn verify_app() {
    cmd().debug_assert();
}

fn main() {
    let m = cmd().get_matches_from(vec!["foo", "-b"]);
    println!("{}", *m.get_one::<bool>("bar").expect("defaulted by clap"));
}

Custom error message for post-parsing validation

Examples
let mut cmd = Command::new("myprog");
let err = cmd.error(ErrorKind::InvalidValue, "Some failure case");
Examples found in repository?
examples/tutorial_derive/04_04_custom.rs (lines 46-49)
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
fn main() {
    let cli = Cli::parse();

    // Let's assume the old version 1.2.3
    let mut major = 1;
    let mut minor = 2;
    let mut patch = 3;

    // See if --set-ver was used to set the version manually
    let version = if let Some(ver) = cli.set_ver.as_deref() {
        if cli.major || cli.minor || cli.patch {
            let mut cmd = Cli::command();
            cmd.error(
                ErrorKind::ArgumentConflict,
                "Can't do relative and absolute version change",
            )
            .exit();
        }
        ver.to_string()
    } else {
        // Increment the one requested (in a real program, we'd reset the lower numbers)
        let (maj, min, pat) = (cli.major, cli.minor, cli.patch);
        match (maj, min, pat) {
            (true, false, false) => major += 1,
            (false, true, false) => minor += 1,
            (false, false, true) => patch += 1,
            _ => {
                let mut cmd = Cli::command();
                cmd.error(
                    ErrorKind::ArgumentConflict,
                    "Can only modify one version field",
                )
                .exit();
            }
        };
        format!("{}.{}.{}", major, minor, patch)
    };

    println!("Version: {}", version);

    // Check for usage of -c
    if let Some(config) = cli.config.as_deref() {
        let input = cli
            .input_file
            .as_deref()
            // 'or' is preferred to 'or_else' here since `Option::as_deref` is 'const'
            .or(cli.spec_in.as_deref())
            .unwrap_or_else(|| {
                let mut cmd = Cli::command();
                cmd.error(
                    ErrorKind::MissingRequiredArgument,
                    "INPUT_FILE or --spec-in is required when using --config",
                )
                .exit()
            });
        println!("Doing work using input {} and config {}", input, config);
    }
}
More examples
Hide additional examples
examples/tutorial_builder/04_04_custom.rs (lines 34-37)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
fn main() {
    // Create application like normal
    let mut cmd = command!() // requires `cargo` feature
        // Add the version arguments
        .arg(arg!(--"set-ver" <VER> "set version manually"))
        .arg(arg!(--major         "auto inc major").action(ArgAction::SetTrue))
        .arg(arg!(--minor         "auto inc minor").action(ArgAction::SetTrue))
        .arg(arg!(--patch         "auto inc patch").action(ArgAction::SetTrue))
        // Arguments can also be added to a group individually, these two arguments
        // are part of the "input" group which is not required
        .arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf)))
        .arg(
            arg!(--"spec-in" <SPEC_IN> "some special input argument")
                .value_parser(value_parser!(PathBuf)),
        )
        // Now let's assume we have a -c [config] argument which requires one of
        // (but **not** both) the "input" arguments
        .arg(arg!(config: -c <CONFIG>).value_parser(value_parser!(PathBuf)));
    let matches = cmd.get_matches_mut();

    // Let's assume the old version 1.2.3
    let mut major = 1;
    let mut minor = 2;
    let mut patch = 3;

    // See if --set-ver was used to set the version manually
    let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
        if matches.get_flag("major") || matches.get_flag("minor") || matches.get_flag("patch") {
            cmd.error(
                ErrorKind::ArgumentConflict,
                "Can't do relative and absolute version change",
            )
            .exit();
        }
        ver.to_string()
    } else {
        // Increment the one requested (in a real program, we'd reset the lower numbers)
        let (maj, min, pat) = (
            matches.get_flag("major"),
            matches.get_flag("minor"),
            matches.get_flag("patch"),
        );
        match (maj, min, pat) {
            (true, false, false) => major += 1,
            (false, true, false) => minor += 1,
            (false, false, true) => patch += 1,
            _ => {
                cmd.error(
                    ErrorKind::ArgumentConflict,
                    "Can only modify one version field",
                )
                .exit();
            }
        };
        format!("{}.{}.{}", major, minor, patch)
    };

    println!("Version: {}", version);

    // Check for usage of -c
    if matches.contains_id("config") {
        let input = matches
            .get_one::<PathBuf>("INPUT_FILE")
            .or_else(|| matches.get_one::<PathBuf>("spec-in"))
            .unwrap_or_else(|| {
                cmd.error(
                    ErrorKind::MissingRequiredArgument,
                    "INPUT_FILE or --spec-in is required when using --config",
                )
                .exit()
            })
            .display();
        println!(
            "Doing work using input {} and config {}",
            input,
            matches.get_one::<PathBuf>("config").unwrap().display()
        );
    }
}

Parse env::args_os, exiting on failure.

Panics

If contradictory arguments or settings exist.

Examples
let matches = Command::new("myprog")
    // Args and options go here...
    .get_matches();
Examples found in repository?
examples/find.rs (line 6)
5
6
7
8
9
fn main() {
    let matches = cli().get_matches();
    let values = Value::from_matches(&matches);
    println!("{:#?}", values);
}
More examples
Hide additional examples
examples/tutorial_builder/03_03_positional.rs (line 6)
3
4
5
6
7
8
9
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(Arg::new("name"))
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
examples/tutorial_builder/03_02_option.rs (line 6)
3
4
5
6
7
8
9
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(Arg::new("name").short('n').long("name"))
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
examples/tutorial_builder/03_03_positional_mult.rs (line 6)
3
4
5
6
7
8
9
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(Arg::new("name").action(ArgAction::Append))
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}
examples/tutorial_builder/05_01_assert.rs (line 4)
3
4
5
6
7
8
9
10
11
fn main() {
    let matches = cmd().get_matches();

    // Note, it's safe to call unwrap() because the arg is required
    let port: usize = *matches
        .get_one::<usize>("PORT")
        .expect("'PORT' is required and parsing will fail if its missing");
    println!("PORT = {}", port);
}
examples/tutorial_builder/03_02_option_mult.rs (line 11)
3
4
5
6
7
8
9
10
11
12
13
14
fn main() {
    let matches = command!() // requires `cargo` feature
        .arg(
            Arg::new("name")
                .short('n')
                .long("name")
                .action(ArgAction::Append),
        )
        .get_matches();

    println!("name: {:?}", matches.get_one::<String>("name"));
}

Parse env::args_os, exiting on failure.

Like Command::get_matches but doesn’t consume the Command.

Panics

If contradictory arguments or settings exist.

Examples
let mut cmd = Command::new("myprog")
    // Args and options go here...
    ;
let matches = cmd.get_matches_mut();
Examples found in repository?
examples/tutorial_builder/04_04_custom.rs (line 24)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
fn main() {
    // Create application like normal
    let mut cmd = command!() // requires `cargo` feature
        // Add the version arguments
        .arg(arg!(--"set-ver" <VER> "set version manually"))
        .arg(arg!(--major         "auto inc major").action(ArgAction::SetTrue))
        .arg(arg!(--minor         "auto inc minor").action(ArgAction::SetTrue))
        .arg(arg!(--patch         "auto inc patch").action(ArgAction::SetTrue))
        // Arguments can also be added to a group individually, these two arguments
        // are part of the "input" group which is not required
        .arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf)))
        .arg(
            arg!(--"spec-in" <SPEC_IN> "some special input argument")
                .value_parser(value_parser!(PathBuf)),
        )
        // Now let's assume we have a -c [config] argument which requires one of
        // (but **not** both) the "input" arguments
        .arg(arg!(config: -c <CONFIG>).value_parser(value_parser!(PathBuf)));
    let matches = cmd.get_matches_mut();

    // Let's assume the old version 1.2.3
    let mut major = 1;
    let mut minor = 2;
    let mut patch = 3;

    // See if --set-ver was used to set the version manually
    let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
        if matches.get_flag("major") || matches.get_flag("minor") || matches.get_flag("patch") {
            cmd.error(
                ErrorKind::ArgumentConflict,
                "Can't do relative and absolute version change",
            )
            .exit();
        }
        ver.to_string()
    } else {
        // Increment the one requested (in a real program, we'd reset the lower numbers)
        let (maj, min, pat) = (
            matches.get_flag("major"),
            matches.get_flag("minor"),
            matches.get_flag("patch"),
        );
        match (maj, min, pat) {
            (true, false, false) => major += 1,
            (false, true, false) => minor += 1,
            (false, false, true) => patch += 1,
            _ => {
                cmd.error(
                    ErrorKind::ArgumentConflict,
                    "Can only modify one version field",
                )
                .exit();
            }
        };
        format!("{}.{}.{}", major, minor, patch)
    };

    println!("Version: {}", version);

    // Check for usage of -c
    if matches.contains_id("config") {
        let input = matches
            .get_one::<PathBuf>("INPUT_FILE")
            .or_else(|| matches.get_one::<PathBuf>("spec-in"))
            .unwrap_or_else(|| {
                cmd.error(
                    ErrorKind::MissingRequiredArgument,
                    "INPUT_FILE or --spec-in is required when using --config",
                )
                .exit()
            })
            .display();
        println!(
            "Doing work using input {} and config {}",
            input,
            matches.get_one::<PathBuf>("config").unwrap().display()
        );
    }
}

Parse env::args_os, returning a clap::Result on failure.

NOTE: This method WILL NOT exit when --help or --version (or short versions) are used. It will return a clap::Error, where the kind is a ErrorKind::DisplayHelp or ErrorKind::DisplayVersion respectively. You must call Error::exit or perform a std::process::exit.

Panics

If contradictory arguments or settings exist.

Examples
let matches = Command::new("myprog")
    // Args and options go here...
    .try_get_matches()
    .unwrap_or_else(|e| e.exit());

Parse the specified arguments, exiting on failure.

NOTE: The first argument will be parsed as the binary name unless Command::no_binary_name is used.

Panics

If contradictory arguments or settings exist.

Examples
let arg_vec = vec!["my_prog", "some", "args", "to", "parse"];

let matches = Command::new("myprog")
    // Args and options go here...
    .get_matches_from(arg_vec);

Parse the specified arguments, returning a clap::Result on failure.

NOTE: This method WILL NOT exit when --help or --version (or short versions) are used. It will return a clap::Error, where the kind is a ErrorKind::DisplayHelp or ErrorKind::DisplayVersion respectively. You must call Error::exit or perform a std::process::exit yourself.

NOTE: The first argument will be parsed as the binary name unless Command::no_binary_name is used.

Panics

If contradictory arguments or settings exist.

Examples
let arg_vec = vec!["my_prog", "some", "args", "to", "parse"];

let matches = Command::new("myprog")
    // Args and options go here...
    .try_get_matches_from(arg_vec)
    .unwrap_or_else(|e| e.exit());
Examples found in repository?
examples/repl.rs (line 32)
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fn respond(line: &str) -> Result<bool, String> {
    let args = shlex::split(line).ok_or("error: Invalid quoting")?;
    let matches = cli()
        .try_get_matches_from(&args)
        .map_err(|e| e.to_string())?;
    match matches.subcommand() {
        Some(("ping", _matches)) => {
            write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?;
            std::io::stdout().flush().map_err(|e| e.to_string())?;
        }
        Some(("quit", _matches)) => {
            write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?;
            std::io::stdout().flush().map_err(|e| e.to_string())?;
            return Ok(true);
        }
        Some((name, _matches)) => unimplemented!("{}", name),
        None => unreachable!("subcommand required"),
    }

    Ok(false)
}

Parse the specified arguments, returning a clap::Result on failure.

Like Command::try_get_matches_from but doesn’t consume the Command.

NOTE: This method WILL NOT exit when --help or --version (or short versions) are used. It will return a clap::Error, where the kind is a ErrorKind::DisplayHelp or ErrorKind::DisplayVersion respectively. You must call Error::exit or perform a std::process::exit yourself.

NOTE: The first argument will be parsed as the binary name unless Command::no_binary_name is used.

Panics

If contradictory arguments or settings exist.

Examples
let arg_vec = vec!["my_prog", "some", "args", "to", "parse"];

let mut cmd = Command::new("myprog");
    // Args and options go here...
let matches = cmd.try_get_matches_from_mut(arg_vec)
    .unwrap_or_else(|e| e.exit());

Prints the short help message (-h) to io::stdout().

See also Command::print_long_help.

Examples
let mut cmd = Command::new("myprog");
cmd.print_help();

Prints the long help message (--help) to io::stdout().

See also Command::print_help.

Examples
let mut cmd = Command::new("myprog");
cmd.print_long_help();

Render the short help message (-h) to a StyledStr

See also Command::render_long_help.

Examples
use std::io;
let mut cmd = Command::new("myprog");
let mut out = io::stdout();
let help = cmd.render_help();
println!("{}", help);

Render the long help message (--help) to a StyledStr.

See also Command::render_help.

Examples
use std::io;
let mut cmd = Command::new("myprog");
let mut out = io::stdout();
let help = cmd.render_long_help();
println!("{}", help);

Version message rendered as if the user ran -V.

See also Command::render_long_version.

Coloring

This function does not try to color the message nor it inserts any ANSI escape codes.

Examples
use std::io;
let cmd = Command::new("myprog");
println!("{}", cmd.render_version());

Version message rendered as if the user ran --version.

See also Command::render_version.

Coloring

This function does not try to color the message nor it inserts any ANSI escape codes.

Examples
use std::io;
let cmd = Command::new("myprog");
println!("{}", cmd.render_long_version());

Usage statement

Examples
use std::io;
let mut cmd = Command::new("myprog");
println!("{}", cmd.render_usage());

Application-wide Settings

These settings will apply to the top-level command and all subcommands, by default. Some settings can be overridden in subcommands.

Specifies that the parser should not assume the first argument passed is the binary name.

This is normally the case when using a “daemon” style mode. For shells / REPLs, see Command::multicall.

Examples
let m = Command::new("myprog")
    .no_binary_name(true)
    .arg(arg!(<cmd> ... "commands to run"))
    .get_matches_from(vec!["command", "set"]);

let cmds: Vec<_> = m.get_many::<String>("cmd").unwrap().collect();
assert_eq!(cmds, ["command", "set"]);

Try not to fail on parse errors, like missing option values.

Note: Make sure you apply it as global_setting if you want this setting to be propagated to subcommands and sub-subcommands!

NOTE: This choice is propagated to all child subcommands.

Examples
let cmd = Command::new("cmd")
  .ignore_errors(true)
  .arg(arg!(-c --config <FILE> "Sets a custom config file"))
  .arg(arg!(-x --stuff <FILE> "Sets a custom stuff file"))
  .arg(arg!(f: -f "Flag"));

let r = cmd.try_get_matches_from(vec!["cmd", "-c", "file", "-f", "-x"]);

assert!(r.is_ok(), "unexpected error: {:?}", r);
let m = r.unwrap();
assert_eq!(m.get_one::<String>("config").unwrap(), "file");
assert!(*m.get_one::<bool>("f").expect("defaulted"));
assert_eq!(m.get_one::<String>("stuff"), None);

Specifies that all arguments override themselves.

This is the equivalent to saying the foo arg using Arg::overrides_with("foo") for all defined arguments.

NOTE: This choice is propagated to all child subcommands.

Disables the automatic delimiting of values after -- or when Command::trailing_var_arg was used.

NOTE: The same thing can be done manually by setting the final positional argument to Arg::value_delimiter(None). Using this setting is safer, because it’s easier to locate when making changes.

NOTE: This choice is propagated to all child subcommands.

Examples
Command::new("myprog")
    .dont_delimit_trailing_values(true)
    .get_matches();
Available on crate feature color only.

Sets when to color output.

NOTE: This choice is propagated to all child subcommands.

NOTE: Default behaviour is ColorChoice::Auto.

Examples
Command::new("myprog")
    .color(ColorChoice::Never)
    .get_matches();

Sets the terminal width at which to wrap help messages.

Using 0 will ignore terminal widths and use source formatting.

Defaults to current terminal width when wrap_help feature flag is enabled. If the flag is disabled or it cannot be determined, the default is 100.

NOTE: This setting applies globally and not on a per-command basis.

Examples
Command::new("myprog")
    .term_width(80)

Limit the line length for wrapping help when using the current terminal’s width.

This only applies when term_width is unset so that the current terminal’s width will be used. See Command::term_width for more details.

Using 0 will ignore terminal widths and use source formatting (default).

NOTE: This setting applies globally and not on a per-command basis.

Examples
Command::new("myprog")
    .max_term_width(100)

Disables -V and --version flag.

Examples
let res = Command::new("myprog")
    .disable_version_flag(true)
    .try_get_matches_from(vec![
        "myprog", "-V"
    ]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);

Specifies to use the version of the current command for all subcommands.

Defaults to false; subcommands have independent version strings from their parents.

Note: Make sure you apply it as global_setting if you want this setting to be propagated to subcommands and sub-subcommands!

NOTE: This choice is propagated to all child subcommands.

Examples
Command::new("myprog")
    .version("v1.1")
    .propagate_version(true)
    .subcommand(Command::new("test"))
    .get_matches();
// running `$ myprog test --version` will display
// "myprog-test v1.1"
Examples found in repository?
examples/tutorial_builder/03_04_subcommands.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let matches = command!() // requires `cargo` feature
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("add")
                .about("Adds files to myapp")
                .arg(arg!([NAME])),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("add", sub_matches)) => println!(
            "'myapp add' was used, name is: {:?}",
            sub_matches.get_one::<String>("NAME")
        ),
        _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
    }
}

Places the help string for all arguments and subcommands on the line after them.

NOTE: This choice is propagated to all child subcommands.

Examples
Command::new("myprog")
    .next_line_help(true)
    .get_matches();
Examples found in repository?
examples/tutorial_builder/02_app_settings.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let matches = command!() // requires `cargo` feature
        .next_line_help(true)
        .arg(arg!(--two <VALUE>).required(true).action(ArgAction::Set))
        .arg(arg!(--one <VALUE>).required(true).action(ArgAction::Set))
        .get_matches();

    println!(
        "two: {:?}",
        matches.get_one::<String>("two").expect("required")
    );
    println!(
        "one: {:?}",
        matches.get_one::<String>("one").expect("required")
    );
}

Disables -h and --help flag.

NOTE: This choice is propagated to all child subcommands.

Examples
let res = Command::new("myprog")
    .disable_help_flag(true)
    .try_get_matches_from(vec![
        "myprog", "-h"
    ]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);

Disables the help subcommand.

Examples
let res = Command::new("myprog")
    .disable_help_subcommand(true)
    // Normally, creating a subcommand causes a `help` subcommand to automatically
    // be generated as well
    .subcommand(Command::new("test"))
    .try_get_matches_from(vec![
        "myprog", "help"
    ]);
assert!(res.is_err());
assert_eq!(res.unwrap_err().kind(), ErrorKind::InvalidSubcommand);

Disables colorized help messages.

NOTE: This choice is propagated to all child subcommands.

Examples
Command::new("myprog")
    .disable_colored_help(true)
    .get_matches();

Panic if help descriptions are omitted.

NOTE: When deriving Parser, you could instead check this at compile-time with #![deny(missing_docs)]

NOTE: This choice is propagated to all child subcommands.

Examples
Command::new("myprog")
    .help_expected(true)
    .arg(
        Arg::new("foo").help("It does foo stuff")
        // As required via `help_expected`, a help message was supplied
     )
Panics
Command::new("myapp")
    .help_expected(true)
    .arg(
        Arg::new("foo")
        // Someone forgot to put .about("...") here
        // Since the setting `help_expected` is activated, this will lead to
        // a panic (if you are in debug mode)
    )

Tells clap not to print possible values when displaying help information.

This can be useful if there are many values, or they are explained elsewhere.

To set this per argument, see Arg::hide_possible_values.

NOTE: This choice is propagated to all child subcommands.

Allow partial matches of long arguments or their aliases.

For example, to match an argument named --test, one could use --t, --te, --tes, and --test.

NOTE: The match must not be ambiguous at all in order to succeed. i.e. to match --te to --test there could not also be another argument or alias --temp because both start with --te

NOTE: This choice is propagated to all child subcommands.

Allow partial matches of subcommand names and their aliases.

For example, to match a subcommand named test, one could use t, te, tes, and test.

NOTE: The match must not be ambiguous at all in order to succeed. i.e. to match te to test there could not also be a subcommand or alias temp because both start with te

CAUTION: This setting can interfere with positional/free arguments, take care when designing CLIs which allow inferred subcommands and have potential positional/free arguments whose values could start with the same characters as subcommands. If this is the case, it’s recommended to use settings such as Command::args_conflicts_with_subcommands in conjunction with this setting.

NOTE: This choice is propagated to all child subcommands.

Examples
let m = Command::new("prog")
    .infer_subcommands(true)
    .subcommand(Command::new("test"))
    .get_matches_from(vec![
        "prog", "te"
    ]);
assert_eq!(m.subcommand_name(), Some("test"));

Command-specific Settings

These apply only to the current command and are not inherited by subcommands.

(Re)Sets the program’s name.

See Command::new for more details.

Examples
let cmd = clap::command!()
    .name("foo");

// continued logic goes here, such as `cmd.get_matches()` etc.

Overrides the runtime-determined name of the binary for help and error messages.

This should only be used when absolutely necessary, such as when the binary name for your application is misleading, or perhaps not how the user should invoke your program.

Pro-tip: When building things such as third party cargo subcommands, this setting should be used!

NOTE: This does not change or set the name of the binary file on disk. It only changes what clap thinks the name is for the purposes of error or help messages.

Examples
Command::new("My Program")
     .bin_name("my_binary")
Examples found in repository?
examples/cargo-example.rs (line 3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let cmd = clap::Command::new("cargo")
        .bin_name("cargo")
        .subcommand_required(true)
        .subcommand(
            clap::command!("example").arg(
                clap::arg!(--"manifest-path" <PATH>)
                    .value_parser(clap::value_parser!(std::path::PathBuf)),
            ),
        );
    let matches = cmd.get_matches();
    let matches = match matches.subcommand() {
        Some(("example", matches)) => matches,
        _ => unreachable!("clap should ensure we don't get here"),
    };
    let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
    println!("{:?}", manifest_path);
}

Overrides the runtime-determined display name of the program for help and error messages.

Examples
Command::new("My Program")
     .display_name("my_program")

Sets the author(s) for the help message.

Pro-tip: Use claps convenience macro crate_authors! to automatically set your application’s author(s) to the same thing as your crate at compile time.

Examples
Command::new("myprog")
     .author("Me, me@mymain.com")
Examples found in repository?
examples/tutorial_builder/02_apps.rs (line 6)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main() {
    let matches = Command::new("MyApp")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg(arg!(--two <VALUE>).required(true))
        .arg(arg!(--one <VALUE>).required(true))
        .get_matches();

    println!(
        "two: {:?}",
        matches.get_one::<String>("two").expect("required")
    );
    println!(
        "one: {:?}",
        matches.get_one::<String>("one").expect("required")
    );
}
More examples
Hide additional examples
examples/pacman.rs (line 9)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
fn main() {
    let matches = Command::new("pacman")
        .about("package manager utility")
        .version("5.2.1")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .author("Pacman Development Team")
        // Query subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("query")
                .short_flag('Q')
                .long_flag("query")
                .about("Query the package database.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .help("search locally installed packages for matching strings")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .short('i')
                        .conflicts_with("search")
                        .help("view package information")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        // Sync subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("sync")
                .short_flag('S')
                .long_flag("sync")
                .about("Synchronize packages.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..)
                        .help("search remote repositories for matching strings"),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .conflicts_with("search")
                        .short('i')
                        .action(ArgAction::SetTrue)
                        .help("view package information"),
                )
                .arg(
                    Arg::new("package")
                        .help("packages")
                        .required_unless_present("search")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("sync", sync_matches)) => {
            if sync_matches.contains_id("search") {
                let packages: Vec<_> = sync_matches
                    .get_many::<String>("search")
                    .expect("contains_id")
                    .map(|s| s.as_str())
                    .collect();
                let values = packages.join(", ");
                println!("Searching for {}...", values);
                return;
            }

            let packages: Vec<_> = sync_matches
                .get_many::<String>("package")
                .expect("is present")
                .map(|s| s.as_str())
                .collect();
            let values = packages.join(", ");

            if sync_matches.get_flag("info") {
                println!("Retrieving info for {}...", values);
            } else {
                println!("Installing {}...", values);
            }
        }
        Some(("query", query_matches)) => {
            if let Some(packages) = query_matches.get_many::<String>("info") {
                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Retrieving info for {}...", comma_sep);
            } else if let Some(queries) = query_matches.get_many::<String>("search") {
                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Searching Locally for {}...", comma_sep);
            } else {
                println!("Displaying all locally installed packages...");
            }
        }
        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    }
}

Sets the program’s description for the short help (-h).

If Command::long_about is not specified, this message will be displayed for --help.

NOTE: Only Command::about (short format) is used in completion script generation in order to be concise.

See also crate_description!.

Examples
Command::new("myprog")
    .about("Does really amazing things for great people")
Examples found in repository?
examples/multicall-busybox.rs (line 8)
6
7
8
9
10
11
fn applet_commands() -> [Command; 2] {
    [
        Command::new("true").about("does nothing successfully"),
        Command::new("false").about("does nothing unsuccessfully"),
    ]
}
More examples
Hide additional examples
examples/tutorial_builder/02_apps.rs (line 7)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main() {
    let matches = Command::new("MyApp")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg(arg!(--two <VALUE>).required(true))
        .arg(arg!(--one <VALUE>).required(true))
        .get_matches();

    println!(
        "two: {:?}",
        matches.get_one::<String>("two").expect("required")
    );
    println!(
        "one: {:?}",
        matches.get_one::<String>("one").expect("required")
    );
}
examples/multicall-hostname.rs (line 9)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
examples/tutorial_builder/03_04_subcommands.rs (line 10)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let matches = command!() // requires `cargo` feature
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("add")
                .about("Adds files to myapp")
                .arg(arg!([NAME])),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("add", sub_matches)) => println!(
            "'myapp add' was used, name is: {:?}",
            sub_matches.get_one::<String>("NAME")
        ),
        _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
    }
}
examples/repl.rs (line 73)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/git.rs (line 8)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn cli() -> Command {
    Command::new("git")
        .about("A fictional versioning CLI")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("clone")
                .about("Clones repos")
                .arg(arg!(<REMOTE> "The remote to clone"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("diff")
                .about("Compare two commits")
                .arg(arg!(base: [COMMIT]))
                .arg(arg!(head: [COMMIT]))
                .arg(arg!(path: [PATH]).last(true)),
        )
        .subcommand(
            Command::new("push")
                .about("pushes things")
                .arg(arg!(<REMOTE> "The remote to target"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("add")
                .about("adds things")
                .arg_required_else_help(true)
                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
        )
        .subcommand(
            Command::new("stash")
                .args_conflicts_with_subcommands(true)
                .args(push_args())
                .subcommand(Command::new("push").args(push_args()))
                .subcommand(Command::new("pop").arg(arg!([STASH])))
                .subcommand(Command::new("apply").arg(arg!([STASH]))),
        )
}

Sets the program’s description for the long help (--help).

If Command::about is not specified, this message will be displayed for -h.

NOTE: Only Command::about (short format) is used in completion script generation in order to be concise.

Examples
Command::new("myprog")
    .long_about(
"Does really amazing things to great people. Now let's talk a little
 more in depth about how this subcommand really works. It may take about
 a few lines of text, but that's ok!")

Free-form help text for after auto-generated short help (-h).

This is often used to describe how to use the arguments, caveats to be noted, or license and contact information.

If Command::after_long_help is not specified, this message will be displayed for --help.

Examples
Command::new("myprog")
    .after_help("Does really amazing things for great people... but be careful with -R!")

Free-form help text for after auto-generated long help (--help).

This is often used to describe how to use the arguments, caveats to be noted, or license and contact information.

If Command::after_help is not specified, this message will be displayed for -h.

Examples
Command::new("myprog")
    .after_long_help("Does really amazing things to great people... but be careful with -R, \
                     like, for real, be careful with this!")

Free-form help text for before auto-generated short help (-h).

This is often used for header, copyright, or license information.

If Command::before_long_help is not specified, this message will be displayed for --help.

Examples
Command::new("myprog")
    .before_help("Some info I'd like to appear before the help info")

Free-form help text for before auto-generated long help (--help).

This is often used for header, copyright, or license information.

If Command::before_help is not specified, this message will be displayed for -h.

Examples
Command::new("myprog")
    .before_long_help("Some verbose and long info I'd like to appear before the help info")

Sets the version for the short version (-V) and help messages.

If Command::long_version is not specified, this message will be displayed for --version.

Pro-tip: Use claps convenience macro crate_version! to automatically set your application’s version to the same thing as your crate at compile time.

Examples
Command::new("myprog")
    .version("v0.1.24")
Examples found in repository?
examples/tutorial_builder/02_apps.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main() {
    let matches = Command::new("MyApp")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg(arg!(--two <VALUE>).required(true))
        .arg(arg!(--one <VALUE>).required(true))
        .get_matches();

    println!(
        "two: {:?}",
        matches.get_one::<String>("two").expect("required")
    );
    println!(
        "one: {:?}",
        matches.get_one::<String>("one").expect("required")
    );
}
More examples
Hide additional examples
examples/pacman.rs (line 6)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
fn main() {
    let matches = Command::new("pacman")
        .about("package manager utility")
        .version("5.2.1")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .author("Pacman Development Team")
        // Query subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("query")
                .short_flag('Q')
                .long_flag("query")
                .about("Query the package database.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .help("search locally installed packages for matching strings")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .short('i')
                        .conflicts_with("search")
                        .help("view package information")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        // Sync subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("sync")
                .short_flag('S')
                .long_flag("sync")
                .about("Synchronize packages.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..)
                        .help("search remote repositories for matching strings"),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .conflicts_with("search")
                        .short('i')
                        .action(ArgAction::SetTrue)
                        .help("view package information"),
                )
                .arg(
                    Arg::new("package")
                        .help("packages")
                        .required_unless_present("search")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("sync", sync_matches)) => {
            if sync_matches.contains_id("search") {
                let packages: Vec<_> = sync_matches
                    .get_many::<String>("search")
                    .expect("contains_id")
                    .map(|s| s.as_str())
                    .collect();
                let values = packages.join(", ");
                println!("Searching for {}...", values);
                return;
            }

            let packages: Vec<_> = sync_matches
                .get_many::<String>("package")
                .expect("is present")
                .map(|s| s.as_str())
                .collect();
            let values = packages.join(", ");

            if sync_matches.get_flag("info") {
                println!("Retrieving info for {}...", values);
            } else {
                println!("Installing {}...", values);
            }
        }
        Some(("query", query_matches)) => {
            if let Some(packages) = query_matches.get_many::<String>("info") {
                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Retrieving info for {}...", comma_sep);
            } else if let Some(queries) = query_matches.get_many::<String>("search") {
                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Searching Locally for {}...", comma_sep);
            } else {
                println!("Displaying all locally installed packages...");
            }
        }
        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    }
}

Sets the version for the long version (--version) and help messages.

If Command::version is not specified, this message will be displayed for -V.

Pro-tip: Use claps convenience macro crate_version! to automatically set your application’s version to the same thing as your crate at compile time.

Examples
Command::new("myprog")
    .long_version(
"v0.1.24
 commit: abcdef89726d
 revision: 123
 release: 2
 binary: myprog")

Overrides the clap generated usage string for help and error messages.

NOTE: Using this setting disables claps “context-aware” usage strings. After this setting is set, this will be the only usage string displayed to the user!

NOTE: Multiple usage lines may be present in the usage argument, but some rules need to be followed to ensure the usage lines are formatted correctly by the default help formatter:

  • Do not indent the first usage line.
  • Indent all subsequent usage lines with seven spaces.
  • The last line must not end with a newline.
Examples
Command::new("myprog")
    .override_usage("myapp [-clDas] <some_file>")

Or for multiple usage lines:

Command::new("myprog")
    .override_usage(
        "myapp -X [-a] [-b] <file>\n       \
         myapp -Y [-c] <file1> <file2>\n       \
         myapp -Z [-d|-e]"
    )

Overrides the clap generated help message (both -h and --help).

This should only be used when the auto-generated message does not suffice.

NOTE: This only replaces the help message for the current command, meaning if you are using subcommands, those help messages will still be auto-generated unless you specify a Command::override_help for them as well.

Examples
Command::new("myapp")
    .override_help("myapp v1.0\n\
           Does awesome things\n\
           (C) me@mail.com\n\n\

           Usage: myapp <opts> <command>\n\n\

           Options:\n\
           -h, --help       Display this message\n\
           -V, --version    Display version info\n\
           -s <stuff>       Do something with stuff\n\
           -v               Be verbose\n\n\

           Commands:\n\
           help             Print this message\n\
           work             Do some work")
Available on crate feature help only.

Sets the help template to be used, overriding the default format.

NOTE: The template system is by design very simple. Therefore, the tags have to be written in the lowercase and without spacing.

Tags are given inside curly brackets.

Valid tags are:

  • {name} - Display name for the (sub-)command.
  • {bin} - Binary name.
  • {version} - Version number.
  • {author} - Author information.
  • {author-with-newline} - Author followed by \n.
  • {author-section} - Author preceded and followed by \n.
  • {about} - General description (from Command::about or Command::long_about).
  • {about-with-newline} - About followed by \n.
  • {about-section} - About preceded and followed by ‘\n’.
  • {usage-heading} - Automatically generated usage heading.
  • {usage} - Automatically generated or given usage string.
  • {all-args} - Help for all arguments (options, flags, positional arguments, and subcommands) including titles.
  • {options} - Help for options.
  • {positionals} - Help for positional arguments.
  • {subcommands} - Help for subcommands.
  • {tag} - Standard tab sized used within clap
  • {after-help} - Help from Command::after_help or Command::after_long_help.
  • {before-help} - Help from Command::before_help or Command::before_long_help.
Examples
Command::new("myprog")
    .version("1.0")
    .help_template("{bin} ({version}) - {usage}")
Examples found in repository?
examples/repl.rs (line 70)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}

Set the default section heading for future args.

This will be used for any arg that hasn’t had Arg::help_heading called.

This is useful if the default Options or Arguments headings are not specific enough for one’s use case.

For subcommands, see Command::subcommand_help_heading

Examples found in repository?
examples/find.rs (line 14)
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn cli() -> Command {
    command!()
        .group(ArgGroup::new("tests").multiple(true))
        .next_help_heading("TESTS")
        .args([
            arg!(--empty "File is empty and is either a regular file or a directory").group("tests"),
            arg!(--name <NAME> "Base of file name (the path with the leading directories removed) matches shell pattern pattern").group("tests"),
        ])
        .group(ArgGroup::new("operators").multiple(true))
        .next_help_heading("OPERATORS")
        .args([
            arg!(-o - -or "expr2 is not evaluate if exp1 is true").group("operators"),
            arg!(-a - -and "Same as `expr1 expr1`").group("operators"),
        ])
}

Change the starting value for assigning future display orders for ags.

This will be used for any arg that hasn’t had Arg::display_order called.

Available on crate feature unstable-replace only.

Replaces an argument or subcommand used on the CLI at runtime with other arguments or subcommands.

Note: This is gated behind unstable-replace

When this method is used, name is removed from the CLI, and target is inserted in its place. Parsing continues as if the user typed target instead of name.

This can be used to create “shortcuts” for subcommands, or if a particular argument has the semantic meaning of several other specific arguments and values.

Examples

We’ll start with the “subcommand short” example. In this example, let’s assume we have a program with a subcommand module which can be invoked via cmd module. Now let’s also assume module also has a subcommand called install which can be invoked cmd module install. If for some reason users needed to be able to reach cmd module install via the short-hand cmd install, we’d have several options.

We could create another sibling subcommand to module called install, but then we would need to manage another subcommand and manually dispatch to cmd module install handling code. This is error prone and tedious.

We could instead use Command::replace so that, when the user types cmd install, clap will replace install with module install which will end up getting parsed as if the user typed the entire incantation.

let m = Command::new("cmd")
    .subcommand(Command::new("module")
        .subcommand(Command::new("install")))
    .replace("install", &["module", "install"])
    .get_matches_from(vec!["cmd", "install"]);

assert!(m.subcommand_matches("module").is_some());
assert!(m.subcommand_matches("module").unwrap().subcommand_matches("install").is_some());

Now let’s show an argument example!

Let’s assume we have an application with two flags --save-context and --save-runtime. But often users end up needing to do both at the same time. We can add a third flag --save-all which semantically means the same thing as cmd --save-context --save-runtime. To implement that, we have several options.

We could create this third argument and manually check if that argument and in our own consumer code handle the fact that both --save-context and --save-runtime should have been used. But again this is error prone and tedious. If we had code relying on checking --save-context and we forgot to update that code to also check --save-all it’d mean an error!

Luckily we can use Command::replace so that when the user types --save-all, clap will replace that argument with --save-context --save-runtime, and parsing will continue like normal. Now all our code that was originally checking for things like --save-context doesn’t need to change!

let m = Command::new("cmd")
    .arg(Arg::new("save-context")
        .long("save-context")
        .action(ArgAction::SetTrue))
    .arg(Arg::new("save-runtime")
        .long("save-runtime")
        .action(ArgAction::SetTrue))
    .replace("--save-all", &["--save-context", "--save-runtime"])
    .get_matches_from(vec!["cmd", "--save-all"]);

assert!(*m.get_one::<bool>("save-context").expect("defaulted by clap"));
assert!(*m.get_one::<bool>("save-runtime").expect("defaulted by clap"));

This can also be used with options, for example if our application with --save-* above also had a --format=TYPE option. Let’s say it accepted txt or json values. However, when --save-all is used, only --format=json is allowed, or valid. We could change the example above to enforce this:

let m = Command::new("cmd")
    .arg(Arg::new("save-context")
        .long("save-context")
        .action(ArgAction::SetTrue))
    .arg(Arg::new("save-runtime")
        .long("save-runtime")
        .action(ArgAction::SetTrue))
    .arg(Arg::new("format")
        .long("format")
        .action(ArgAction::Set)
        .value_parser(["txt", "json"]))
    .replace("--save-all", &["--save-context", "--save-runtime", "--format=json"])
    .get_matches_from(vec!["cmd", "--save-all"]);

assert!(*m.get_one::<bool>("save-context").expect("defaulted by clap"));
assert!(*m.get_one::<bool>("save-runtime").expect("defaulted by clap"));
assert_eq!(m.get_one::<String>("format").unwrap(), "json");

Exit gracefully if no arguments are present (e.g. $ myprog).

NOTE: subcommands count as arguments

Examples
Command::new("myprog")
    .arg_required_else_help(true);
Examples found in repository?
examples/multicall-hostname.rs (line 6)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
More examples
Hide additional examples
examples/tutorial_builder/03_04_subcommands.rs (line 7)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let matches = command!() // requires `cargo` feature
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("add")
                .about("Adds files to myapp")
                .arg(arg!([NAME])),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("add", sub_matches)) => println!(
            "'myapp add' was used, name is: {:?}",
            sub_matches.get_one::<String>("NAME")
        ),
        _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
    }
}
examples/repl.rs (line 66)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/multicall-busybox.rs (line 18)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
examples/git.rs (line 10)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn cli() -> Command {
    Command::new("git")
        .about("A fictional versioning CLI")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("clone")
                .about("Clones repos")
                .arg(arg!(<REMOTE> "The remote to clone"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("diff")
                .about("Compare two commits")
                .arg(arg!(base: [COMMIT]))
                .arg(arg!(head: [COMMIT]))
                .arg(arg!(path: [PATH]).last(true)),
        )
        .subcommand(
            Command::new("push")
                .about("pushes things")
                .arg(arg!(<REMOTE> "The remote to target"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("add")
                .about("adds things")
                .arg_required_else_help(true)
                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
        )
        .subcommand(
            Command::new("stash")
                .args_conflicts_with_subcommands(true)
                .args(push_args())
                .subcommand(Command::new("push").args(push_args()))
                .subcommand(Command::new("pop").arg(arg!([STASH])))
                .subcommand(Command::new("apply").arg(arg!([STASH]))),
        )
}
examples/pacman.rs (line 8)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
fn main() {
    let matches = Command::new("pacman")
        .about("package manager utility")
        .version("5.2.1")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .author("Pacman Development Team")
        // Query subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("query")
                .short_flag('Q')
                .long_flag("query")
                .about("Query the package database.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .help("search locally installed packages for matching strings")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .short('i')
                        .conflicts_with("search")
                        .help("view package information")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        // Sync subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("sync")
                .short_flag('S')
                .long_flag("sync")
                .about("Synchronize packages.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..)
                        .help("search remote repositories for matching strings"),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .conflicts_with("search")
                        .short('i')
                        .action(ArgAction::SetTrue)
                        .help("view package information"),
                )
                .arg(
                    Arg::new("package")
                        .help("packages")
                        .required_unless_present("search")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("sync", sync_matches)) => {
            if sync_matches.contains_id("search") {
                let packages: Vec<_> = sync_matches
                    .get_many::<String>("search")
                    .expect("contains_id")
                    .map(|s| s.as_str())
                    .collect();
                let values = packages.join(", ");
                println!("Searching for {}...", values);
                return;
            }

            let packages: Vec<_> = sync_matches
                .get_many::<String>("package")
                .expect("is present")
                .map(|s| s.as_str())
                .collect();
            let values = packages.join(", ");

            if sync_matches.get_flag("info") {
                println!("Retrieving info for {}...", values);
            } else {
                println!("Installing {}...", values);
            }
        }
        Some(("query", query_matches)) => {
            if let Some(packages) = query_matches.get_many::<String>("info") {
                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Retrieving info for {}...", comma_sep);
            } else if let Some(queries) = query_matches.get_many::<String>("search") {
                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Searching Locally for {}...", comma_sep);
            } else {
                println!("Displaying all locally installed packages...");
            }
        }
        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    }
}

Allows one to implement two styles of CLIs where positionals can be used out of order.

The first example is a CLI where the second to last positional argument is optional, but the final positional argument is required. Such as $ prog [optional] <required> where one of the two following usages is allowed:

  • $ prog [optional] <required>
  • $ prog <required>

This would otherwise not be allowed. This is useful when [optional] has a default value.

Note: when using this style of “missing positionals” the final positional must be required if -- will not be used to skip to the final positional argument.

Note: This style also only allows a single positional argument to be “skipped” without the use of --. To skip more than one, see the second example.

The second example is when one wants to skip multiple optional positional arguments, and use of the -- operator is OK (but not required if all arguments will be specified anyways).

For example, imagine a CLI which has three positional arguments [foo] [bar] [baz]... where baz accepts multiple values (similar to man ARGS... style training arguments).

With this setting the following invocations are posisble:

  • $ prog foo bar baz1 baz2 baz3
  • $ prog foo -- baz1 baz2 baz3
  • $ prog -- baz1 baz2 baz3
Examples

Style number one from above:

// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
    .allow_missing_positional(true)
    .arg(Arg::new("arg1"))
    .arg(Arg::new("arg2")
        .required(true))
    .get_matches_from(vec![
        "prog", "other"
    ]);

assert_eq!(m.get_one::<String>("arg1"), None);
assert_eq!(m.get_one::<String>("arg2").unwrap(), "other");

Now the same example, but using a default value for the first optional positional argument

// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
    .allow_missing_positional(true)
    .arg(Arg::new("arg1")
        .default_value("something"))
    .arg(Arg::new("arg2")
        .required(true))
    .get_matches_from(vec![
        "prog", "other"
    ]);

assert_eq!(m.get_one::<String>("arg1").unwrap(), "something");
assert_eq!(m.get_one::<String>("arg2").unwrap(), "other");

Style number two from above:

// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
    .allow_missing_positional(true)
    .arg(Arg::new("foo"))
    .arg(Arg::new("bar"))
    .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..))
    .get_matches_from(vec![
        "prog", "foo", "bar", "baz1", "baz2", "baz3"
    ]);

assert_eq!(m.get_one::<String>("foo").unwrap(), "foo");
assert_eq!(m.get_one::<String>("bar").unwrap(), "bar");
assert_eq!(m.get_many::<String>("baz").unwrap().collect::<Vec<_>>(), &["baz1", "baz2", "baz3"]);

Now nofice if we don’t specify foo or baz but use the -- operator.

// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
    .allow_missing_positional(true)
    .arg(Arg::new("foo"))
    .arg(Arg::new("bar"))
    .arg(Arg::new("baz").action(ArgAction::Set).num_args(1..))
    .get_matches_from(vec![
        "prog", "--", "baz1", "baz2", "baz3"
    ]);

assert_eq!(m.get_one::<String>("foo"), None);
assert_eq!(m.get_one::<String>("bar"), None);
assert_eq!(m.get_many::<String>("baz").unwrap().collect::<Vec<_>>(), &["baz1", "baz2", "baz3"]);

Sets the short version of the subcommand flag without the preceding -.

Allows the subcommand to be used as if it were an Arg::short.

Examples
let matches = Command::new("pacman")
    .subcommand(
        Command::new("sync").short_flag('S').arg(
            Arg::new("search")
                .short('s')
                .long("search")
                .action(ArgAction::SetTrue)
                .help("search remote repositories for matching strings"),
        ),
    )
    .get_matches_from(vec!["pacman", "-Ss"]);

assert_eq!(matches.subcommand_name().unwrap(), "sync");
let sync_matches = matches.subcommand_matches("sync").unwrap();
assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
Examples found in repository?
examples/pacman.rs (line 15)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
fn main() {
    let matches = Command::new("pacman")
        .about("package manager utility")
        .version("5.2.1")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .author("Pacman Development Team")
        // Query subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("query")
                .short_flag('Q')
                .long_flag("query")
                .about("Query the package database.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .help("search locally installed packages for matching strings")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .short('i')
                        .conflicts_with("search")
                        .help("view package information")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        // Sync subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("sync")
                .short_flag('S')
                .long_flag("sync")
                .about("Synchronize packages.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..)
                        .help("search remote repositories for matching strings"),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .conflicts_with("search")
                        .short('i')
                        .action(ArgAction::SetTrue)
                        .help("view package information"),
                )
                .arg(
                    Arg::new("package")
                        .help("packages")
                        .required_unless_present("search")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("sync", sync_matches)) => {
            if sync_matches.contains_id("search") {
                let packages: Vec<_> = sync_matches
                    .get_many::<String>("search")
                    .expect("contains_id")
                    .map(|s| s.as_str())
                    .collect();
                let values = packages.join(", ");
                println!("Searching for {}...", values);
                return;
            }

            let packages: Vec<_> = sync_matches
                .get_many::<String>("package")
                .expect("is present")
                .map(|s| s.as_str())
                .collect();
            let values = packages.join(", ");

            if sync_matches.get_flag("info") {
                println!("Retrieving info for {}...", values);
            } else {
                println!("Installing {}...", values);
            }
        }
        Some(("query", query_matches)) => {
            if let Some(packages) = query_matches.get_many::<String>("info") {
                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Retrieving info for {}...", comma_sep);
            } else if let Some(queries) = query_matches.get_many::<String>("search") {
                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Searching Locally for {}...", comma_sep);
            } else {
                println!("Displaying all locally installed packages...");
            }
        }
        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    }
}

Sets the long version of the subcommand flag without the preceding --.

Allows the subcommand to be used as if it were an Arg::long.

NOTE: Any leading - characters will be stripped.

Examples

To set long_flag use a word containing valid UTF-8 codepoints. If you supply a double leading -- such as --sync they will be stripped. Hyphens in the middle of the word; however, will not be stripped (i.e. sync-file is allowed).

let matches = Command::new("pacman")
    .subcommand(
        Command::new("sync").long_flag("sync").arg(
            Arg::new("search")
                .short('s')
                .long("search")
                .action(ArgAction::SetTrue)
                .help("search remote repositories for matching strings"),
        ),
    )
    .get_matches_from(vec!["pacman", "--sync", "--search"]);

assert_eq!(matches.subcommand_name().unwrap(), "sync");
let sync_matches = matches.subcommand_matches("sync").unwrap();
assert!(*sync_matches.get_one::<bool>("search").expect("defaulted by clap"));
Examples found in repository?
examples/pacman.rs (line 16)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
fn main() {
    let matches = Command::new("pacman")
        .about("package manager utility")
        .version("5.2.1")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .author("Pacman Development Team")
        // Query subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("query")
                .short_flag('Q')
                .long_flag("query")
                .about("Query the package database.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .help("search locally installed packages for matching strings")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .short('i')
                        .conflicts_with("search")
                        .help("view package information")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        // Sync subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("sync")
                .short_flag('S')
                .long_flag("sync")
                .about("Synchronize packages.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..)
                        .help("search remote repositories for matching strings"),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .conflicts_with("search")
                        .short('i')
                        .action(ArgAction::SetTrue)
                        .help("view package information"),
                )
                .arg(
                    Arg::new("package")
                        .help("packages")
                        .required_unless_present("search")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("sync", sync_matches)) => {
            if sync_matches.contains_id("search") {
                let packages: Vec<_> = sync_matches
                    .get_many::<String>("search")
                    .expect("contains_id")
                    .map(|s| s.as_str())
                    .collect();
                let values = packages.join(", ");
                println!("Searching for {}...", values);
                return;
            }

            let packages: Vec<_> = sync_matches
                .get_many::<String>("package")
                .expect("is present")
                .map(|s| s.as_str())
                .collect();
            let values = packages.join(", ");

            if sync_matches.get_flag("info") {
                println!("Retrieving info for {}...", values);
            } else {
                println!("Installing {}...", values);
            }
        }
        Some(("query", query_matches)) => {
            if let Some(packages) = query_matches.get_many::<String>("info") {
                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Retrieving info for {}...", comma_sep);
            } else if let Some(queries) = query_matches.get_many::<String>("search") {
                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Searching Locally for {}...", comma_sep);
            } else {
                println!("Displaying all locally installed packages...");
            }
        }
        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    }
}

Sets a hidden alias to this subcommand.

This allows the subcommand to be accessed via either the original name, or this given alias. This is more efficient and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all aliased variants.

NOTE: Aliases defined with this method are hidden from the help message. If you’re looking for aliases that will be displayed in the help message, see Command::visible_alias.

NOTE: When using aliases and checking for the existence of a particular subcommand within an ArgMatches struct, one only needs to search for the original name and not all aliases.

Examples
let m = Command::new("myprog")
    .subcommand(Command::new("test")
        .alias("do-stuff"))
    .get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));
Examples found in repository?
examples/repl.rs (line 78)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}

Add an alias, which functions as “hidden” short flag subcommand

This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").short_flag('t')
                .short_flag_alias('d'))
            .get_matches_from(vec!["myprog", "-d"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add an alias, which functions as a “hidden” long flag subcommand.

This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").long_flag("test")
                .long_flag_alias("testing"))
            .get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));

Sets multiple hidden aliases to this subcommand.

This allows the subcommand to be accessed via either the original name or any of the given aliases. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command and not all aliased variants.

NOTE: Aliases defined with this method are hidden from the help message. If looking for aliases that will be displayed in the help message, see Command::visible_aliases.

NOTE: When using aliases and checking for the existence of a particular subcommand within an ArgMatches struct, one only needs to search for the original name and not all aliases.

Examples
let m = Command::new("myprog")
    .subcommand(Command::new("test")
        .aliases(["do-stuff", "do-tests", "tests"]))
        .arg(Arg::new("input")
            .help("the file to add")
            .required(false))
    .get_matches_from(vec!["myprog", "do-tests"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add aliases, which function as “hidden” short flag subcommands.

These will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.

Examples
let m = Command::new("myprog")
    .subcommand(Command::new("test").short_flag('t')
        .short_flag_aliases(['a', 'b', 'c']))
        .arg(Arg::new("input")
            .help("the file to add")
            .required(false))
    .get_matches_from(vec!["myprog", "-a"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add aliases, which function as “hidden” long flag subcommands.

These will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").long_flag("test")
                .long_flag_aliases(["testing", "testall", "test_all"]))
                .arg(Arg::new("input")
                            .help("the file to add")
                            .required(false))
            .get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));

Sets a visible alias to this subcommand.

This allows the subcommand to be accessed via either the original name or the given alias. This is more efficient and easier than creating hidden subcommands as one only needs to check for the existence of this command and not all aliased variants.

NOTE: The alias defined with this method is visible from the help message and displayed as if it were just another regular subcommand. If looking for an alias that will not be displayed in the help message, see Command::alias.

NOTE: When using aliases and checking for the existence of a particular subcommand within an ArgMatches struct, one only needs to search for the original name and not all aliases.

Examples
let m = Command::new("myprog")
    .subcommand(Command::new("test")
        .visible_alias("do-stuff"))
    .get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add an alias, which functions as “visible” short flag subcommand

This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.

See also Command::short_flag_alias.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").short_flag('t')
                .visible_short_flag_alias('d'))
            .get_matches_from(vec!["myprog", "-d"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add an alias, which functions as a “visible” long flag subcommand.

This will automatically dispatch as if this subcommand was used. This is more efficient, and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command, and not all variants.

See also Command::long_flag_alias.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").long_flag("test")
                .visible_long_flag_alias("testing"))
            .get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));

Sets multiple visible aliases to this subcommand.

This allows the subcommand to be accessed via either the original name or any of the given aliases. This is more efficient and easier than creating multiple hidden subcommands as one only needs to check for the existence of this command and not all aliased variants.

NOTE: The alias defined with this method is visible from the help message and displayed as if it were just another regular subcommand. If looking for an alias that will not be displayed in the help message, see Command::alias.

NOTE: When using aliases, and checking for the existence of a particular subcommand within an ArgMatches struct, one only needs to search for the original name and not all aliases.

Examples
let m = Command::new("myprog")
    .subcommand(Command::new("test")
        .visible_aliases(["do-stuff", "tests"]))
    .get_matches_from(vec!["myprog", "do-stuff"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add aliases, which function as visible short flag subcommands.

See Command::short_flag_aliases.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").short_flag('b')
                .visible_short_flag_aliases(['t']))
            .get_matches_from(vec!["myprog", "-t"]);
assert_eq!(m.subcommand_name(), Some("test"));

Add aliases, which function as visible long flag subcommands.

See Command::long_flag_aliases.

Examples
let m = Command::new("myprog")
            .subcommand(Command::new("test").long_flag("test")
                .visible_long_flag_aliases(["testing", "testall", "test_all"]))
            .get_matches_from(vec!["myprog", "--testing"]);
assert_eq!(m.subcommand_name(), Some("test"));

Set the placement of this subcommand within the help.

Subcommands with a lower value will be displayed first in the help message. Subcommands with duplicate display orders will be displayed in alphabetical order.

This is helpful when one would like to emphasize frequently used subcommands, or prioritize those towards the top of the list.

NOTE: The default is 999 for all subcommands.

Examples
let m = Command::new("cust-ord")
   .subcommand(Command::new("alpha") // typically subcommands are grouped
                                              // alphabetically by name. Subcommands
                                              // without a display_order have a value of
                                              // 999 and are displayed alphabetically with
                                              // all other 999 subcommands
       .about("Some help and text"))
   .subcommand(Command::new("beta")
       .display_order(1)   // In order to force this subcommand to appear *first*
                           // all we have to do is give it a value lower than 999.
                           // Any other subcommands with a value of 1 will be displayed
                           // alphabetically with this one...then 2 values, then 3, etc.
       .about("I should be first!"))
   .get_matches_from(vec![
       "cust-ord", "--help"
   ]);

The above example displays the following help message

cust-ord

Usage: cust-ord [OPTIONS]

Commands:
    beta    I should be first!
    alpha   Some help and text

Options:
    -h, --help       Print help information
    -V, --version    Print version information

Specifies that this subcommand should be hidden from help messages

Examples
Command::new("myprog")
    .subcommand(
        Command::new("test").hide(true)
    )

If no subcommand is present at runtime, error and exit gracefully.

Examples
let err = Command::new("myprog")
    .subcommand_required(true)
    .subcommand(Command::new("test"))
    .try_get_matches_from(vec![
        "myprog",
    ]);
assert!(err.is_err());
assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand);
Examples found in repository?
examples/derive_ref/hand_subcommand.rs (line 56)
53
54
55
56
57
58
59
60
61
62
    fn augment_subcommands(cmd: Command) -> Command {
        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
            .subcommand_required(true)
    }
    fn augment_subcommands_for_update(cmd: Command) -> Command {
        cmd.subcommand(AddArgs::augment_args(Command::new("add")))
            .subcommand(RemoveArgs::augment_args(Command::new("remove")))
            .subcommand_required(true)
    }
More examples
Hide additional examples
examples/tutorial_builder/03_04_subcommands.rs (line 6)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let matches = command!() // requires `cargo` feature
        .propagate_version(true)
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("add")
                .about("Adds files to myapp")
                .arg(arg!([NAME])),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("add", sub_matches)) => println!(
            "'myapp add' was used, name is: {:?}",
            sub_matches.get_one::<String>("NAME")
        ),
        _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
    }
}
examples/cargo-example.rs (line 4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let cmd = clap::Command::new("cargo")
        .bin_name("cargo")
        .subcommand_required(true)
        .subcommand(
            clap::command!("example").arg(
                clap::arg!(--"manifest-path" <PATH>)
                    .value_parser(clap::value_parser!(std::path::PathBuf)),
            ),
        );
    let matches = cmd.get_matches();
    let matches = match matches.subcommand() {
        Some(("example", matches)) => matches,
        _ => unreachable!("clap should ensure we don't get here"),
    };
    let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
    println!("{:?}", manifest_path);
}
examples/repl.rs (line 67)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/git.rs (line 9)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn cli() -> Command {
    Command::new("git")
        .about("A fictional versioning CLI")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("clone")
                .about("Clones repos")
                .arg(arg!(<REMOTE> "The remote to clone"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("diff")
                .about("Compare two commits")
                .arg(arg!(base: [COMMIT]))
                .arg(arg!(head: [COMMIT]))
                .arg(arg!(path: [PATH]).last(true)),
        )
        .subcommand(
            Command::new("push")
                .about("pushes things")
                .arg(arg!(<REMOTE> "The remote to target"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("add")
                .about("adds things")
                .arg_required_else_help(true)
                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
        )
        .subcommand(
            Command::new("stash")
                .args_conflicts_with_subcommands(true)
                .args(push_args())
                .subcommand(Command::new("push").args(push_args()))
                .subcommand(Command::new("pop").arg(arg!([STASH])))
                .subcommand(Command::new("apply").arg(arg!([STASH]))),
        )
}
examples/pacman.rs (line 7)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
fn main() {
    let matches = Command::new("pacman")
        .about("package manager utility")
        .version("5.2.1")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .author("Pacman Development Team")
        // Query subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("query")
                .short_flag('Q')
                .long_flag("query")
                .about("Query the package database.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .help("search locally installed packages for matching strings")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .short('i')
                        .conflicts_with("search")
                        .help("view package information")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        // Sync subcommand
        //
        // Only a few of its arguments are implemented below.
        .subcommand(
            Command::new("sync")
                .short_flag('S')
                .long_flag("sync")
                .about("Synchronize packages.")
                .arg(
                    Arg::new("search")
                        .short('s')
                        .long("search")
                        .conflicts_with("info")
                        .action(ArgAction::Set)
                        .num_args(1..)
                        .help("search remote repositories for matching strings"),
                )
                .arg(
                    Arg::new("info")
                        .long("info")
                        .conflicts_with("search")
                        .short('i')
                        .action(ArgAction::SetTrue)
                        .help("view package information"),
                )
                .arg(
                    Arg::new("package")
                        .help("packages")
                        .required_unless_present("search")
                        .action(ArgAction::Set)
                        .num_args(1..),
                ),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("sync", sync_matches)) => {
            if sync_matches.contains_id("search") {
                let packages: Vec<_> = sync_matches
                    .get_many::<String>("search")
                    .expect("contains_id")
                    .map(|s| s.as_str())
                    .collect();
                let values = packages.join(", ");
                println!("Searching for {}...", values);
                return;
            }

            let packages: Vec<_> = sync_matches
                .get_many::<String>("package")
                .expect("is present")
                .map(|s| s.as_str())
                .collect();
            let values = packages.join(", ");

            if sync_matches.get_flag("info") {
                println!("Retrieving info for {}...", values);
            } else {
                println!("Installing {}...", values);
            }
        }
        Some(("query", query_matches)) => {
            if let Some(packages) = query_matches.get_many::<String>("info") {
                let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Retrieving info for {}...", comma_sep);
            } else if let Some(queries) = query_matches.get_many::<String>("search") {
                let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
                println!("Searching Locally for {}...", comma_sep);
            } else {
                println!("Displaying all locally installed packages...");
            }
        }
        _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
    }
}

Assume unexpected positional arguments are a subcommand.

Arguments will be stored in the "" argument in the ArgMatches

NOTE: Use this setting with caution, as a truly unexpected argument (i.e. one that is NOT an external subcommand) will not cause an error and instead be treated as a potential subcommand. One should check for such cases manually and inform the user appropriately.

NOTE: A built-in subcommand will be parsed as an external subcommand when escaped with --.

Examples
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
    .allow_external_subcommands(true)
    .get_matches_from(vec![
        "myprog", "subcmd", "--option", "value", "-fff", "--flag"
    ]);

// All trailing arguments will be stored under the subcommand's sub-matches using an empty
// string argument name
match m.subcommand() {
    Some((external, ext_m)) => {
         let ext_args: Vec<_> = ext_m.get_many::<OsString>("").unwrap().collect();
         assert_eq!(external, "subcmd");
         assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
    },
    _ => {},
}
Examples found in repository?
examples/git.rs (line 11)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn cli() -> Command {
    Command::new("git")
        .about("A fictional versioning CLI")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("clone")
                .about("Clones repos")
                .arg(arg!(<REMOTE> "The remote to clone"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("diff")
                .about("Compare two commits")
                .arg(arg!(base: [COMMIT]))
                .arg(arg!(head: [COMMIT]))
                .arg(arg!(path: [PATH]).last(true)),
        )
        .subcommand(
            Command::new("push")
                .about("pushes things")
                .arg(arg!(<REMOTE> "The remote to target"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("add")
                .about("adds things")
                .arg_required_else_help(true)
                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
        )
        .subcommand(
            Command::new("stash")
                .args_conflicts_with_subcommands(true)
                .args(push_args())
                .subcommand(Command::new("push").args(push_args()))
                .subcommand(Command::new("pop").arg(arg!([STASH])))
                .subcommand(Command::new("apply").arg(arg!([STASH]))),
        )
}

Specifies how to parse external subcommand arguments.

The default parser is for OsString. This can be used to switch it to String or another type.

NOTE: Setting this requires Command::allow_external_subcommands

Examples
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
   .allow_external_subcommands(true)
   .get_matches_from(vec![
       "myprog", "subcmd", "--option", "value", "-fff", "--flag"
   ]);

// All trailing arguments will be stored under the subcommand's sub-matches using an empty
// string argument name
match m.subcommand() {
   Some((external, ext_m)) => {
        let ext_args: Vec<_> = ext_m.get_many::<OsString>("").unwrap().collect();
        assert_eq!(external, "subcmd");
        assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
   },
   _ => {},
}
// Assume there is an external subcommand named "subcmd"
let m = Command::new("myprog")
    .external_subcommand_value_parser(value_parser!(String))
    .get_matches_from(vec![
        "myprog", "subcmd", "--option", "value", "-fff", "--flag"
    ]);

// All trailing arguments will be stored under the subcommand's sub-matches using an empty
// string argument name
match m.subcommand() {
    Some((external, ext_m)) => {
         let ext_args: Vec<_> = ext_m.get_many::<String>("").unwrap().collect();
         assert_eq!(external, "subcmd");
         assert_eq!(ext_args, ["--option", "value", "-fff", "--flag"]);
    },
    _ => {},
}

Specifies that use of an argument prevents the use of subcommands.

By default clap allows arguments between subcommands such as <cmd> [cmd_args] <subcmd> [subcmd_args] <subsubcmd> [subsubcmd_args].

This setting disables that functionality and says that arguments can only follow the final subcommand. For instance using this setting makes only the following invocations possible:

  • <cmd> <subcmd> <subsubcmd> [subsubcmd_args]
  • <cmd> <subcmd> [subcmd_args]
  • <cmd> [cmd_args]
Examples
Command::new("myprog")
    .args_conflicts_with_subcommands(true);
Examples found in repository?
examples/git.rs (line 39)
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn cli() -> Command {
    Command::new("git")
        .about("A fictional versioning CLI")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(
            Command::new("clone")
                .about("Clones repos")
                .arg(arg!(<REMOTE> "The remote to clone"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("diff")
                .about("Compare two commits")
                .arg(arg!(base: [COMMIT]))
                .arg(arg!(head: [COMMIT]))
                .arg(arg!(path: [PATH]).last(true)),
        )
        .subcommand(
            Command::new("push")
                .about("pushes things")
                .arg(arg!(<REMOTE> "The remote to target"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("add")
                .about("adds things")
                .arg_required_else_help(true)
                .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
        )
        .subcommand(
            Command::new("stash")
                .args_conflicts_with_subcommands(true)
                .args(push_args())
                .subcommand(Command::new("push").args(push_args()))
                .subcommand(Command::new("pop").arg(arg!([STASH])))
                .subcommand(Command::new("apply").arg(arg!([STASH]))),
        )
}

Prevent subcommands from being consumed as an arguments value.

By default, if an option taking multiple values is followed by a subcommand, the subcommand will be parsed as another value.

cmd --foo val1 val2 subcommand
          --------- ----------
            values   another value

This setting instructs the parser to stop when encountering a subcommand instead of greedily consuming arguments.

cmd --foo val1 val2 subcommand
          --------- ----------
            values   subcommand

Note: Make sure you apply it as global_setting if you want this setting to be propagated to subcommands and sub-subcommands!

Examples
let cmd = Command::new("cmd").subcommand(Command::new("sub")).arg(
    Arg::new("arg")
        .long("arg")
        .num_args(1..)
        .action(ArgAction::Set),
);

let matches = cmd
    .clone()
    .try_get_matches_from(&["cmd", "--arg", "1", "2", "3", "sub"])
    .unwrap();
assert_eq!(
    matches.get_many::<String>("arg").unwrap().collect::<Vec<_>>(),
    &["1", "2", "3", "sub"]
);
assert!(matches.subcommand_matches("sub").is_none());

let matches = cmd
    .subcommand_precedence_over_arg(true)
    .try_get_matches_from(&["cmd", "--arg", "1", "2", "3", "sub"])
    .unwrap();
assert_eq!(
    matches.get_many::<String>("arg").unwrap().collect::<Vec<_>>(),
    &["1", "2", "3"]
);
assert!(matches.subcommand_matches("sub").is_some());

Allows subcommands to override all requirements of the parent command.

For example, if you had a subcommand or top level application with a required argument that is only required as long as there is no subcommand present, using this setting would allow you to set those arguments to Arg::required(true) and yet receive no error so long as the user uses a valid subcommand instead.

NOTE: This defaults to false (using subcommand does not negate requirements)

Examples

This first example shows that it is an error to not use a required argument

let err = Command::new("myprog")
    .subcommand_negates_reqs(true)
    .arg(Arg::new("opt").required(true))
    .subcommand(Command::new("test"))
    .try_get_matches_from(vec![
        "myprog"
    ]);
assert!(err.is_err());
assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);

This next example shows that it is no longer error to not use a required argument if a valid subcommand is used.

let noerr = Command::new("myprog")
    .subcommand_negates_reqs(true)
    .arg(Arg::new("opt").required(true))
    .subcommand(Command::new("test"))
    .try_get_matches_from(vec![
        "myprog", "test"
    ]);
assert!(noerr.is_ok());

Multiple-personality program dispatched on the binary name (argv[0])

A “multicall” executable is a single executable that contains a variety of applets, and decides which applet to run based on the name of the file. The executable can be called from different names by creating hard links or symbolic links to it.

This is desirable for:

  • Easy distribution, a single binary that can install hardlinks to access the different personalities.
  • Minimal binary size by sharing common code (e.g. standard library, clap)
  • Custom shells or REPLs where there isn’t a single top-level command

Setting multicall will cause

  • argv[0] to be stripped to the base name and parsed as the first argument, as if Command::no_binary_name was set.
  • Help and errors to report subcommands as if they were the top-level command

When the subcommand is not present, there are several strategies you may employ, depending on your needs:

  • Let the error percolate up normally
  • Print a specialized error message using the Error::context
  • Print the help but this might be ambiguous
  • Disable multicall and re-parse it
  • Disable multicall and re-parse it with a specific subcommand

When detecting the error condition, the ErrorKind isn’t sufficient as a sub-subcommand might report the same error. Enable allow_external_subcommands if you want to specifically get the unrecognized binary name.

NOTE: Multicall can’t be used with no_binary_name since they interpret the command name in incompatible ways.

NOTE: The multicall command cannot have arguments.

NOTE: Applets are slightly semantically different from subcommands, so it’s recommended to use Command::subcommand_help_heading and Command::subcommand_value_name to change the descriptive text as above.

Examples

hostname is an example of a multicall executable. Both hostname and dnsdomainname are provided by the same executable and which behaviour to use is based on the executable file name.

This is desirable when the executable has a primary purpose but there is related functionality that would be convenient to provide and implement it to be in the same executable.

The name of the cmd is essentially unused and may be the same as the name of a subcommand.

The names of the immediate subcommands of the Command are matched against the basename of the first argument, which is conventionally the path of the executable.

This does not allow the subcommand to be passed as the first non-path argument.

let mut cmd = Command::new("hostname")
    .multicall(true)
    .subcommand(Command::new("hostname"))
    .subcommand(Command::new("dnsdomainname"));
let m = cmd.try_get_matches_from_mut(&["/usr/bin/hostname", "dnsdomainname"]);
assert!(m.is_err());
assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
let m = cmd.get_matches_from(&["/usr/bin/dnsdomainname"]);
assert_eq!(m.subcommand_name(), Some("dnsdomainname"));

Busybox is another common example of a multicall executable with a subcommmand for each applet that can be run directly, e.g. with the cat applet being run by running busybox cat, or with cat as a link to the busybox binary.

This is desirable when the launcher program has additional options or it is useful to run the applet without installing a symlink e.g. to test the applet without installing it or there may already be a command of that name installed.

To make an applet usable as both a multicall link and a subcommand the subcommands must be defined both in the top-level Command and as subcommands of the “main” applet.

fn applet_commands() -> [Command; 2] {
    [Command::new("true"), Command::new("false")]
}
let mut cmd = Command::new("busybox")
    .multicall(true)
    .subcommand(
        Command::new("busybox")
            .subcommand_value_name("APPLET")
            .subcommand_help_heading("APPLETS")
            .subcommands(applet_commands()),
    )
    .subcommands(applet_commands());
// When called from the executable's canonical name
// its applets can be matched as subcommands.
let m = cmd.try_get_matches_from_mut(&["/usr/bin/busybox", "true"]).unwrap();
assert_eq!(m.subcommand_name(), Some("busybox"));
assert_eq!(m.subcommand().unwrap().1.subcommand_name(), Some("true"));
// When called from a link named after an applet that applet is matched.
let m = cmd.get_matches_from(&["/usr/bin/true"]);
assert_eq!(m.subcommand_name(), Some("true"));
Examples found in repository?
examples/multicall-hostname.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
More examples
Hide additional examples
examples/repl.rs (line 65)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/multicall-busybox.rs (line 15)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}

Sets the value name used for subcommands when printing usage and help.

By default, this is “COMMAND”.

See also Command::subcommand_help_heading

Examples
Command::new("myprog")
    .subcommand(Command::new("sub1"))
    .print_help()

will produce

myprog

Usage: myprog [COMMAND]

Commands:
    help    Print this message or the help of the given subcommand(s)
    sub1

Options:
    -h, --help       Print help information
    -V, --version    Print version information

but usage of subcommand_value_name

Command::new("myprog")
    .subcommand(Command::new("sub1"))
    .subcommand_value_name("THING")
    .print_help()

will produce

myprog

Usage: myprog [THING]

Commands:
    help    Print this message or the help of the given subcommand(s)
    sub1

Options:
    -h, --help       Print help information
    -V, --version    Print version information
Examples found in repository?
examples/multicall-hostname.rs (line 7)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
More examples
Hide additional examples
examples/repl.rs (line 68)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/multicall-busybox.rs (line 19)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}

Sets the help heading used for subcommands when printing usage and help.

By default, this is “Commands”.

See also Command::subcommand_value_name

Examples
Command::new("myprog")
    .subcommand(Command::new("sub1"))
    .print_help()

will produce

myprog

Usage: myprog [COMMAND]

Commands:
    help    Print this message or the help of the given subcommand(s)
    sub1

Options:
    -h, --help       Print help information
    -V, --version    Print version information

but usage of subcommand_help_heading

Command::new("myprog")
    .subcommand(Command::new("sub1"))
    .subcommand_help_heading("Things")
    .print_help()

will produce

myprog

Usage: myprog [COMMAND]

Things:
    help    Print this message or the help of the given subcommand(s)
    sub1

Options:
    -h, --help       Print help information
    -V, --version    Print version information
Examples found in repository?
examples/multicall-hostname.rs (line 8)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
        .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));

    match cmd.get_matches().subcommand_name() {
        Some("hostname") => println!("www"),
        Some("dnsdomainname") => println!("example.com"),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}
More examples
Hide additional examples
examples/repl.rs (line 69)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
fn cli() -> Command {
    // strip out usage
    const PARSER_TEMPLATE: &str = "\
        {all-args}
    ";
    // strip out name/version
    const APPLET_TEMPLATE: &str = "\
        {about-with-newline}\n\
        {usage-heading}\n    {usage}\n\
        \n\
        {all-args}{after-help}\
    ";

    Command::new("repl")
        .multicall(true)
        .arg_required_else_help(true)
        .subcommand_required(true)
        .subcommand_value_name("APPLET")
        .subcommand_help_heading("APPLETS")
        .help_template(PARSER_TEMPLATE)
        .subcommand(
            Command::new("ping")
                .about("Get a response")
                .help_template(APPLET_TEMPLATE),
        )
        .subcommand(
            Command::new("quit")
                .alias("exit")
                .about("Quit the REPL")
                .help_template(APPLET_TEMPLATE),
        )
}
examples/multicall-busybox.rs (line 20)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
fn main() {
    let cmd = Command::new(env!("CARGO_CRATE_NAME"))
        .multicall(true)
        .subcommand(
            Command::new("busybox")
                .arg_required_else_help(true)
                .subcommand_value_name("APPLET")
                .subcommand_help_heading("APPLETS")
                .arg(
                    Arg::new("install")
                        .long("install")
                        .help("Install hardlinks for all subcommands in path")
                        .exclusive(true)
                        .action(ArgAction::Set)
                        .default_missing_value("/usr/local/bin")
                        .value_parser(value_parser!(PathBuf)),
                )
                .subcommands(applet_commands()),
        )
        .subcommands(applet_commands());

    let matches = cmd.get_matches();
    let mut subcommand = matches.subcommand();
    if let Some(("busybox", cmd)) = subcommand {
        if cmd.contains_id("install") {
            unimplemented!("Make hardlinks to the executable here");
        }
        subcommand = cmd.subcommand();
    }
    match subcommand {
        Some(("false", _)) => exit(1),
        Some(("true", _)) => exit(0),
        _ => unreachable!("parser should ensure only valid subcommand names are used"),
    }
}

Get the name of the binary.

Get the name of the binary.

Set binary name. Uses &mut self instead of self.

Get the name of the cmd.

Get the version of the cmd.

Get the long version of the cmd.

Get the authors of the cmd.

Get the short flag of the subcommand.

Get the long flag of the subcommand.

Get the help message specified via Command::about.

Get the help message specified via Command::long_about.

Get the custom section heading specified via Command::next_help_heading.

Iterate through the visible aliases for this subcommand.

Iterate through the visible short aliases for this subcommand.

Iterate through the visible long aliases for this subcommand.

Iterate through the set of all the aliases for this subcommand, both visible and hidden.

Iterate through the set of all the short aliases for this subcommand, both visible and hidden.

Iterate through the set of all the long aliases for this subcommand, both visible and hidden.

Should we color the output?

Iterate through the set of subcommands, getting a reference to each.

Iterate through the set of subcommands, getting a mutable reference to each.

Returns true if this Command has subcommands.

Returns the help heading for listing subcommands.

Returns the subcommand value name.

Returns the help heading for listing subcommands.

Returns the help heading for listing subcommands.

Returns the help heading for listing subcommands.

Returns the help heading for listing subcommands.

Find subcommand such that its name or one of aliases equals name.

This does not recurse through subcommands of subcommands.

Find subcommand such that its name or one of aliases equals name, returning a mutable reference to the subcommand.

This does not recurse through subcommands of subcommands.

Iterate through the set of groups.

Iterate through the set of arguments.

Iterate through the positionals arguments.

Iterate through the options.

Get a list of all arguments the given argument conflicts with.

If the provided argument is declared as global, the conflicts will be determined based on the propagation rules of global arguments.

Panics

If the given arg contains a conflict with an argument that is unknown to this Command.

Report whether Command::no_binary_name is set

Report whether Command::disable_version_flag is set

Report whether Command::propagate_version is set

Report whether Command::next_line_help is set

Report whether Command::disable_help_flag is set

Report whether Command::disable_help_subcommand is set

Report whether Command::disable_colored_help is set

Report whether Command::arg_required_else_help is set

Report whether Command::allow_missing_positional is set

Report whether Command::hide is set

Report whether Command::subcommand_required is set

Configured parser for values passed to an external subcommand

Example
let cmd = clap::Command::new("raw")
    .external_subcommand_value_parser(clap::value_parser!(String));
let value_parser = cmd.get_external_subcommand_value_parser();
println!("{:?}", value_parser);

Report whether Command::subcommand_negates_reqs is set

Report whether Command::multicall is set

Prepare for introspecting on all included Commands

Call this on the top-level Command when done building and before reading state for cases like completions, custom help output, etc.

Trait Implementations

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Formats the value using the given formatter. Read more
Converts to this type from the input type.
The returned type after indexing.
Performs the indexing (container[index]) operation. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.