Skip to main content

Option

The following functions allow you to define new options for your cli commands. They must be registered into each command via regular public class properties (private class properties aren't supported):

ts
class MyCommand extends Command {
flag = Option.Boolean(`--flag`);
}
ts
class MyCommand extends Command {
flag = Option.Boolean(`--flag`);
}

Option.Array​

ts
Option.Array(optionNames: string, default?: string[], opts?: {...})
ts
Option.Array(optionNames: string, default?: string[], opts?: {...})
OptiontypeDescription
aritynumberNumber of arguments for the option
descriptionstringShort description for the help message
hiddenbooleanHide the option from any usage list
requiredbooleanWhether at least a single occurrence of the option is required or not

Specifies that the command accepts a set of string arguments. The arity parameter defines how many values need to be accepted for each item. If no default value is provided, the option will start as undefined.

ts
class RunCommand extends Command {
args = Option.Array(`--arg`);
points = Option.Array(`--point`, {arity: 3});
// ...
}
ts
class RunCommand extends Command {
args = Option.Array(`--arg`);
points = Option.Array(`--point`, {arity: 3});
// ...
}

Generates:

bash
run --arg value1 --arg value2
# => TestCommand {"args": ["value1", "value2"]}
run --point x y z --point a b c
# => TestCommand {"points": [["x", "y", "z"], ["a", "b", "c"]]}
bash
run --arg value1 --arg value2
# => TestCommand {"args": ["value1", "value2"]}
run --point x y z --point a b c
# => TestCommand {"points": [["x", "y", "z"], ["a", "b", "c"]]}

Option.Boolean​

ts
Option.Boolean(optionNames: string, default?: boolean, opts?: {...})
ts
Option.Boolean(optionNames: string, default?: boolean, opts?: {...})
OptiontypeDescription
descriptionstringShort description for the help message
hiddenbooleanHide the option from any usage list
requiredbooleanWhether at least a single occurrence of the option is required or not

Specifies that the command accepts a boolean flag as an option. If no default value is provided, the option will start as undefined.

ts
class TestCommand extends Command {
flag = Option.Boolean(`--flag`);
// ...
}
ts
class TestCommand extends Command {
flag = Option.Boolean(`--flag`);
// ...
}

Generates:

bash
run --flag
# => TestCommand {"flag": true}
bash
run --flag
# => TestCommand {"flag": true}

Option.Counter​

ts
Option.Counter(optionNames: string, default?: number, opts?: {...})
ts
Option.Counter(optionNames: string, default?: number, opts?: {...})
OptiontypeDescription
descriptionstringShort description for the help message
hiddenbooleanHide the option from any usage list
requiredbooleanWhether at least a single occurrence of the option is required or not

Specifies that the command accepts a boolean flag as an option. Contrary to classic boolean options, each detected occurence will cause the counter to be incremented. Each time the argument is negated (--no-<name>), the counter will be reset to 0. If no default value is provided, the option will start as undefined.

ts
class TestCommand extends Command {
verbose = Option.Counter(`-v,--verbose`);
// ...
}
ts
class TestCommand extends Command {
verbose = Option.Counter(`-v,--verbose`);
// ...
}

Generates:

bash
run -v
# => TestCommand {"verbose": 1}
run -vv
# => TestCommand {"verbose": 2}
run --verbose -v --verbose -v
# => TestCommand {"verbose": 4}
run --verbose -v --verbose -v --no-verbose
# => TestCommand {"verbose": 0}
bash
run -v
# => TestCommand {"verbose": 1}
run -vv
# => TestCommand {"verbose": 2}
run --verbose -v --verbose -v
# => TestCommand {"verbose": 4}
run --verbose -v --verbose -v --no-verbose
# => TestCommand {"verbose": 0}

Option.Proxy​

ts
Option.Proxy(opts?: {...})
ts
Option.Proxy(opts?: {...})
OptiontypeDescription
requirednumberNumber of required trailing arguments

Specifies that the command accepts an infinite set of positional arguments that will not be consumed by the options of the Command instance. Use this decorator instead of Option.Rest when you wish to forward arguments to another command parsing them in any way. By default no arguments are required, but this can be changed by setting the required option.

ts
class RunCommand extends Command {
args = Option.Proxy();
// ...
}
ts
class RunCommand extends Command {
args = Option.Proxy();
// ...
}

Generates:

bash
run
# => TestCommand {"values": []}
run value1 value2
# => TestCommand {"values": ["value1", "value2"]}
run value1 --foo
# => TestCommand {"values": ["value1", "--foo"]}
run --bar=baz
# => TestCommand {"values": ["--bar=baz"]}
bash
run
# => TestCommand {"values": []}
run value1 value2
# => TestCommand {"values": ["value1", "value2"]}
run value1 --foo
# => TestCommand {"values": ["value1", "--foo"]}
run --bar=baz
# => TestCommand {"values": ["--bar=baz"]}

Note: Proxying can only happen once per command. Once triggered, a command can't get out of "proxy mode", all remaining arguments being proxied into a list. "Proxy mode" can be triggered in the following ways:

  • By passing a positional or an option that doesn't have any listeners attached to it. This happens when the listeners don't exist in the first place.

  • By passing a positional that doesn't have any remaining listeners attached to it. This happens when the listeners have already consumed a positional.

  • By passing the -- separator before an option that has a listener attached to it. This will cause Clipanion to activate "proxy mode" for all arguments after the separator, without proxying the separator itself. In all other cases, the separator will be proxied and not consumed by Clipanion.

Option.Rest​

ts
Option.Rest(opts?: {...})
ts
Option.Rest(opts?: {...})
OptiontypeDescription
requirednumberNumber of required trailing arguments

Specifies that the command accepts an unlimited number of positional arguments. By default no arguments are required, but this can be changed by setting the required option.

ts
class RunCommand extends Command {
values = Option.Rest();
// ...
}
ts
class RunCommand extends Command {
values = Option.Rest();
// ...
}

Generates:

bash
run
# => TestCommand {"values": []}
run value1 value2
# => TestCommand {"values": ["value1", "value2"]}
run value1
# => TestCommand {"values": ["value1"]}
run
# => TestCommand {"values": []}
bash
run
# => TestCommand {"values": []}
run value1 value2
# => TestCommand {"values": ["value1", "value2"]}
run value1
# => TestCommand {"values": ["value1"]}
run
# => TestCommand {"values": []}

Note: Rest arguments are strictly positionals. All options found between rest arguments will be consumed as options of the Command instance. If you wish to forward a list of option to another command without having to parse them yourself, use Option.Proxy instead.

Note: Rest arguments can be surrounded by other finite non-optional positionals such as Option.String({required: true}). Having multiple rest arguments in the same command is however invalid.

Advanced Example:

ts
class CopyCommand extends Command {
sources = Option.Rest({required: 1});
destination = Option.String();
force = Option.Boolean(`-f,--force`);
reflink = Option.String(`--reflink`, {tolerateBoolean: true});
// ...
}
ts
class CopyCommand extends Command {
sources = Option.Rest({required: 1});
destination = Option.String();
force = Option.Boolean(`-f,--force`);
reflink = Option.String(`--reflink`, {tolerateBoolean: true});
// ...
}

Generates:

bash
run src dest
# => CopyCommand {"sources": ["src"], "destination": "dest"}
run src1 src2 dest
# => CopyCommand {"sources": ["src1", "src2"], "destination": "dest"}
run src1 --force src2 dest
# => CopyCommand {"sources": ["src1", "src2"], "destination": "dest", "force": true}
run src1 src2 --reflink=always dest
# => CopyCommand {"sources": ["src1", "src2"], "destination": "dest", "reflink": "always"}
run src
# => Invalid! - Not enough positional arguments.
run dest
# => Invalid! - Not enough positional arguments.
bash
run src dest
# => CopyCommand {"sources": ["src"], "destination": "dest"}
run src1 src2 dest
# => CopyCommand {"sources": ["src1", "src2"], "destination": "dest"}
run src1 --force src2 dest
# => CopyCommand {"sources": ["src1", "src2"], "destination": "dest", "force": true}
run src1 src2 --reflink=always dest
# => CopyCommand {"sources": ["src1", "src2"], "destination": "dest", "reflink": "always"}
run src
# => Invalid! - Not enough positional arguments.
run dest
# => Invalid! - Not enough positional arguments.

Option.String (option)​

ts
Option.String(optionNames: string, default?: string, opts?: {...})
ts
Option.String(optionNames: string, default?: string, opts?: {...})
OptiontypeDescription
aritynumberNumber of arguments for the option
descriptionstringShort description for the help message
envstringName of an environment variable
hiddenbooleanHide the option from any usage list
tolerateBooleanbooleanAccept the option even if no argument is provided
requiredbooleanWhether at least a single occurrence of the option is required or not

Specifies that the command accepts an option that takes arguments (by default one, unless overriden via arity). If no default value is provided, the option will start as undefined.

If env is set and the specified environment variable is non-empty, it'll override the default value if necessary. Note that explicit options still take precedence over env values.

ts
class TestCommand extends Command {
arg = Option.String(`-a,--arg`);
// ...
}
ts
class TestCommand extends Command {
arg = Option.String(`-a,--arg`);
// ...
}

Generates:

bash
run --arg value
run --arg=value
run -a value
run -a=value
# => TestCommand {"arg": "value"}
run --arg=-42
# => TestCommand {"arg": "-42"}
run --arg -42
# => Invalid! Option `-42` doesn't exist.
bash
run --arg value
run --arg=value
run -a value
run -a=value
# => TestCommand {"arg": "value"}
run --arg=-42
# => TestCommand {"arg": "-42"}
run --arg -42
# => Invalid! Option `-42` doesn't exist.

Be careful, by default, options that accept an argument must receive one on the CLI (ie --foo --bar wouldn't be valid if --foo accepts an argument).

This behaviour can be toggled off if the tolerateBoolean option is set. In this case, the option will act like a boolean flag if it doesn't have a value. Note that with this option on, arguments values can only be specified using the --foo=ARG syntax, which makes this option incompatible with arities higher than one.

ts
class TestCommand extends Command {
debug = Option.String(`--inspect`, {tolerateBoolean: true});
// ...
}
ts
class TestCommand extends Command {
debug = Option.String(`--inspect`, {tolerateBoolean: true});
// ...
}

Generates:

bash
run --inspect
# => TestCommand {"debug": true}
run --inspect=1234
# => TestCommand {"debug": "1234"}
run --inspect 1234
# Invalid!
bash
run --inspect
# => TestCommand {"debug": true}
run --inspect=1234
# => TestCommand {"debug": "1234"}
run --inspect 1234
# Invalid!

Option.String (positional)​

ts
Option.String(opts: {...})
ts
Option.String(opts: {...})
OptiontypeDescription
requiredbooleanWhether the positional argument is required or not

Specifies that the command accepts a positional argument. By default it will be required, but this can be toggled off using required.

ts
class TestCommand extends Command {
foo = Option.String();
// ...
}
ts
class TestCommand extends Command {
foo = Option.String();
// ...
}

Generates:

bash
run value
# => TestCommand {"foo": "value"}
bash
run value
# => TestCommand {"foo": "value"}

Note that Clipanion supports required positional arguments both at the beginning and the end of the positional argument list (which allows you to build CLI for things like cp). For that to work, make sure to list your arguments in the right order:

ts
class TestCommand extends Command {
foo = Option.String({required: false});
bar = Option.String();
// ...
}
ts
class TestCommand extends Command {
foo = Option.String({required: false});
bar = Option.String();
// ...
}

Generates:

bash
run value1 value2
# => TestCommand {"foo": "value1", "bar": "value2"}
run value
# => TestCommand {"foo": undefined, "bar": "value"}
run
# Invalid!
bash
run value1 value2
# => TestCommand {"foo": "value1", "bar": "value2"}
run value
# => TestCommand {"foo": undefined, "bar": "value"}
run
# Invalid!