structopt

Parse command-line arguments in Rust by deriving StructOpt directly on your own struct or enum.

Library
Cargo
v0.3.26
2,727stars
Custom / Unknown

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity0
Maintenance20
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
69/100Good
Architecture68
Code Quality62
Innovation66
Learning Curve78

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 become about/long_about/help/long_help clap output without extra annotations
  • flatten support 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 --help output
  • Custom string parser hooks (from_str, try_from_str, from_os_str, try_from_os_str, from_occurrences, from_flag) for types without a FromStr implementation
  • “Raw method” escape hatches that pass any clap::App/clap::Arg builder 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 git or cargo) where each subcommand is a variant of a StructOpt-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 derive feature 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.

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