Skip to content

Repository files navigation

Argx

Expressive command-line parsing and configuration for Rust


Version MIT OR Apache-2.0

Argx is a derive-first command-line parser and configuration library for Rust. Define your CLI and configuration with Rust types, and Argx derives parsing, help, diagnostics, completions, schema discovery, and layered configuration from those definitions.

See docs.rs/argx for the complete API and behavioral reference.

Installation

cargo add argx

Features

The derive feature is enabled by default. Enable toml when using TOML configuration layers:

cargo add argx --features toml

Enable chrono, url, or uuid when command values and schema-enabled types use those crates. Argx preserves recognized formats in invocation schemas and enables the matching Schemars integrations. Chrono DateTime and NaiveDate values receive standard date-time and date formats. NaiveTime and NaiveDateTime remain lexical strings because JSON Schema has no standard format that faithfully represents their timezone-free values:

cargo add argx --features chrono,url,uuid

Quick start

use argx::{Args, Parser, Subcommand};

#[derive(Parser)]
#[argx(name = "acme")]
struct Cli {
    #[argx(subcommand)]
    command: Command,
}

#[derive(Subcommand)]
enum Command {
    /// Start the service.
    Serve(Serve),

    /// Print service status.
    Status,
}

#[derive(Args)]
struct Serve {
    /// Port to listen on.
    #[argx(long, default = 8080)]
    port: u16,
}

fn main() {
    match Cli::parse().command {
        Command::Serve(args) => println!("listening on {}", args.port),
        Command::Status => println!("running"),
    }
}

Rust documentation becomes CLI help, while field types define parsing.

$ acme serve --port 3000
listening on 3000

$ acme --help
Usage: acme [OPTIONS] <COMMAND>

Commands:
  serve   Start the service.
  status  Print service status.

Options:
  -h, --help  Print help

Nested commands get their own generated help:

$ acme serve --help
Start the service.

Usage: acme serve [OPTIONS]

Options:
      --port <PORT>  Port to listen on.
  -h, --help         Print help

The same derived command model also powers shell completion and schema discovery.

Configuration

#[derive(argx::Config)] resolves one typed value from explicitly ordered layers:

use argx::{Argv, Defaults, Environment};

#[derive(argx::Config)]
#[argx(prefix = "ACME")]
struct Config {
    #[argx(long, default = 4)]
    workers: usize,

    #[argx(long)]
    endpoint: String,
}

let config = Config::loader()
    .layer(Defaults)
    .layer(Environment)
    .layer(Argv::current())
    .resolve()?;

Layers are applied in declaration order, with later layers overriding only values they provide. Defaults are explicit through Defaults. Environment reads mapped environment variables and Argv reads fields with CLI metadata. Dotenv and optional Toml layers read only the paths you provide. Argx performs no configuration-file discovery.

See the configuration example for environment naming, flattening, interpolation, and collection values.

Schema discovery

Mark each command that participates in schema discovery with #[argx(schema)].

At the root, Argx exposes the immediate command structure:

acme schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "acme",
  "type": "object",
  "additionalProperties": false,
  "$defs": {
    "subcommands": {
      "$defs": {
        "objects": {
          "title": "objects",
          "description": "Manage objects."
        }
      }
    }
  }
}

Nested structural commands work the same way:

acme schema objects
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "objects",
  "description": "Manage objects.",
  "type": "object",
  "additionalProperties": false,
  "$defs": {
    "subcommands": {
      "$defs": {
        "get": {
          "title": "get",
          "description": "Get an object."
        }
      }
    }
  }
}

Leaf commands expose the concrete invocation contract together with typed result and error schemas:

acme objects get object-7 --schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "get",
  "description": "Get an object.",
  "type": "object",
  "properties": {
    "id": {
      "description": "Object identifier.",
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false,
  "$defs": {
    "result": {
      "$ref": "#/$defs/types/$defs/GetOutput",
      "title": "GetOutput"
    },
    "error": {
      "$ref": "#/$defs/types/$defs/GetError",
      "title": "GetError"
    },
    "types": {
      "$defs": {
        "GetOutput": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            }
          },
          "required": [
            "id"
          ]
        },
        "GetError": {
          "type": "string",
          "enum": [
            "NotFound"
          ]
        }
      }
    }
  }
}

Structural schemas let tools walk the command tree incrementally. Leaf schemas describe the exact arguments a command accepts and, when associated with a handler, the result and error types it can produce.

Use --full to recursively expand a structural command.

See the schema example for a complete command tree.

Examples

Runnable examples cover the main Argx features. Start with basic for the smallest integration point or complete for an integrated example.

Example Focus Try it
basic Minimal parser and built-in help cargo run --example basic -- --help
arguments Options, defaults, constraints, and finite values cargo run --example arguments -- input.txt --format json
commands Subcommands, flattening, aliases, and versions cargo run --example commands -- --verbose add hello --force
configuration Ordered configuration layers cargo run --example configuration -- --workers 8
schema Schema discovery and handler contracts cargo run --example schema -- schema objects get
completions Dynamic shell completion cargo run --example completions -- zsh
complete Integrated reference application cargo run --example complete -- get object-7

Support

Argx supports Linux and macOS natively. Windows is supported through the Windows Subsystem for Linux (WSL). Native Windows targets are not supported.

MSRV

The current MSRV (minimum supported Rust version) is 1.95.

Argx will keep a rolling MSRV policy of at least two versions behind the latest stable release (so if the latest stable release is 1.97, we would support 1.95).

Note that the MSRV is not increased automatically.

Contributing

Contributions to Argx are welcome. See the Contributing Guide for information on reporting bugs, proposing features, submitting pull requests, and the licensing terms that apply to contributions.

Security Policy

If you believe you have found a security vulnerability, please do not report it through GitHub Issues. See our Security Policy for reporting instructions.

Credit

Argx is inspired in part by Usage, Clap and Incur.

Usage was a particularly important influence on Argx’s compile-time architecture: static command metadata, separation of argv parsing from typed construction, compile-time composition of commands and argument groups, and the use of one authoritative CLI description to drive parsing and other derived behavior.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

This software includes third-party components subject to separate license terms. See THIRD_PARTY_NOTICES.md.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Argx by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Expressive command-line parsing and configuration for Rust.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages