Flags accepted by a command. Long form is derived from the atom name
(:base_port becomes --base-port); short aliases and every other behavior
are opt-in.
Types
option :port, type: :integer
option :ratio, type: :float
option :name, type: :string # default
option :verbose, type: :boolean # also supports --no-verbose
option :v, type: :count # -vv -> 2Typed values are coerced before your handler sees them. Invalid values
produce an error and never reach run/2.
Short aliases
option :port, type: :integer, short: :pAccepts -p 4000 or --port 4000.
Defaults and env var fallback
option :port, type: :integer, default: 4000, env: "PORT"Priority: CLI flag > PORT env var > default.
Choices
option :format, type: :string, choices: ["json", "csv", "table"]Rejected values produce an error before run/2 runs.
Repeated flags (:multi)
option :tag, type: :string, multi: true
# --tag a --tag b -> args[:tag] == ["a", "b"]Multi-value flags (:num_args)
:num_args collects several values from a single flag invocation into a list.
Pass an integer for an exact count or a range for a variable count:
option :point, type: :integer, num_args: 2
# --point 1 2 -> args[:point] == [1, 2]
option :tags, type: :string, num_args: 1..3
# --tags a b c -> args[:tags] == ["a", "b", "c"]Both the space-separated form (--point 1 2) and the --flag=value form work.
Collection stops at the next flag (a token starting with -) or at --, and
each value is coerced to the option's :type. A count outside the declared
range is a usage error:
--point 1 -> error: --point expects 2 value(s), got 1This is distinct from :multi, which repeats the whole flag (--tag a --tag b)
rather than consuming multiple tokens after one flag.
Hyphen-leading values (:allow_hyphen_values)
A value that starts with - normally looks like a flag, so it is rejected.
Negative numbers are always accepted (--range -5 5). For other hyphen-leading
values, set :allow_hyphen_values:
option :pattern, type: :string, allow_hyphen_values: true
# --pattern -v -> args[:pattern] == "-v"
option :range, type: :integer, num_args: 2, allow_hyphen_values: true
# --range -a -b -> args[:range] == ["-a", "-b"]A single-value option consumes exactly the next token as its value, so a
following flag is still parsed normally (--pattern x --verbose). With
:num_args, collection consumes hyphen-leading tokens up to the declared count.
Delimited values (:value_delimiter)
:value_delimiter splits one value on a string into a list:
option :tags, type: :string, value_delimiter: ","
# --tags a,b,c -> args[:tags] == ["a", "b", "c"]
option :ids, type: :integer, value_delimiter: ","
# --ids 1,2,3 -> args[:ids] == [1, 2, 3]Each element is coerced to the option's :type and validated against
:choices. A string :default is split the same way, and it combines with
:multi (each occurrence is split and the results flattened). This differs
from :num_args, which reads several separate tokens after one flag.
Optional value (:default_missing_value)
:default_missing_value is the value a flag takes when it is present with no
value, distinct from :default (the flag absent):
option :color, type: :string, default: "auto", default_missing_value: "always"
# (absent) -> args[:color] == "auto"
# --color -> args[:color] == "always"
# --color=never -> args[:color] == "never"An explicit value must use the --flag=value form. --color never leaves
never as a positional argument, so --color still resolves to the missing
value.
Custom value parsers (:parse)
:parse transforms a value into a domain type (an atom, a Date, a struct)
after :type coercion. See Validation for the full contract:
option :mode, type: :string, parse: fn
"r" -> {:ok, :read}
"w" -> {:ok, :write}
_ -> {:error, "must be r or w"}
end
# --mode r -> args[:mode] == :readAliases (long-form)
option :color, type: :string, aliases: [:colour]
# --color red and --colour red both set args[:color]Global options
Propagate an option to every subcommand:
option :verbose, type: :boolean, global: trueChildren inherit the option spec but can override by redeclaring.
Hiding options
option :internal, type: :boolean, hide: trueStill accepted by the parser, not shown in help.
Boolean negation
Every boolean option automatically accepts its --no-<name> inverse:
option :color, type: :boolean, default: true
# --color -> true
# --no-color -> falsePutting it together
option :port, type: :integer, short: :p,
default: 4000, env: "PORT",
validate: fn p -> if p in 1024..65_535, do: :ok, else: {:error, "invalid port"} end,
help: "Port to listen on"See also
- Validation for
:validateand cross-param validators. - Constraints for
:conflicts_with,:requires,:required_if,:required_unless, and groups. - Help and output for
:help_heading,:display_order, and other presentation controls.