๐ nanoargs
A lightweight, zero-dependency argument parser for Rust.
Part of the nano crate family โ minimal, zero-dependency building blocks for Rust:
- nanocolor โ terminal colors and styles
- nanospinner โ terminal spinners
- nanoprogress โ progress bars
- nanologger โ minimal logger
- nanotime โ time utilities
- nanoargs โ argument parser
Everything you'd expect from a CLI parser โ flags, options, subcommands, help generation, env fallback, typed parsing โ with zero dependencies.
Why nanoargs?
clap pulls in 10+ transitive dependencies. pico-args and lexopt are zero-dep but skip help generation, env var fallback, and subcommands. nanoargs covers the gap: everything you'd reach for clap for in a typical CLI, with zero dependencies.
If your CLI needs advanced features like derive macros, argument groups, shell completions, or value validation, clap and bpaf are great choices. nanoargs is for the common, lightweight case.
| Feature | nanoargs |
clap |
bpaf |
pico-args |
lexopt |
|---|---|---|---|---|---|
| Dependencies (transitive) | 0 | ~12* | 5** | 0 | 0 |
| Auto help text | โ | โ | โ | โ | โ |
Version flag (--version) |
โ | โ | โ | โ | โ |
| Env var fallback | โ | โ | โ | โ | โ |
| Multi-value options | โ | โ | โ | โ | โ |
| Subcommands | โ | โ | โ | โโ | โโ |
Combined short flags (-abc) |
โ | โ | โ | โโก | โ |
| Default values | โ | โ | โ | โ | โ |
| Required args | โ | โ | โ | โ | โ |
| Hidden args | โ | โ | โ | โ | โ |
| Colored help | โยง | โ | โยง | โ | โ |
| Derive macros | โ | โ | โ | โ | โ |
| Shell completions | โ | โ | โยง | โ | โ |
| Other advanced features | โ | โ | โ | โ | โ |
* clap with default features. With derive, ~17 total.
** bpaf combinatoric API has 0 deps. With derive, 5 total (bpaf_derive + syn tree).
โ No built-in support. Achievable manually by matching on positional tokens.
โก Via opt-in cargo features (combined-flags, short-space-opt).
ยง Via opt-in cargo features.
Quick Start (full demo)
use ;
Or for throwaway scripts, see Schema-Free Parsing below.
Usage
Flags (example)
Boolean switches toggled by presence.
let parser = new
.flag
.flag
.build;
Options (example)
Key-value arguments with fluent modifiers. Construct an Opt with Opt::new(), chain .placeholder(), .desc(), .short(), .required(), .default(), .env(), .multi(), or .hidden() as needed, then pass it to .option().
let parser = new
.option
.option
.option
.option
.build;
Environment Variable Fallback (example)
Options can fall back to environment variables when not provided on the command line. Chain .env() on the Opt builder. The resolution order is: CLI value โ env var โ default โ error (if required).
let parser = new
.option
.option
.option
.build;
# CLI value takes priority
# Falls back to env var when CLI option is omitted
MYAPP_OUTPUT=from_env.txt
# Falls back to default when both CLI and env var are absent
Help text automatically shows the associated env var:
Options:
-l, --log-level <LEVEL> Log level [env: MYAPP_LOG_LEVEL]
-o, --output <FILE> Output file (required) [env: MYAPP_OUTPUT]
-f, --format <FMT> Output format [default: text] [env: MYAPP_FORMAT]
Positionals (example)
Unnamed arguments collected in order. Chain .required() on the Pos builder to make a positional mandatory.
let parser = new
.positional
.positional
.build;
Hidden Arguments
Flags and options can be marked as hidden โ they parse normally but are excluded from --help output. Useful for internal, debug, or deprecated arguments.
let parser = new
.flag
.option
.flag
.build;
# Hidden arguments work on the command line
# But --help only shows --verbose
The .hidden() modifier is available on both Flag and Opt, and can be called in any order relative to other modifiers.
Combined Short Flags (example)
Combine multiple short flags into a single token. The parser walks characters left-to-right against the registered schema.
let parser = new
.flag
.flag
.flag
.option
.build;
# Combined flags
# Attached option value
# Flags + option in one token
When the parser encounters an option character during the walk, it claims all remaining characters as the value. If none remain, it consumes the next argument token.
Subcommands (example)
Git-style subcommands, each with their own flags, options, and positionals. Global flags are parsed before the subcommand token.
let build_parser = new
.name
.description
.flag
.build;
let test_parser = new
.name
.description
.flag
.build;
let parser = new
.name
.description
.flag
.subcommand
.subcommand
.build;
Note: When subcommands are registered, the first bare (non-flag/option) token is always treated as the subcommand name. Parent-level positional arguments are not supported alongside subcommands โ this matches git-style CLI conventions.
# Supported โ global flags before the subcommand: # NOT supported โ positionals before the subcommand:
Access results via subcommand() and subcommand_result():
if let Some = result.subcommand
Version Flag (example)
Built-in --version / -V support. Set a version string on the builder and the parser handles the rest.
let parser = new
.name
.version
.flag
.build
.unwrap;
The -V short flag is reserved when a version is configured โ the builder will reject any user-registered flag or option that uses 'V' as its short form. When no version is set, --version and -V are treated as unknown arguments, and 'V' is available for user flags.
When both --help and --version appear, whichever comes first wins. After --, both are treated as positionals.
Typed Parsing
Parse option values into any type implementing FromStr. Convenience helpers collapse the common three-way match into a single call:
// With a default fallback โ returns the parsed value, or the default if absent/unparseable
let jobs: u32 = result.get_option_or_default;
// With a lazy default โ closure only runs if needed
let jobs: u32 = result.get_option_or;
// Required with Result โ use the ? operator
let jobs: u32 = result.get_option_required?;
For fine-grained control over parse errors, the original accessor is still available:
match result.
Help Text (example)
Auto-generated from your schema. Triggered by --help or -h.
)
Double-Dash Separator
Everything after -- is treated as a positional, even if it looks like a flag or option.
# positionals: ["--not-a-flag", "-abc"]
Colored Help (opt-in)
Enable the color feature to get ANSI-colored help text and error messages via nanocolor:
[]
= { = "0.1", = ["color"] }
When enabled, section headers are bold yellow, flag/option names are green, placeholders are cyan, and metadata like [default: ...] is dim. Error messages get a bold red error: prefix. Color is automatically suppressed when NO_COLOR is set or output is not a TTY (handled by nanocolor). Without the feature, the crate remains zero-dependency and output is unchanged.
Error Handling (example)
match parser.parse
Schema-Free Parsing for Quick Scripts
parse_loose() skips the schema entirely โ useful for throwaway scripts where defining flags and options feels like overkill.
It uses a heuristic to guess whether --key is a flag or an option: if the next token doesn't start with -, it's consumed as the value.
When it works well: simple scripts with clear flag/option boundaries (--verbose --output file.txt).
When it doesn't: --output -v silently treats --output as a flag (not an option), because -v starts with -. If your CLI has options that could receive flag-like values, use ArgBuilder instead.
API Reference
See the full API docs on docs.rs.
Examples
| Example | Description | Run |
|---|---|---|
| flags | Boolean flags | cargo run --example flags -- -v --dry-run |
| options | Options with defaults and required | cargo run --example options -- -o=out.txt -j 8 |
| positionals | Positional arguments | cargo run --example positionals -- file.txt extra |
| short_flags | Combined short flags and attached values | cargo run --example short_flags -- -abcw10 |
| help_text | Auto-generated help | cargo run --example help_text -- --help |
| error_handling | Error handling patterns | cargo run --example error_handling |
| version_flag | Built-in version flag | cargo run --example version_flag -- --version |
| env_fallback | Environment variable fallback | cargo run --example env_fallback -- --output out.txt |
| subcommands | Git-style subcommands | cargo run --example subcommands -- build --release |
| full_demo | All features together | cargo run --example full_demo -- -vj8 -o=result.txt input.txt |
Contributing
Contributions are welcome. To get started:
- Fork the repository
- Create a feature branch (
git checkout -b my-feature) - Make your changes
- Run the tests:
cargo test - Submit a pull request
Please keep changes minimal and focused. This crate's goal is to stay small and dependency-free.
License
This project is licensed under the MIT License.