created_at2023-04-10 23:56:31.144498
updated_at2024-02-22 17:04:55.323414
descriptionObsessively tiny argument parsing
Jay Oster (parasyte)


README Documentation unsafe forbidden GitHub actions GitHub activity GitHub Sponsors

Only argument parsing! Nothing more.


  • 100% safe Rust 🦀.
  • Correctness: Paths with invalid UTF-8 work correctly on all platforms.
  • Fast compile times.
  • Convenience: #[derive(OnlyArgs)] on a struct and parse CLI arguments from the environment into it with minimal boilerplate.

MSRV Policy

The Minimum Supported Rust Version for onlyargs will always be made available in the file on GitHub.


There's an argument parsing crate for everyone. So why write another?

onlyargs is an example of extreme minimalism! The only thing it provides is a trait and some utility functions; you're expected to do the actual work to implement it for your CLI argument struct. But don't let that scare you away! The parser implementation in the "full" example is only around 50 lines! (Most of the file is boilerplate.)

The goals of this parser are correctness, fast compile times, and convenience.

100% safe Rust

No shenanigans! The only unsafe code is abstracted away in the standard library.


  • The main parsing loop uses OsString so that invalid UTF-8 can be accepted as an argument.
  • Arguments can either be stored directly as an OsString or converted to a PathBuf with no extra cost. Easily access your mojibake file systems!
  • Conversions from OsString are handled by your parser implementation. It's only as correct as you want it to be!
  • Play with the examples. Try to break it. Have fun!

Fast compile times

See myn benchmark results.


Argument parsing is dead simple (assuming your preferred DSL is opinionated and no-nonsense). There is no reason to overcomplicate it by supporting multiple forms like --argument 123 and --argument=123 or -a 123 and -a123. Just pick one!

The provided examples use the former in both cases: --argument 123 and -a 123 are accepted for arguments with a value. Supporting both long and short argument names is just a pattern!

Some("--argument") | Some("-a")

It is fairly straightforward to derive an implementation with a proc_macro. Compare the "full-derive" example to the "full" example.

Commit count: 32

cargo fmt