Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Important
System.CommandLine
is currently in PREVIEW, and this documentation is for version 2.0 beta 5.
Some information relates to prerelease product that may be substantially modified before it's released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
This article explains the command-line syntax that System.CommandLine
recognizes. The information is useful to both users and developers of .NET command-line apps, including the .NET CLI.
Tokens
System.CommandLine
parses command-line input into tokens, which are strings delimited by spaces. For example, consider the following command line:
dotnet tool install dotnet-suggest --global --verbosity quiet
This input is parsed by the dotnet
application into tokens tool
, install
, dotnet-suggest
, --global
, --verbosity
, and quiet
.
Tokens are interpreted as commands, options, or arguments. The command-line app that is being invoked determines how the tokens after the first one are interpreted. The following table shows how System.CommandLine
interprets the preceding example:
Token | Parsed as |
---|---|
tool |
Subcommand |
install |
Subcommand |
dotnet-suggest |
Argument for install command |
--global |
Option for install command |
--verbosity |
Option for install command |
quiet |
Argument for --verbosity option |
A token can contain spaces if it's enclosed in quotation marks ("
). Here's an example:
dotnet tool search "ef migrations add"
Commands
A command in command-line input is a token that specifies an action or defines a group of related actions. For example:
- In
dotnet run
,run
is a command that specifies an action. - In
dotnet tool install
,install
is a command that specifies an action, andtool
is a command that specifies a group of related commands. There are other tool-related commands, such astool uninstall
,tool list
, andtool update
.
Root command
The root command is the one that specifies the name of the app's executable. For example, the dotnet
command specifies the dotnet.exe executable.
System.CommandLine.Command
is the general-purpose class for any command or subcommand, while System.CommandLine.RootCommand
is a specialized version intended for the application's root entry point, inheriting all features of System.CommandLine.Command
but adding root-specific behavior and defaults, such as Help option, Version option and Suggest directive.
Subcommands
Most command-line apps support subcommands, also known as verbs. For example, the dotnet
command has a run
subcommand that you invoke by entering dotnet run
.
Subcommands can have their own subcommands. In dotnet tool install
, install
is a subcommand of tool
.
You can add subcommands as shown in the following example:
RootCommand rootCommand = new();
Command sub1Command = new("sub1", "First-level subcommand");
rootCommand.Subcommands.Add(sub1Command);
Command sub1aCommand = new("sub1a", "Second level subcommand");
sub1Command.Subcommands.Add(sub1aCommand);
The innermost subcommand in this example can be invoked like this:
myapp sub1 sub1a
Options
An option is a named parameter that can be passed to a command. POSIX CLIs typically prefix the option name with two hyphens (--
). The following example shows two options:
dotnet tool update dotnet-suggest --verbosity quiet --global
^---------^ ^------^
As this example illustrates, the value of the option may be explicit (quiet
for --verbosity
) or implicit (nothing follows --global
). Options that have no value specified are typically Boolean parameters that default to true
if the option is specified on the command line.
For some Windows command-line apps, you identify an option by using a leading slash (/
) with the option name. For example:
msbuild /version
^------^
System.CommandLine
supports both POSIX and Windows prefix conventions.
When you configure an option, you specify the option name including the prefix:
Option<int> delayOption = new("--delay", "-d")
{
Description = "An option whose argument is parsed as an int.",
DefaultValueFactory = parseResult => 42,
};
Option<string> messageOption = new("--message", "-m")
{
Description = "An option whose argument is parsed as a string."
};
RootCommand rootCommand = new();
rootCommand.Options.Add(delayOption);
rootCommand.Options.Add(messageOption);
To add an option to a command and recursively to all of its subcommands, use the System.CommandLine.Symbol.Recursive
property.
Required Options
Some options have required arguments. For example in the .NET CLI, --output
requires a folder name argument. If the argument is not provided, the command fails. To make an option required, set its System.CommandLine.Symbol.Required
property to true
, as shown in the following example:
Option<FileInfo> fileOption = new("--output")
{
Required = true
};
If a required option has a default value (specified via DefaultValueFactory
property), the option doesn't have to be specified on the command line. In that case, the default value provides the required option value.
Arguments
An argument is an unnamed parameter that can be passed to a command. The following example shows an argument for the build
command.
dotnet build myapp.csproj
^----------^
When you configure an argument, you specify the argument name (it's not used for parsing, but it can be used for getting parsed values by name or displaying help) and type:
Argument<int> delayArgument = new("delay")
{
Description = "An argument that is parsed as an int.",
DefaultValueFactory = parseResult => 42
};
Argument<string> messageArgument = new("message")
{
Description = "An argument that is parsed as a string."
};
RootCommand rootCommand = new();
rootCommand.Arguments.Add(delayArgument);
rootCommand.Arguments.Add(messageArgument);
Default Values
Both arguments and options can have default values that apply if no argument is explicitly provided. For example, many options are implicitly Boolean parameters with a default of true
when the option name is in the command line. The following command-line examples are equivalent:
dotnet tool update dotnet-suggest --global
^------^
dotnet tool update dotnet-suggest --global true
^-----------^
An argument that is defined without a default value is treated as a required argument.
Parse errors
Options and arguments have expected types, and an error is produced when the value can't be parsed. For example, the following command errors because "silent" isn't one of the valid values for --verbosity
:
dotnet build --verbosity silent
Option<string> verbosityOption = new("--verbosity", "-v")
{
Description = "Set the verbosity level.",
};
verbosityOption.AcceptOnlyFromAmong("quiet", "minimal", "normal", "detailed", "diagnostic");
RootCommand rootCommand = new() { verbosityOption };
ParseResult parseResult = rootCommand.Parse(args);
foreach (ParseError parseError in parseResult.Errors)
{
Console.WriteLine(parseError.Message);
}
Argument 'silent' not recognized. Must be one of:
'quiet'
'minimal'
'normal'
'detailed'
'diagnostic'
Arguments also have expectations about how many values can be provided. Examples are provided in the section on argument arity.
Order of options and arguments
You can provide options before arguments or arguments before options on the command line. The following commands are equivalent:
dotnet add package System.CommandLine --prerelease
dotnet add package --prerelease System.CommandLine
Options can be specified in any order. The following commands are equivalent:
dotnet add package System.CommandLine --prerelease --no-restore --source https://api.nuget.org/v3/index.json
dotnet add package System.CommandLine --source https://api.nuget.org/v3/index.json --no-restore --prerelease
When there are multiple arguments, the order does matter. The following commands are not equivalent; they differ in the order of the values, which could lead to different results:
myapp argument1 argument2
myapp argument2 argument1
Aliases
In both POSIX and Windows, it's common for some commands and options to have aliases. These are usually short forms that are easier to type. Aliases can also be used for other purposes, such as to simulate case-insensitivity and to support alternate spellings of a word.
POSIX short forms typically have a single leading hyphen followed by a single character. The following commands are equivalent:
dotnet build --verbosity quiet
dotnet build -v quiet
The GNU standard recommends automatic aliases. That is, you can enter any part of a long-form command or option name and it will be accepted. This behavior would make the following command lines equivalent:
dotnet publish --output ./publish
dotnet publish --outpu ./publish
dotnet publish --outp ./publish
dotnet publish --out ./publish
dotnet publish --ou ./publish
dotnet publish --o ./publish
System.CommandLine
doesn't support automatic aliases. Each alias must be specified explicitly. Both commands and options expose an Aliases
property. Option
has a constructor that accepts aliases as parameters, so you can define an option with multiple aliases in a single line:
Option<bool> helpOption = new("--help", ["-h", "/h", "-?", "/?"]);
Command command = new("serialize") { helpOption };
command.Aliases.Add("serialise");
We recommend that you minimize the number of option aliases that you define, and avoid defining certain aliases in particular. For more information, see Short-form aliases.
Case sensitivity
Command and option names and aliases are case-sensitive by default according to POSIX convention, and System.CommandLine
follows this convention. If you want your CLI to be case insensitive, define aliases for the various casing alternatives. For example, --additional-probing-path
could have aliases --Additional-Probing-Path
and --ADDITIONAL-PROBING-PATH
.
In some command-line tools, a difference in casing specifies a difference in function. For example, git clean -X
behaves differently than git clean -x
. The .NET CLI is all lowercase.
Case sensitivity does not apply to argument values for options that are based on enums. Enum names are matched regardless of casing.
The --
token
POSIX convention interprets the double-dash (--
) token as an escape mechanism. Everything that follows the double-dash token is interpreted as arguments for the command. This functionality can be used to submit arguments that look like options, since it prevents them from being interpreted as options.
Suppose myapp takes a message
argument, and you want the value of message
to be --interactive
. The following command line might give unexpected results.
myapp --interactive
If myapp
doesn't have an --interactive
option, the --interactive
token is interpreted as an argument. But if the app does have an --interactive
option, this input will be interpreted as referring to that option.
The following command line uses the double-dash token to set the value of the message
argument to "--interactive":
myapp -- --interactive
^^
System.CommandLine
supports this double-dash functionality.
Option-argument delimiters
System.CommandLine
lets you use a space, '=', or ':' as the delimiter between an option name and its argument. For example, the following commands are equivalent:
dotnet build -v quiet
dotnet build -v=quiet
dotnet build -v:quiet
A POSIX convention lets you omit the delimiter when you are specifying a single-character option alias. For example, the following commands are equivalent:
myapp -vquiet
myapp -v quiet
System.CommandLine supports this syntax by default.
Argument arity
The arity of an option or command's argument is the number of values that can be passed if that option or command is specified.
Arity is expressed with a minimum value and a maximum value, as the following table illustrates:
Min | Max | Example validity | Example |
---|---|---|---|
0 | 0 | Valid: | --file |
Invalid: | --file a.json | ||
Invalid: | --file a.json --file b.json | ||
0 | 1 | Valid: | --flag |
Valid: | --flag true | ||
Valid: | --flag false | ||
Invalid: | --flag false --flag false | ||
1 | 1 | Valid: | --file a.json |
Invalid: | --file | ||
Invalid: | --file a.json --file b.json | ||
0 | n | Valid: | --file |
Valid: | --file a.json | ||
Valid: | --file a.json --file b.json | ||
1 | n | Valid: | --file a.json |
Valid: | --file a.json b.json | ||
Invalid: | --file |
System.CommandLine
has an System.CommandLine.ArgumentArity
struct for defining arity, with the following values:
System.CommandLine.ArgumentArity.Zero
- No values allowed.System.CommandLine.ArgumentArity.ZeroOrOne
- May have one value, may have no values.System.CommandLine.ArgumentArity.ExactlyOne
- Must have one value.System.CommandLine.ArgumentArity.ZeroOrMore
- May have one value, multiple values, or no values.System.CommandLine.ArgumentArity.OneOrMore
- May have multiple values, must have at least one value.
You can explicitly set arity by using the Arity
property, but in most cases that is not necessary. System.CommandLine
automatically determines the argument arity based on the argument type:
Argument type | Default arity |
---|---|
Boolean |
ArgumentArity.ZeroOrOne |
Collection types | ArgumentArity.ZeroOrMore |
Everything else | ArgumentArity.ExactlyOne |
Option overrides
If the arity maximum is 1, System.CommandLine
can still be configured to accept multiple instances of an option. In that case, the last instance of a repeated option overwrites any earlier instances. In the following example, the value 2 would be passed to the myapp
command.
myapp --delay 3 --message example --delay 2
Multiple arguments
By default, when you call a command, you can repeat an option name to specify multiple arguments for an option that has maximum arity greater than one.
myapp --items one --items two --items three
To allow multiple arguments without repeating the option name, set System.CommandLine.Option.AllowMultipleArgumentsPerToken
to true
. This setting lets you enter the following command line.
myapp --items one two three
The same setting has a different effect if maximum argument arity is 1. It allows you to repeat an option but takes only the last value on the line. In the following example, the value three
would be passed to the app.
myapp --item one --item two --item three
Option bundling
POSIX recommends that you support bundling of single-character options, also known as stacking. Bundled options are single-character option aliases specified together after a single hyphen prefix. Only the last option can specify an argument. For example, the following command lines are equivalent:
git clean -f -d -x
git clean -fdx
If an argument is provided after an option bundle, it applies to the last option in the bundle. The following command lines are equivalent:
myapp -a -b -c arg
myapp -abc arg
In both variants in this example, the argument arg
would apply only to the option -c
.
Boolean options (flags)
If true
or false
is passed for an option having a bool
argument, it's parsed as expected. But an option whose argument type is bool
typically doesn't require an argument to be specified. Boolean options, sometimes called "flags", typically have an arity of System.CommandLine.ArgumentArity.ZeroOrOne
. The presence of the option name on the command line, with no argument following it, results in a default value of true
. The absence of the option name in command-line input results in a value of false
. If the myapp
command prints out the value of a Boolean option named --interactive
, the following input creates the following output:
myapp
myapp --interactive
myapp --interactive false
myapp --interactive true
False
True
False
True
Version option
Apps built on System.CommandLine
automatically provide the version number in response to the --version
option used with the root command. For example:
dotnet --version
6.0.100
Response files
A response file is a file that contains a set of tokens for a command-line app. Response files are a feature of System.CommandLine
that is useful in two scenarios:
- To invoke a command-line app by specifying input that is longer than the character limit of the terminal.
- To invoke the same command repeatedly without retyping the whole line.
To use a response file, enter the file name prefixed by an @
sign wherever in the line you want to insert commands, options, and arguments. The .rsp file extension is a common convention, but you can use any file extension.
The following lines are equivalent:
dotnet build --no-restore --output ./build-output/
dotnet @sample1.rsp
dotnet build @sample2.rsp --output ./build-output/
Contents of sample1.rsp:
build
--no-restore
--output
./build-output/
Contents of sample2.rsp:
--no-restore
Here are syntax rules that determine how the text in a response file is interpreted:
- Tokens are delimited by spaces. A line that contains Good morning! is treated as two tokens, Good and morning!.
- Multiple tokens enclosed in quotes are interpreted as a single token. A line that contains "Good morning!" is treated as one token, Good morning!.
- Any text between a
#
symbol and the end of the line is treated as a comment and ignored. - Tokens prefixed with
@
can reference additional response files. - The response file can have multiple lines of text. The lines are concatenated and interpreted as a sequence of tokens.
Directives
System.CommandLine
introduces a syntactic element called a directive represented by System.CommandLine.Directive
type. The [diagram]
directive is an example. When you include [diagram]
after the app's name, System.CommandLine
displays a diagram of the parse result instead of invoking the command-line app:
dotnet [diagram] build --no-restore --output ./build-output/
^-----^
[ dotnet [ build [ --no-restore <True> ] [ --output <./build-output/> ] ] ]
The purpose of directives is to provide cross-cutting functionality that can apply across command-line apps. Because directives are syntactically distinct from the app's own syntax, they can provide functionality that applies across apps.
A directive must conform to the following syntax rules:
- It's a token on the command line that comes after the app's name but before any subcommands or options.
- It's enclosed in square brackets.
- It doesn't contain spaces.
An unrecognized directive is ignored without causing a parsing error.
A directive can include an argument, separated from the directive name by a colon.
The following directives are built in:
The [diagram]
directive
Both users and developers might find it useful to see how an app will interpret a given input. One of the default features of a System.CommandLine
app is the [diagram]
directive, which lets you preview the result of parsing command input. For example:
myapp [diagram] --delay not-an-int --interactive --file filename.txt extra
![ myapp [ --delay !<not-an-int> ] [ --interactive <True> ] [ --file <filename.txt> ] *[ --fgcolor <White> ] ] ???--> extra
In the preceding example:
- The command (
myapp
), its child options, and the arguments to those options are grouped using square brackets. - For the option result
[ --delay !<not-an-int> ]
, the!
indicates a parsing error. The valuenot-an-int
for anint
option can't be parsed to the expected type. The error is also flagged by!
in front of the command that contains the errored option:![ myapp...
. - For the option result
*[ --fgcolor <White> ]
, the option wasn't specified on the command line, so the configured default was used.White
is the effective value for this option. The asterisk indicates that the value is the default. ???-->
points to input that wasn't matched to any of the app's commands or options.
Suggest directive
The [suggest]
directive lets you search for commands when you don't know the exact command.
dotnet [suggest] buil
build
build-server
msbuild