Skip to main content

commandline-cheatsheet

Use when building command-line applications in .NET with System.CommandLine. Covers command/option/argument definitions, middleware, tab completion, parsing, and hosting integration for CLI tools. USE FOR: building CLI applications with typed argument parsing, creating dotnet tools with subcommands, System.CommandLine setup and configuration, adding tab completion to CLI apps, parsing and validating command-line arguments DO NOT USE FOR: executing external CLI processes (use cliwrap), rendering rich terminal UI with tables and progress bars (use spectre-console), building web APIs (use ASP.NET Core), simple Console.ReadLine input

Quellinformationen

Repository
Tyler-R-Kendrick/agent-skills
Letzte Quellaktivität
11. Februar 2026 um 05:14
Erkannte Sprache von SKILL.md
Englisch
Sterne
12
Forks
4

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
21 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
commandline-cheatsheet
description
Use when building command-line applications in .NET with System.CommandLine. Covers command/option/argument definitions, middleware, tab completion, parsing, and hosting integration for CLI tools. USE FOR: building CLI applications with typed argument parsing, creating dotnet tools with subcommands, System.CommandLine setup and configuration, adding tab completion to CLI apps, parsing and validating command-line arguments DO NOT USE FOR: executing external CLI processes (use cliwrap), rendering rich terminal UI with tables and progress bars (use spectre-console), building web APIs (use ASP.NET Core), simple Console.ReadLine input
license
MIT
metadata
{"displayName":"Command-Line Cheatsheet","author":"Tyler-R-Kendrick","version":"1.0.0"}
compatibility
claude, copilot, cursor
references
[{"title":"System.CommandLine Documentation","url":"https://learn.microsoft.com/dotnet/standard/commandline"},{"title":"System.CommandLine GitHub Repository","url":"https://github.com/dotnet/command-line-api"},{"title":"System.CommandLine NuGet Package","url":"https://www.nuget.org/packages/System.CommandLine"}]
# Command-Line Cheatsheet ## Overview System.CommandLine is the official .NET library for building command-line applications with typed argument parsing, automatic help generation, tab completion, and middleware support. It provides a structured way to define commands, options, and arguments that map directly to handler methods, with built-in validation and error reporting. ## NuGet Packages ```bash dotnet add package System.CommandLine dotnet add package System.CommandLine.Hosting # Generic Host integration ``` ## Minimal CLI Application ```csharp using System.CommandLine; var nameOption = new Option<string>( name: "--name", description: "Your name") { IsRequired = true }; var greetingOption = new Option<string>( name: "--greeting", description: "The greeting to use", getDefaultValue: () => "Hello"); var rootCommand = new RootCommand("A simple greeting CLI tool"); rootCommand.AddOption(nameOption); rootCommand.AddOption(greetingOption); rootCommand.SetHandler((string name, string greeting) => { Console.WriteLine($"{greeting}, {name}!"); }, nameOption, greetingOption); return await rootCommand.InvokeAsync(args); // Usage: myapp --name Alice --greeting "Good morning" ``` ## Commands with Subcommands ```csharp using System.CommandLine; var rootCommand = new RootCommand("Project management CLI"); // 'new' command var newCommand = new Command("new", "Create a new project"); var templateArg = new Argument<string>("template", "Project template name"); var outputOption = new Option<DirectoryInfo>( "--output", "Output directory") { IsRequired = false }; newCommand.AddArgument(templateArg); newCommand.AddOption(outputOption); newCommand.SetHandler((string template, DirectoryInfo? output) => { var dir = output?.FullName ?? Directory.GetCurrentDirectory(); Console.WriteLine($"Creating '{template}' project in {dir}"); }, templateArg, outputOption); // 'build' command var buildCommand = new Command("build", "Build the project"); var configOption = new Option<string>( "--configuration", () => "Debug", "Build configuration"); configOption.AddAlias("-c"); var verbosityOption = new Option<Verbosity>( "--verbosity", () => Verbosity.Normal, "Output verbosity"); verbosityOption.AddAlias("-v"); buildCommand.AddOption(configOption); buildCommand.AddOption(verbosityOption); buildCommand.SetHandler((string config, Verbosity verbosity) => { Console.WriteLine($"Building with configuration={config}, verbosity={verbosity}"); }, configOption, verbosityOption); // 'test' command with nested subcommands var testCommand = new Command("test", "Run tests"); var unitCommand = new Command("unit", "Run unit tests"); var integrationCommand = new Command("integration", "Run integration tests"); var filterOption = new Option<string?>("--filter", "Test filter expression"); unitCommand.AddOption(filterOption); unitCommand.SetHandler((string? filter) => { Console.WriteLine($"Running unit tests{(filter != null ? $" with filter: {filter}" : "")}"); }, filterOption); integrationCommand.SetHandler(() => { Console.WriteLine("Running integration tests"); }); testCommand.AddCommand(unitCommand); testCommand.AddCommand(integrationCommand); rootCommand.AddCommand(newCommand); rootCommand.AddCommand(buildCommand); rootCommand.AddCommand(testCommand); return await rootCommand.InvokeAsync(args); enum Verbosity { Quiet, Normal, Detailed, Diagnostic } // Usage: // myapp new webapp --output ./MyApp // myapp build -c Release -v Detailed // myapp test unit --filter "Category=Smoke" // myapp test integration ``` ## Options, Arguments, and Aliases | Concept | Description | Example | |---------|-------------|---------| | `Option<T>` | Named parameter with `--` prefix | `--output`, `-o` | | `Argument<T>` | Positional parameter (no prefix) | `myapp <file>` | | `AddAlias` | Short alias for an option | `-c` for `--configuration` | | `IsRequired` | Makes an option mandatory | `{ IsRequired = true }` | | `getDefaultValue` | Factory for default values | `() => "Debug"` | | `FromAmong` | Restricts to allowed values | `FromAmong("Debug", "Release")` | ## Argument Validation ```csharp using System.CommandLine; var portOption = new Option<int>("--port", "Server port"); portOption.AddValidator(result => { var port = result.GetValueForOption(portOption); if (port < 1024 || port > 65535) { result.ErrorMessage = "Port must be between 1024 and 65535"; } }); var fileArgument = new Argument<FileInfo>("file", "Input file"); fileArgument.AddValidator(result => { var file = result.GetValueForArgument(fileArgument); if (file is not null && !file.Exists) { result.ErrorMessage = $"File not found: {file.FullName}"; } }); // Restrict to specific values var envOption = new Option<string>("--environment"); envOption.FromAmong("Development", "Staging", "Production"); ``` ## Global Options ```csharp var verboseOption = new Option<bool>("--verbose", "Enable verbose logging"); verboseOption.AddAlias("-V"); var rootCommand = new RootCommand("My CLI"); rootCommand.AddGlobalOption(verboseOption); // Available to all subcommands var serveCommand = new Command("serve", "Start the server"); serveCommand.SetHandler((bool verbose) => { if (verbose) Console.WriteLine("Verbose mode enabled"); Console.WriteLine("Starting server..."); }, verboseOption); rootCommand.AddCommand(serveCommand); // Usage: myapp serve --verbose // Usage: myapp --verbose serve (global options work before or after subcommand) ``` ## Hosting Integration Integrate System.CommandLine with the .NET Generic Host for DI, configuration, and logging. ```csharp using System.CommandLine; using System.CommandLine.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; var rootCommand = new RootCommand("CLI with hosting"); var nameOption = new Option<string>("--name", "User name") { IsRequired = true }; rootCommand.AddOption(nameOption); rootCommand.SetHandler(async (IHost host) => { var greeter = host.Services.GetRequiredService<GreeterService>(); var parseResult = host.Services.GetRequiredService<ParseResult>(); var name = parseResult.GetValueForOption(nameOption)!; await greeter.GreetAsync(name); }); var builder = new CommandLineBuilder(rootCommand) .UseHost(hostBuilder => { hostBuilder.ConfigureServices(services => { services.AddTransient<GreeterService>(); }); hostBuilder.ConfigureLogging(logging => { logging.AddConsole(); logging.SetMinimumLevel(LogLevel.Information); }); }) .UseDefaults(); return await builder.Build().InvokeAsync(args); public class GreeterService(ILogger<GreeterService> logger) { public Task GreetAsync(string name) { logger.LogInformation("Greeting user: {Name}", name); Console.WriteLine($"Hello, {name}!"); return Task.CompletedTask; } } ``` ## Middleware ```csharp var builder = new CommandLineBuilder(rootCommand) .UseDefaults() .AddMiddleware(async (context, next) => { var sw = System.Diagnostics.Stopwatch.StartNew(); Console.WriteLine($"Executing: {context.ParseResult.CommandResult.Command.Name}"); await next(context); sw.Stop(); Console.WriteLine($"Completed in {sw.ElapsedMilliseconds}ms"); }); var parser = builder.Build(); return await parser.InvokeAsync(args); ``` ## File and Directory Arguments ```csharp var inputFile = new Argument<FileInfo>("input", "Input file path"); var outputDir = new Option<DirectoryInfo>( "--output-dir", () => new DirectoryInfo("."), "Output directory"); var convertCommand = new Command("convert", "Convert a file"); convertCommand.AddArgument(inputFile); convertCommand.AddOption(outputDir); convertCommand.SetHandler((FileInfo input, DirectoryInfo outDir) => { if (!input.Exists) { Console.Error.WriteLine($"File not found: {input.FullName}"); return; } Console.WriteLine($"Converting {input.Name} to {outDir.FullName}"); }, inputFile, outputDir); ``` ## Creating a dotnet Tool ```xml <!-- .csproj file --> <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <PackAsTool>true</PackAsTool> <ToolCommandName>mytool</ToolCommandName> <PackageId>MyOrg.MyTool</PackageId> <Version>1.0.0</Version> </PropertyGroup> <ItemGroup> <PackageReference Include="System.CommandLine" Version="2.0.0-beta4.*" /> </ItemGroup> </Project> ``` ```bash # Pack and install locally dotnet pack dotnet tool install --global --add-source ./nupkg MyOrg.MyTool # Usage mytool build -c Release mytool test unit --filter "Priority=1" ``` ## Best Practices - Use `RootCommand` with descriptive text as the entry point and organize functionality into `Command` subcommands rather than overloading the root with many options. - Add both long (`--configuration`) and short (`-c`) aliases for frequently used options to reduce typing in interactive use while keeping discoverability for scripts. - Use `Option<T>` with strongly-typed generics (`Option<int>`, `Option<FileInfo>`, `Option<Verbosity>`) instead of `Option<string>` with manual parsing to get automatic validation and help text. - Set `IsRequired = true` on mandatory options and provide `getDefaultValue` factories on optional ones so the help text accurately reflects what is required vs. optional. - Use `AddValidator` for custom validation rules (port ranges, file existence, format checks) to provide clear error messages before the handler runs. - Use `FromAmong` to restrict string options to a fixed set of allowed values (e.g., environments, log levels) with automatic validation and tab completion. - Integrate with `System.CommandLine.Hosting` for applications that need dependency injection, `IConfiguration`, or `ILogger` rather than constructing services manually in handlers. - Add `AddGlobalOption` for cross-cutting options like `--verbose`, `--output-format`, or `--no-color` that apply to all subcommands without repeating them. - Set `<PackAsTool>true</PackAsTool>` in the .csproj to distribute the CLI as a `dotnet tool` that users install with `dotnet tool install`. - Use `CommandLineBuilder.UseDefaults()` to enable automatic help (`--help`), version (`--version`), parse error reporting, and suggest-typo features without manual configuration.
Auf GitHub ansehen