jodersky / cmdr Edit

Pragmatic command line parsing and configuration for Scala apps

Version Matrix


Pragmatic command line parsing for Scala applications.


  • Simple interfaces:

    • imperative-style, inspired by the argparse package from python

    • declarative-style, inspired by Scala 3's @main annotation

  • Embedded bash completion. Simply add complete -o nospace -C <program> <program> to ~/.bashrc


Both examples have the same command-line interface.

1. Imperative Style

object Main {
  def main(args: Array[String]): Unit = {
    val parser = cmdr.ArgParser(
      "An example application"

    val host = parser.param[String](
      default = "localhost",
      help = "network host"

    val port = parser.param[Int](
      default = 8080,
      aliases = Seq("-p"),
      env = "PORT",
      help = "some port"

    val path = parser.requiredParam[java.nio.file.Path](
      help = "the path to use"


2. Declarative Style

object Main {
  @cmdr.main(name = "readme", doc = "An example application")
  def main(
    @cmdr.arg(doc = "network host")
    host: String = "localhost",
    @cmdr.arg(doc = "some port", aliases = Seq("-p"), env = "PORT")
    port: Int = 8080,
    @cmdr.arg(doc="the path to use")
    path: java.nio.file.Path
  ) = {

  def main(args: Array[String]): Unit = cmdr.parseOrExit(args)
  1. Build the above application by running either:
  • ./mill examples.readme-imperative[3.0.0-M3].dist
  • or, ./mill examples.readme-declarative[3.0.0-M3].dist
  1. Run the ./readme-<imperative|declarative> executable:
$ ./readme
missing argument: path
run with '--help' for more information
$ ./readme --help
usage: readme [options] <path>

An example application

positional arguments:
 path           the path to use
named arguments:
 --help         show this message and exit
 --host=        network host
 --port=, -p=   some port
environment variables:
 PORT           --port
$ ./readme /srv/www
$ ./readme --port=9090 /srv/www
$ ./readme /srv/www --port=9090
$ PORT=80 ./readme /srv/www --host=
# all parse errors are displayed; not just the first
$ ./readme --port="aaaahhhhh" a b c
unknown argument: b
unknown argument: c
error processing argument --port: 'aaaahhhhh' is not an integral number
run with '--help' for more information


This library is published for Scala 2.13 (JVM and Native), and 3. It is available on maven central under the coordinates:

  • mill: ivy"io.crashbox::cmdr::<version>"
  • sbt: "io.crashbox" %%% "cmdr" % "<version>"

where <version> is given by Latest version


Look at the API docs (defined here) for parsing rules and explanations on how it works.



  • Add range reader.
  • Upgrade mill to 0.9.10


  • Add experimental case class parser (Scala 3 only), available under parser.settings (the previous mutable settings parser has been renamed to parser.mutableSettings).
  • Add readers for:
    • scala.concurrent.time.Duration
    • Common java.time data types
    • Collections of paths. These readers use : as a separator, instead of the usual ,'.
  • Upgrade to Scala 3.0.2.


  • Upgrade to Scala 2.13.6
  • Refactor XDG directory implemention
  • Refactor default help message


  • Add support for Scala 3.0.0


  • Wrap text in help messages
  • Add support for Scala 3.0.0-RC3


  • Add support for Scala 3.0.0-RC2


  • Add readers for () => InputStream, () => OutputStream and geny.Readable. These readers follow the convention of using '-' to read/write from stdin/stdout.
  • Change the parser to support inserting parameters during parsing. Predefs can now be specified as parameters.


  • Show default values of named parameters in help messages.
  • Implement XDG Base Directory Specification.
  • Introduce the concept of a "predef", a flat configuration file which contains command line arguments

0.8.0 and before

A command line parser for Scala 2 and 3, featuring:

  • simple interfaces
  • bash completion


parameter : a named variable in an command line definition

argument : the value assigned to a parameter

named argument : an argument that starts with --. The characters following determine the name of the parameter that the argument is assigned to. The actual value assigned to the parameter is given after an '=' or a spance. For instance --foo=bar assigns bar to foo. Named arguments may appear in any order on a command line.

positional argument : an argument that is not named. Positional arguments are assigned to positional parameters according to their respective order of occurence.