pico-args

An ultra-simple, zero-dependency CLI arguments parser for Rust with a tiny binary footprint.

Library
Cargo
v0.5.0
646stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
33/100Needs Attention
Development Activity0
Maintenance0
Community44
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture78
Code Quality85
Innovation65
Learning Curve65

pico-args is a minimalist command-line argument parser for Rust, built around a single design goal: parse just enough to make CLIs usable without carrying the compile-time or binary-size overhead of larger frameworks. Instead of a declarative struct-based system, it exposes a streaming API against a Vec<OsString> that callers query directly for flags, key-value pairs, and free-standing arguments, removing each one as it is consumed.

With #![forbid(unsafe_code)] and zero required dependencies, the crate is deliberately restrained: no automatic help-text generation, no derive macros, no subcommand trees, only flags, options, positional arguments, and single-level subcommands. Optional Cargo features (eq-separator, short-space-opt, combined-flags) unlock GNU-style = separators, -w10 short-key value packing, and -abc flag combination, each adding only a small amount to the compiled binary. This makes it a common choice for CLI tools where binary size and compile time genuinely matter: embedded tooling, small utilities, or crates that want argument parsing without pulling in a heavier dependency tree.

What You Get

  • Flag, option, and free-argument parsing via a simple streaming API (contains, value_from_str, free_from_str)
  • Single-level subcommand support through Arguments::subcommand
  • Non-UTF-8 argument handling via *_os_str variants for OsString/OsStr values
  • Optional Cargo features (eq-separator, short-space-opt, combined-flags) to opt into GNU-style syntax without paying for it by default
  • #![forbid(unsafe_code)] guarantee with zero required dependencies

Common Use Cases

  • Small CLI utilities where binary size and compile time matter more than ergonomic derive macros
  • Embedded or resource-constrained Rust binaries that can’t afford a heavier parsing dependency tree
  • Tools that need to forward unrecognized arguments (—) to another program
  • Prototyping a CLI quickly before deciding whether a heavier framework is warranted
  • Libraries that expose a thin CLI wrapper and want to avoid forcing their dependency choices on consumers

Under The Hood

Architecture The crate is a single 808-line module (src/lib.rs) built around one struct, Arguments, wrapping a mutable Vec<OsString>. Every parsing method (contains, value_from_fn, free_from_fn, subcommand) searches this vector via index_of/index_of2 helpers and removes matched elements in place, so state mutates as the caller consumes arguments rather than through a declarative schema built up front. Error handling is centralized in a single Error enum with a Display implementation covering every failure mode (missing option, non-UTF-8 argument, parse failure). Optional Cargo features (eq-separator, short-space-opt, combined-flags) are implemented through #[cfg(feature = …)] blocks that swap in different find_value and index_of2 implementations at compile time rather than branching at runtime, keeping the default build lean. There is no plugin system, external dependency, or layering beyond this single module; the API surface is the architecture.

Tech Stack Pure Rust (edition 2018) with zero required dependencies, drawing only on std::ffi::{OsString, OsStr}, std::fmt, and std::str::FromStr. Optional Cargo features unlock additional parsing syntax at compile time rather than pulling in extra crates. Tests live in a single tests/tests.rs file exercising flags, values, free arguments, and subcommands; examples/app.rs and examples/dash_dash.rs demonstrate typical usage, including forwarding arguments to a wrapped process. A GitHub Actions Rust workflow (referenced by the README badge) runs CI on pushes. The deployment target is any Rust binary that pulls the crate in via Cargo.toml.

Code Quality tests/tests.rs contains substantial coverage relative to the size of the implementation, covering flags, key-value parsing, free-standing arguments, subcommands, and each feature-gated syntax variant. Error handling is fully typed via the Error enum, with debug_assert! used only to validate caller-provided key literals at development time rather than at runtime in release builds. #![forbid(unsafe_code)] and #![warn(missing_docs)] are enforced at the compiler level, and every public item carries a doc comment. Naming is consistent throughout (value_from_str, opt_value_from_str, values_from_str following a predictable pattern). No dedicated lint configuration is present in the repo beyond the built-in compiler warnings.

What Makes It Unique pico-args deliberately rejects the declarative, derive-macro-driven model that dominates Rust CLI parsing in favor of an imperative, streaming style where the caller queries a mutable argument list method by method. This trades auto-generated help and ergonomics for a near-zero binary and compile-time cost, using granular opt-in Cargo features, each adding only a small amount to the binary, rather than an all-or-nothing feature set. It is not a novel parsing algorithm, but the API design point of imperative “pull” parsing over declarative “define a struct” parsing is a genuine departure from the dominant pattern in the ecosystem.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search