Args
Successful Parsing
Simple Arguments
Parse a struct with flags, options, and positional arguments.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-v", "-j", "4", "input.txt", "output.txt"])
Success
SimpleArgs {
verbose: true,
jobs: Option<usize>::Some(4),
input: "input.txt",
output: Option<String>::Some("output.txt"),
}
Attached Short Flag Value
Short flags can have their values attached directly without a space.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-j4", "input.txt"])
Success
SimpleArgs {
verbose: false,
jobs: Option<usize>::Some(4),
input: "input.txt",
output: Option<String>::None,
}
Boolean Flag with Explicit Value
Boolean flags can be explicitly set to true or false using =.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["--verbose=true", "input.txt"])
Success
SimpleArgs {
verbose: true,
jobs: Option<usize>::None,
input: "input.txt",
output: Option<String>::None,
}
Subcommands
Parse a CLI with subcommands, each with their own arguments.
Target Type
/// Git-like CLI with subcommands. #[derive(Facet)] struct GitLikeArgs { /// Show version information #[facet(args::named)] version: bool, /// Git command to run #[facet(args::subcommand)] command: GitCommand, } /// Available commands #[derive(Facet)] #[repr(u8)] enum GitCommand { /// Clone a repository into a new directory Clone { /// The repository URL to clone #[facet(args::positional)] url: String, /// Directory to clone into #[facet(args::positional)] directory: Option<String>, /// Clone only the specified branch #[facet(args::named, args::short)] branch: Option<String>, /// Create a shallow clone with limited history #[facet(args::named)] depth: Option<usize>, }, /// Show the working tree status Status { /// Show short-format output #[facet(args::named, args::short)] short: bool, /// Show the branch even in short-format #[facet(args::named, args::short)] branch: bool, }, /// Manage set of tracked repositories Remote { /// Remote action to perform #[facet(args::subcommand)] action: RemoteAction, }, } /// Remote management commands #[derive(Facet)] #[repr(u8)] enum RemoteAction { /// Add a remote named <name> for the repository at <url> Add { /// Name of the remote #[facet(args::positional)] name: String, /// URL of the remote repository #[facet(args::positional)] url: String, }, /// Remove the remote named <name> rm { /// Name of the remote to remove #[facet(args::positional)] name: String, }, /// List all remotes ls { /// Show remote URLs after names #[facet(args::named, args::short)] verbose: bool, }, }
Rust Input
from_slice(&["clone", "--branch", "main", "https://github.com/user/repo"])
Success
GitLikeArgs {
version: false,
command: GitCommand::Clone {
url: "https://github.com/user/repo",
directory: Option<String>::None,
branch: Option<String>::Some("main"),
depth: Option<usize>::None,
},
}
Nested Subcommands
Parse deeply nested subcommands like git remote add.
Target Type
/// Git-like CLI with subcommands. #[derive(Facet)] struct GitLikeArgs { /// Show version information #[facet(args::named)] version: bool, /// Git command to run #[facet(args::subcommand)] command: GitCommand, } /// Available commands #[derive(Facet)] #[repr(u8)] enum GitCommand { /// Clone a repository into a new directory Clone { /// The repository URL to clone #[facet(args::positional)] url: String, /// Directory to clone into #[facet(args::positional)] directory: Option<String>, /// Clone only the specified branch #[facet(args::named, args::short)] branch: Option<String>, /// Create a shallow clone with limited history #[facet(args::named)] depth: Option<usize>, }, /// Show the working tree status Status { /// Show short-format output #[facet(args::named, args::short)] short: bool, /// Show the branch even in short-format #[facet(args::named, args::short)] branch: bool, }, /// Manage set of tracked repositories Remote { /// Remote action to perform #[facet(args::subcommand)] action: RemoteAction, }, } /// Remote management commands #[derive(Facet)] #[repr(u8)] enum RemoteAction { /// Add a remote named <name> for the repository at <url> Add { /// Name of the remote #[facet(args::positional)] name: String, /// URL of the remote repository #[facet(args::positional)] url: String, }, /// Remove the remote named <name> rm { /// Name of the remote to remove #[facet(args::positional)] name: String, }, /// List all remotes ls { /// Show remote URLs after names #[facet(args::named, args::short)] verbose: bool, }, }
Rust Input
from_slice(&["remote", "add", "origin", "https://github.com/user/repo"])
Success
GitLikeArgs {
version: false,
command: GitCommand::Remote {
action: RemoteAction::Add {
name: "origin",
url: "https://github.com/user/repo",
},
},
}
Help Generation
Simple Help
Auto-generated help text from struct definition and doc comments.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Output
mytool 1.0.0 A simple CLI tool for file processing. USAGE: mytool [OPTIONS] <INPUT> [OUTPUT] ARGUMENTS: <INPUT> Input file to process <OUTPUT> Output file (defaults to stdout) OPTIONS: -v, --verbose Enable verbose output -j, --jobs <OPTION> Number of parallel jobs to run
Help with Subcommands
Help text automatically lists available subcommands with descriptions.
Target Type
/// Git-like CLI with subcommands. #[derive(Facet)] struct GitLikeArgs { /// Show version information #[facet(args::named)] version: bool, /// Git command to run #[facet(args::subcommand)] command: GitCommand, } /// Available commands #[derive(Facet)] #[repr(u8)] enum GitCommand { /// Clone a repository into a new directory Clone { /// The repository URL to clone #[facet(args::positional)] url: String, /// Directory to clone into #[facet(args::positional)] directory: Option<String>, /// Clone only the specified branch #[facet(args::named, args::short)] branch: Option<String>, /// Create a shallow clone with limited history #[facet(args::named)] depth: Option<usize>, }, /// Show the working tree status Status { /// Show short-format output #[facet(args::named, args::short)] short: bool, /// Show the branch even in short-format #[facet(args::named, args::short)] branch: bool, }, /// Manage set of tracked repositories Remote { /// Remote action to perform #[facet(args::subcommand)] action: RemoteAction, }, } /// Remote management commands #[derive(Facet)] #[repr(u8)] enum RemoteAction { /// Add a remote named <name> for the repository at <url> Add { /// Name of the remote #[facet(args::positional)] name: String, /// URL of the remote repository #[facet(args::positional)] url: String, }, /// Remove the remote named <name> rm { /// Name of the remote to remove #[facet(args::positional)] name: String, }, /// List all remotes ls { /// Show remote URLs after names #[facet(args::named, args::short)] verbose: bool, }, }
Rust Output
git 2.40.0 Git-like CLI with subcommands. USAGE: git [OPTIONS] <COMMAND> OPTIONS: --version Show version information COMMANDS: clone Clone a repository into a new directory status Show the working tree status remote Manage set of tracked repositories
Shell Completions
Bash Completions
Generated Bash completion script for tab-completion support.
Target Type
/// A build tool configuration #[derive(Facet)] struct BuildArgs { /// Build in release mode with optimizations #[facet(args::named, args::short)] release: bool, /// Number of parallel jobs #[facet(args::named, args::short)] jobs: Option<usize>, /// Package to build #[facet(args::named, args::short)] package: Option<String>, /// Build all packages in the workspace #[facet(args::named)] workspace: bool, /// Space-separated list of features to enable #[facet(args::named, args::short)] features: Option<String>, /// Target triple to build for #[facet(args::named)] target: Option<String>, }
Rust Output
_cargo-build() { local cur prev words cword _init_completion || return local commands="" local flags="" flags="--release -r --jobs -j --package -p --workspace --features -F --target" case "$prev" in # Add cases for flags that take values *) ;; esac if [[ "$cur" == -* ]]; then COMPREPLY=($(compgen -W "$flags" -- "$cur")) elif [[ -n "$commands" ]]; then COMPREPLY=($(compgen -W "$commands" -- "$cur")) fi } complete -F _cargo-build cargo-build
Zsh Completions
Generated Zsh completion script with argument descriptions.
Target Type
/// A build tool configuration #[derive(Facet)] struct BuildArgs { /// Build in release mode with optimizations #[facet(args::named, args::short)] release: bool, /// Number of parallel jobs #[facet(args::named, args::short)] jobs: Option<usize>, /// Package to build #[facet(args::named, args::short)] package: Option<String>, /// Build all packages in the workspace #[facet(args::named)] workspace: bool, /// Space-separated list of features to enable #[facet(args::named, args::short)] features: Option<String>, /// Target triple to build for #[facet(args::named)] target: Option<String>, }
Rust Output
#compdef cargo-build _cargo-build() { local -a commands local -a options options=( '-r[Build in release mode with optimizations]' '--release[Build in release mode with optimizations]' '-j[Number of parallel jobs]' '--jobs[Number of parallel jobs]' '-p[Package to build]' '--package[Package to build]' '--workspace[Build all packages in the workspace]' '-F[Space-separated list of features to enable]' '--features[Space-separated list of features to enable]' '--target[Target triple to build for]' ) _arguments $options } _cargo-build "$@"
Fish Completions
Generated Fish shell completion script.
Target Type
/// A build tool configuration #[derive(Facet)] struct BuildArgs { /// Build in release mode with optimizations #[facet(args::named, args::short)] release: bool, /// Number of parallel jobs #[facet(args::named, args::short)] jobs: Option<usize>, /// Package to build #[facet(args::named, args::short)] package: Option<String>, /// Build all packages in the workspace #[facet(args::named)] workspace: bool, /// Space-separated list of features to enable #[facet(args::named, args::short)] features: Option<String>, /// Target triple to build for #[facet(args::named)] target: Option<String>, }
Rust Output
# Fish completion for cargo-build complete -c cargo-build -s r -l release -d 'Build in release mode with optimizations' complete -c cargo-build -s j -l jobs -d 'Number of parallel jobs' complete -c cargo-build -s p -l package -d 'Package to build' complete -c cargo-build -l workspace -d 'Build all packages in the workspace' complete -c cargo-build -s F -l features -d 'Space-separated list of features to enable' complete -c cargo-build -l target -d 'Target triple to build for'
Error Diagnostics
Unknown Flag
Error when an unrecognized flag is provided.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["--verbos", "input.txt"])
Error
args::unknown_long_flag
× Could not parse CLI arguments
╭────
1 │ --verbos input.txt
· ────┬───
· ╰── unknown flag `--verbos`
╰────
help: did you mean `--verbose`?
Unknown Flag with Suggestion
When the flag name is close to a valid one, a suggestion is offered.
Target Type
/// A build tool configuration #[derive(Facet)] struct BuildArgs { /// Build in release mode with optimizations #[facet(args::named, args::short)] release: bool, /// Number of parallel jobs #[facet(args::named, args::short)] jobs: Option<usize>, /// Package to build #[facet(args::named, args::short)] package: Option<String>, /// Build all packages in the workspace #[facet(args::named)] workspace: bool, /// Space-separated list of features to enable #[facet(args::named, args::short)] features: Option<String>, /// Target triple to build for #[facet(args::named)] target: Option<String>, }
Rust Input
from_slice(&["--releas"])
Error
args::unknown_long_flag
× Could not parse CLI arguments
╭────
1 │ --releas
· ────┬───
· ╰── unknown flag `--releas`
╰────
help: did you mean `--release`?
Invalid Short Flag
Boolean short flags cannot have trailing characters attached.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-vxyz", "input.txt"])
Error
args::unknown_short_flag
× Could not parse CLI arguments
╭────
1 │ -vxyz input.txt
· ──┬──
· ╰── unknown flag `-vxyz`
╰────
help: `-vxyz` is `--verbose`
Triple Dash Flag
Flags with too many dashes are rejected.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["---verbose", "input.txt"])
Error
args::unknown_long_flag
× Could not parse CLI arguments
╭────
1 │ ---verbose input.txt
· ─────┬────
· ╰── unknown flag `---verbose`
╰────
help: available options:
-v, --verbose Enable verbose output
-j, --jobs Number of parallel jobs to run
<input> Input file to process
<output> Output file (defaults to stdout)
Single Dash with Long Name
Long flag names require double dashes.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-verbose", "input.txt"])
Error
args::unknown_short_flag
× Could not parse CLI arguments
╭────
1 │ -verbose input.txt
· ────┬───
· ╰── unknown flag `-verbose`
╰────
help: `-verbose` is `--verbose`
Missing Value
Error when a flag that requires a value doesn't get one.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-j"])
Error
args::expected_value
× Could not parse CLI arguments
╭────
1 │ -j
· ─┬
· ╰── expected `usize` value
╰────
help: provide a value after the flag
Missing Required Argument
Error when a required positional argument is not provided.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-v"])
Error
args::missing_argument
× Could not parse CLI arguments
╭────
1 │ -v
╰────
help: provide a value for `<input>`
Unexpected Positional Argument
Error when a positional argument is provided but not expected.
Target Type
/// A build tool configuration #[derive(Facet)] struct BuildArgs { /// Build in release mode with optimizations #[facet(args::named, args::short)] release: bool, /// Number of parallel jobs #[facet(args::named, args::short)] jobs: Option<usize>, /// Package to build #[facet(args::named, args::short)] package: Option<String>, /// Build all packages in the workspace #[facet(args::named)] workspace: bool, /// Space-separated list of features to enable #[facet(args::named, args::short)] features: Option<String>, /// Target triple to build for #[facet(args::named)] target: Option<String>, }
Rust Input
from_slice(&["extra", "--release"])
Error
args::unexpected_positional
× Could not parse CLI arguments
╭────
1 │ extra --release
· ──┬──
· ╰── unexpected positional argument
╰────
help: available options:
-r, --release Build in release mode with optimizations
-j, --jobs Number of parallel jobs
-p, --package Package to build
--workspace Build all packages in the workspace
-F, --features Space-separated list of features to enable
--target Target triple to build for
Unknown Subcommand
Error when an unrecognized subcommand is provided, with available options listed.
Target Type
/// Git-like CLI with subcommands. #[derive(Facet)] struct GitLikeArgs { /// Show version information #[facet(args::named)] version: bool, /// Git command to run #[facet(args::subcommand)] command: GitCommand, } /// Available commands #[derive(Facet)] #[repr(u8)] enum GitCommand { /// Clone a repository into a new directory Clone { /// The repository URL to clone #[facet(args::positional)] url: String, /// Directory to clone into #[facet(args::positional)] directory: Option<String>, /// Clone only the specified branch #[facet(args::named, args::short)] branch: Option<String>, /// Create a shallow clone with limited history #[facet(args::named)] depth: Option<usize>, }, /// Show the working tree status Status { /// Show short-format output #[facet(args::named, args::short)] short: bool, /// Show the branch even in short-format #[facet(args::named, args::short)] branch: bool, }, /// Manage set of tracked repositories Remote { /// Remote action to perform #[facet(args::subcommand)] action: RemoteAction, }, } /// Remote management commands #[derive(Facet)] #[repr(u8)] enum RemoteAction { /// Add a remote named <name> for the repository at <url> Add { /// Name of the remote #[facet(args::positional)] name: String, /// URL of the remote repository #[facet(args::positional)] url: String, }, /// Remove the remote named <name> rm { /// Name of the remote to remove #[facet(args::positional)] name: String, }, /// List all remotes ls { /// Show remote URLs after names #[facet(args::named, args::short)] verbose: bool, }, }
Rust Input
from_slice(&["clon", "https://example.com"])
Error
args::unknown_subcommand
× Could not parse CLI arguments
╭────
1 │ clon https://example.com
· ──┬─
· ╰── unknown subcommand `clon`
╰────
help: did you mean `clone`?
Missing Subcommand
Error when a required subcommand is not provided.
Target Type
/// Git-like CLI with subcommands. #[derive(Facet)] struct GitLikeArgs { /// Show version information #[facet(args::named)] version: bool, /// Git command to run #[facet(args::subcommand)] command: GitCommand, } /// Available commands #[derive(Facet)] #[repr(u8)] enum GitCommand { /// Clone a repository into a new directory Clone { /// The repository URL to clone #[facet(args::positional)] url: String, /// Directory to clone into #[facet(args::positional)] directory: Option<String>, /// Clone only the specified branch #[facet(args::named, args::short)] branch: Option<String>, /// Create a shallow clone with limited history #[facet(args::named)] depth: Option<usize>, }, /// Show the working tree status Status { /// Show short-format output #[facet(args::named, args::short)] short: bool, /// Show the branch even in short-format #[facet(args::named, args::short)] branch: bool, }, /// Manage set of tracked repositories Remote { /// Remote action to perform #[facet(args::subcommand)] action: RemoteAction, }, } /// Remote management commands #[derive(Facet)] #[repr(u8)] enum RemoteAction { /// Add a remote named <name> for the repository at <url> Add { /// Name of the remote #[facet(args::positional)] name: String, /// URL of the remote repository #[facet(args::positional)] url: String, }, /// Remove the remote named <name> rm { /// Name of the remote to remove #[facet(args::positional)] name: String, }, /// List all remotes ls { /// Show remote URLs after names #[facet(args::named, args::short)] verbose: bool, }, }
Rust Input
from_slice(&["--version"])
Error
args::missing_subcommand
× Could not parse CLI arguments
╭────
1 │ --version
╰────
help: available subcommands:
clone Clone a repository into a new directory
status Show the working tree status
remote Manage set of tracked repositories
Missing Nested Subcommand Argument
Error when a required argument in a nested subcommand is missing.
Target Type
/// Git-like CLI with subcommands. #[derive(Facet)] struct GitLikeArgs { /// Show version information #[facet(args::named)] version: bool, /// Git command to run #[facet(args::subcommand)] command: GitCommand, } /// Available commands #[derive(Facet)] #[repr(u8)] enum GitCommand { /// Clone a repository into a new directory Clone { /// The repository URL to clone #[facet(args::positional)] url: String, /// Directory to clone into #[facet(args::positional)] directory: Option<String>, /// Clone only the specified branch #[facet(args::named, args::short)] branch: Option<String>, /// Create a shallow clone with limited history #[facet(args::named)] depth: Option<usize>, }, /// Show the working tree status Status { /// Show short-format output #[facet(args::named, args::short)] short: bool, /// Show the branch even in short-format #[facet(args::named, args::short)] branch: bool, }, /// Manage set of tracked repositories Remote { /// Remote action to perform #[facet(args::subcommand)] action: RemoteAction, }, } /// Remote management commands #[derive(Facet)] #[repr(u8)] enum RemoteAction { /// Add a remote named <name> for the repository at <url> Add { /// Name of the remote #[facet(args::positional)] name: String, /// URL of the remote repository #[facet(args::positional)] url: String, }, /// Remove the remote named <name> rm { /// Name of the remote to remove #[facet(args::positional)] name: String, }, /// List all remotes ls { /// Show remote URLs after names #[facet(args::named, args::short)] verbose: bool, }, }
Rust Input
from_slice(&["remote", "add", "origin"])
Error
args::missing_argument
× Could not parse CLI arguments
╭────
1 │ remote add origin
╰────
help: provide a value for `<url>`
Invalid Value Type
Error when a value cannot be parsed as the expected type.
Target Type
/// A simple CLI tool for file processing. #[derive(Facet)] struct SimpleArgs { /// Enable verbose output #[facet(args::named, args::short)] verbose: bool, /// Number of parallel jobs to run #[facet(args::named, args::short)] jobs: Option<usize>, /// Input file to process #[facet(args::positional)] input: String, /// Output file (defaults to stdout) #[facet(args::positional)] output: Option<String>, }
Rust Input
from_slice(&["-j", "not-a-number", "input.txt"])
Error
args::reflect_error
× Could not parse CLI arguments
╭────
1 │ -j not-a-number input.txt
· ──────┬─────
· ╰── invalid value for `usize`
╰────