Defining Commands and Arguments

How to declare command-line parameters (arguments and options) using Spectre.Console.Cli's attributes and settings classes

Every command in Spectre.Console.Cli receives its input through a CommandSettings class. Decorate properties with [CommandArgument] for positional parameters and [CommandOption] for named flags and options. The framework handles parsing, validation, and help generation automatically.

What We're Building

A file copy command with a required source path, optional destination, and various flags like --force and --buffer-size:

Defining commands and arguments demonstration

Define Arguments and Options

Use [CommandArgument] with a position index and template: angle brackets <name> for required arguments, square brackets [name] for optional ones. For named parameters, use [CommandOption] with short and/or long forms separated by |.

public class Settings : CommandSettings
{
    // Required positional argument (angle brackets)
    [CommandArgument(0, "<source>")]
    [Description("The source file to copy")]
    public string Source { get; init; } = string.Empty;
  
    // Optional positional argument (square brackets)
    [CommandArgument(1, "[destination]")]
    [Description("The destination path (defaults to current directory)")]
    public string? Destination { get; init; }
  
    // Short and long option forms
    [CommandOption("-f|--force")]
    [Description("Overwrite existing files without prompting")]
    public bool Force { get; init; }
  
    // Option with a value
    [CommandOption("-b|--buffer-size")]
    [Description("Buffer size in KB for the copy operation")]
    [DefaultValue(64)]
    public int BufferSize { get; init; } = 64;
  
    // Long-form only option
    [CommandOption("--preserve-timestamps")]
    [Description("Preserve original file timestamps")]
    public bool PreserveTimestamps { get; init; }
  
    // Short-form only option
    [CommandOption("-v")]
    [Description("Enable verbose output")]
    public bool Verbose { get; init; }
}

This settings class produces the following usage:

USAGE:
    myapp <source> [destination] [OPTIONS]
  
OPTIONS:
    -f, --force                 Overwrite existing files without prompting
    -b, --buffer-size <INT>     Buffer size in KB for the copy operation [default: 64]
        --preserve-timestamps   Preserve original file timestamps
    -v                          Enable verbose output

Boolean properties become flags—users include them to set true, omit them for false. Properties with [DefaultValue] show their defaults in help text.

Accept Multiple Values

For commands that process multiple files or need repeatable options, use array types. An array argument captures all remaining positional values and must be the last argument. Array options can be specified multiple times.

public class Settings : CommandSettings
{
    // Array argument captures all remaining positional values
    // Must be the last argument (highest position index)
    [CommandArgument(0, "<files>")]
    [Description("One or more files to process")]
    public string[] Files { get; init; } = [];
  
    // Array option - specify multiple times: --tag api --tag v2
    [CommandOption("-t|--tag <TAG>")]
    [Description("Tags to apply (can be specified multiple times)")]
    public string[] Tags { get; init; } = [];
}

Users invoke this as:

myapp file1.txt file2.txt file3.txt --tag api --tag production

Use Enums for Constrained Values

When an option should only accept specific values, use an enum type. The framework validates input and displays allowed values in help text.

public class Settings : CommandSettings
{
    [CommandArgument(0, "[project]")]
    [Description("The project to build")]
    public string? Project { get; init; }
  
    // Enum option - framework validates and shows allowed values in help
    [CommandOption("-l|--log-level")]
    [Description("Set the logging verbosity")]
    [DefaultValue(LogLevel.Normal)]
    public LogLevel LogLevel { get; init; } = LogLevel.Normal;
  
    // Enum option for build configuration
    [CommandOption("-c|--configuration")]
    [Description("Build configuration")]
    [DefaultValue(Configuration.Debug)]
    public Configuration Configuration { get; init; } = Configuration.Debug;
}

Invalid values produce a clear error message listing the allowed options.

See Also