Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions docs/standard/commandline/conceptual-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
title: Conceptual overview of System.CommandLine
ms.date: 01/22/2026
description: "Understand the design philosophy and conceptual model of System.CommandLine and how it compares to other .NET command-line libraries."
no-loc: [System.CommandLine]
helpviewer_keywords:
- "command line interface"
- "command line"
- "System.CommandLine"
ms.topic: conceptual
---

# Conceptual overview of System.CommandLine

This article explains the design philosophy and conceptual model behind `System.CommandLine` and how it differs from other popular .NET command-line parsing libraries.

## Design philosophy

`System.CommandLine` is built around several core principles:

### API-first design

The library provides a strongly-typed, object-oriented API for defining your command-line interface. Instead of using attributes on data classes, you explicitly construct `Command`, `Option`, and `Argument` objects that represent your CLI structure. This approach:

- Makes the command structure explicit and discoverable through code
- Enables dynamic command construction based on runtime conditions
- Separates CLI definition from your application's data model
- Provides better control over parsing behavior and validation

### Type safety and parsing

`System.CommandLine` uses generic types like `Option<T>` and `Argument<T>` to provide compile-time type safety. The library automatically handles parsing command-line strings into strongly-typed values. Built-in support includes:

- All primitive .NET types
- Common types like `DateTime`, `Guid`, `FileInfo`, and `DirectoryInfo`
- Enums (with case-insensitive matching)
- Arrays and `List<T>` for multi-valued options and arguments
- Custom types through user-defined parsers

### POSIX and Windows conventions

The parser natively supports both POSIX-style (`--option value`, `-o value`) and Windows-style (`/option value`) command-line syntax. This ensures your CLI works naturally across platforms without extra configuration.

### Rich user experience

`System.CommandLine` automatically provides features that improve the end-user experience:

- **Help generation** - Automatic `--help` text based on your command definitions and descriptions
- **Tab completion** - Shell integration for suggesting options, subcommands, and argument values
- **Error messages** - Clear, actionable error messages when parsing fails
- **Response files** - Support for reading arguments from files using `@response.txt` syntax

### Extensibility

The library is designed to be extended:

- Custom validators for complex validation rules
- Custom parsers for specialized types or input formats
- Custom completions for dynamic suggestion lists
- Middleware pattern for cross-cutting concerns

## Conceptual model

`System.CommandLine` uses a hierarchical model of symbols to represent your CLI:

### Commands

A `Command` represents an action your application can perform. Commands can have:

- Subcommands (creating a tree of nested commands)
- Options (named parameters that modify the command's behavior)
- Arguments (positional parameters required to execute the command)
- A handler (the code that executes when the command is invoked)

For example, `git commit -m "message"` has:
- Root command: `git`
- Subcommand: `commit`
- Option: `-m` (with value `"message"`)

### Options

An `Option` is a named parameter specified with a prefix (`--`, `-`, or `/`). Options:

- Are usually optional (but can be marked as required)
- Can have one or more values
- Can have aliases (for example, `-v` and `--verbose`)
- Can have default values

### Arguments

An `Argument` is a positional parameter that doesn't use a name prefix. Arguments:

- Are specified by their position in the command line
- Can be required or optional
- Can accept multiple values
- Are often used for the primary input to a command (like a file path)

### Parsing and invocation

When you invoke `Parse()` or `Invoke()`, the library:

1. Tokenizes the command-line input into discrete parts
2. Matches tokens to commands, options, and arguments
3. Validates the parsed values against defined rules
4. Converts string values to the appropriate .NET types
5. (For `Invoke()`) Executes the appropriate command handler

## Comparison with other libraries

### System.CommandLine vs. CommandLineParser

**CommandLineParser** uses an attribute-based approach where you decorate properties on a POCO:

```csharp
// CommandLineParser style
class Options
{
[Option('v', "verbose", Required = false)]
public bool Verbose { get; set; }
}
```

**System.CommandLine** uses explicit API construction:

```csharp
// System.CommandLine style
var verboseOption = new Option<bool>("--verbose", "Enable verbose output");
```

**Key differences:**

- **CommandLineParser** is simpler for basic scenarios but less flexible for complex command hierarchies
- **System.CommandLine** provides better support for subcommands and deeply nested command structures
- **System.CommandLine** offers built-in tab completion, which CommandLineParser doesn't support
- **System.CommandLine** is trim-friendly and optimized for AOT compilation
- **System.CommandLine** has a steeper learning curve but greater extensibility

### System.CommandLine vs. McMaster.Extensions.CommandLineUtils

**McMaster.Extensions.CommandLineUtils** supports both attribute-based and fluent builder patterns:

```csharp
// McMaster style
var app = new CommandLineApplication();
app.Option("-v|--verbose", "Enable verbose output", CommandOptionType.NoValue);
```

**Key differences:**

- **McMaster.Extensions.CommandLineUtils** is lightweight and pragmatic for simple tools
- **System.CommandLine** provides more advanced features like validators, custom parsers, and structured completions
- **System.CommandLine** has stronger type safety through generics
- **System.CommandLine** is officially supported by Microsoft and used in .NET CLI tools
- **System.CommandLine** has better documentation and is the strategic choice for new .NET projects

## When to use System.CommandLine

`System.CommandLine` is ideal when you need:

- **Complex command structures** with multiple levels of subcommands
- **Tab completion** support across different shells
- **Type-safe parsing** with compile-time guarantees
- **Trim-friendly** or AOT-compiled applications
- **Future-proof** CLI tools aligned with .NET's direction
- **Rich validation** and custom parsing logic
- **Consistent behavior** with other .NET CLI tools

For simple, single-command tools where you just need to parse a few options, lighter-weight alternatives might be sufficient. But for any CLI that will grow in complexity or requires modern features, `System.CommandLine` provides the best foundation.

## See also

- [System.CommandLine overview](index.md)
- [Tutorial: Get started with System.CommandLine](get-started-tutorial.md)
- [Command-line syntax overview](syntax.md)
- [How to customize parsing and validation](how-to-customize-parsing-and-validation.md)
Loading
Loading