structopt
Parse command-line arguments in Rust by deriving StructOpt directly on your own struct or enum.
Repository Health
Technical Analysis
structopt is a Rust crate that generates a command-line argument parser from a plain struct or enum definition, using a custom #[derive(StructOpt)] macro built on top of clap 2.x. Instead of hand-assembling clap::App and clap::Arg calls, developers annotate fields with #[structopt(...)] attributes and let the derive macro translate field types, doc comments, and attribute metadata into a full-featured CLI parser, including flags, options, positional arguments, subcommands, environment-variable fallbacks, and custom string parsers.
The project is explicitly in maintenance mode: once clap 3.0 folded structopt’s derive ergonomics into clap::Parser, the structopt README states no new features will be added, only bug fixes and doc improvements. It remains widely depended-upon in older Rust codebases and is a useful reference for understanding clap’s own derive API, which inherited most of structopt’s attribute syntax and type-magic conventions.
What You Get
- A
#[derive(StructOpt)]macro that turns struct fields into clap flags, options, and positional arguments based on their Rust type (bool,Option<T>,Vec<T>,Option<Option<T>>, etc.) - Automatic subcommand generation from enums, including nested subcommands, optional subcommands, external subcommand passthrough, and flattening multiple subcommand enums together
- Doc-comment-to-help-text translation, so
///comments on structs, enums, and fields becomeabout/long_about/help/long_helpclap output without extra annotations flattensupport for composing reusable argument groups (e.g. shared daemon options) across multiple top-level CLI structs- Environment-variable fallback (
env) with auto-derived variable names and an option to hide sensitive values from--helpoutput - Custom string parser hooks (
from_str,try_from_str,from_os_str,try_from_os_str,from_occurrences,from_flag) for types without aFromStrimplementation - “Raw method” escape hatches that pass any
clap::App/clap::Argbuilder method straight through the attribute syntax for cases the magical methods don’t cover
Common Use Cases
- Defining the argument struct for a Rust CLI binary without writing manual
clap::App::new(...).arg(...)builder chains - Building multi-command CLIs (in the style of
gitorcargo) where each subcommand is a variant of aStructOpt-derived enum - Sharing a common set of flags (verbosity, config path, etc.) across several subcommands via
#[structopt(flatten)] - Reading configuration values from environment variables as a fallback when a flag isn’t passed on the command line
- Maintaining legacy Rust CLI tools that predate clap 3’s built-in
derivefeature and haven’t been migrated yet
Under The Hood
Architecture The workspace splits into two crates: structopt (src/lib.rs, ~1,200 lines, mostly doctested docs) defines the public StructOpt trait (clap(), from_clap(), from_args(), from_iter(), from_args_safe()) plus a hidden StructOptInternal trait for subcommand augmentation, blanket-implemented for Box<T>; structopt-derive (structopt-derive/src/lib.rs, ~1,000 lines) is the proc-macro that does the real work, parsing #[structopt(...)] attributes (attrs.rs, ~685 lines) into an internal model, inspecting field types via ty.rs to decide whether a field becomes a flag, option, or positional arg, converting doc comments via doc_comments.rs, and emitting code that constructs a clap::App/clap::Arg tree at macro-expansion time.
Tech Stack Rust 2018 edition, built on clap 2.33 with default-features = false so consumers opt into clap’s color/suggestions/wrap_help features explicitly; lazy_static 1.4 is re-exported for macro-generated statics; the derive crate is version-pinned (=0.4.18) to stay in lockstep with the parent crate. Optional integration with the paw crate is feature-gated. Dev-dependencies (trybuild, rustversion, strum) support compile-fail attribute testing and enum-derive examples.
Code Quality The crate enforces #![deny(missing_docs)] and #![forbid(unsafe_code)] at the top of src/lib.rs. 27 integration test files under tests/ exercise flattening, subcommands, custom parsers, environment fallback, and doc-comment preprocessing, plus examples/ that double as documentation. The codebase is stable and effectively frozen by design (maintenance mode since clap 3 landed derive support), with the last commit in January 2024 reflecting deliberate low churn rather than neglect.
API Design The attribute DSL (short, long, flatten, subcommand, env, parse(...)) is compact once learned, and doc-comment-to-help-text translation removes a whole category of boilerplate, but the split between “magical methods” and “raw” passthrough methods (any clap::App/Arg method callable by name) adds a real learning curve documented at length in the crate’s own top-level docs. This attribute surface was influential enough that clap 3’s own derive(Parser) API inherited most of its conventions.
Used by 2 apps in this directory
Quickwit
Search · Monitoring
Cloud-native search engine for logs and traces, delivering sub-second search directly on S3, GCS, or Azure Blob storage at a fraction of Elasticsearch's cost.
WrenAI
Analytics · AI Agents · Data Engineering
Open-source GenBI engine that lets AI agents turn natural-language questions into governed SQL, charts, and shareable dashboards across 20+ data sources — no vendor lock-in, no black-box prompts.