Ploch.CommandLine.Spectre is an opinionated framework for building console applications on .NET
(the packages target .NET 10). It layers Spectre.Console.Cli on top
of Microsoft.Extensions.Hosting, so a CLI gets dependency injection, configuration, logging,
validation and output formatting from one builder chain.
| Package | Purpose |
|---|---|
Ploch.CommandLine.Spectre |
Core framework: AppBuilder, the command base classes, the settings pipeline and the output pipeline. |
Ploch.CommandLine.Spectre.Serilog |
Opt-in Serilog logging, switched on with UseSerilog on the builder. |
Ploch.CommandLine.Spectre.FluentValidation |
Validation of command settings with FluentValidation validators. |
Ploch.CommandLine.UseCases |
Commands that delegate to an IResultUseCase built on Ardalis.Result. |
dotnet new console -n greeter
cd greeter
dotnet add package Ploch.CommandLine.SpectreDefine a settings class and a command (GreetCommand.cs):
using System.ComponentModel;
using Ploch.CommandLine.Spectre;
using Ploch.CommandLine.Spectre.Commands;
using Ploch.CommandLine.Spectre.Output;
using Spectre.Console.Cli;
public class GreetSettings : CommandSettings
{
[CommandArgument(0, "<name>")]
[Description("The name to greet.")]
public string Name { get; init; } = string.Empty;
[CommandOption("-l|--loud")]
[Description("Shout the greeting.")]
public bool Loud { get; init; }
}
public class GreetCommand(
CommandArgumentsRootProcessor settingsProcessor,
ICommandSettingsValidator<GreetSettings> validator,
IExceptionHandler exceptionHandler,
IOutput output)
: AppCommand<GreetSettings>(settingsProcessor, validator, exceptionHandler, output)
{
protected override ExitCode DoExecute(
CommandContext context, GreetSettings settings, CancellationToken cancellationToken)
{
var greeting = $"Hello, {settings.Name}!";
Output.WriteLine(settings.Loud ? greeting.ToUpperInvariant() : greeting);
return ExitCode.Success;
}
}AppCommand<TSettings> takes the settings processor, the validator, the exception handler and an
IOutput, which it exposes as the Output property. Anything else the command needs is an ordinary
constructor parameter resolved from the container.
Wire it up in Program.cs:
using Ploch.CommandLine.Spectre;
using Spectre.Console.Cli;
// The builder owns the Ctrl+C handler and cancellation source it creates; dispose it after the run.
using var appBuilder = AppBuilder.Create(args)
.WithName("greeter")
.WithVersion(new Version(1, 0, 0))
.WithDescription("A greeting utility.");
var executor = appBuilder.ConfigureCommandApp(config =>
{
config.SetApplicationName("greeter");
config.AddCommand<GreetCommand>("greet")
.WithDescription("Greet someone by name.")
.WithExample("greet", "Alice", "--loud");
});
return executor.Run(args);$ dotnet run -- greet Alice --loud
HELLO, ALICE!That is standard output. The start-up banner and the Executing command greet line go to standard
error, so greeter greet Alice --loud | cat prints just HELLO, ALICE!. A command line Spectre
cannot parse, and settings that fail validation, exit with code 2; the
exit codes are part of the contract.
- Documentation site — overview, core concepts and the generated API reference.
- Getting started — build a CLI from an empty directory, one feature at a time: commands, configuration, dependency injection, sub-commands, validation, token expansion, use cases, exit codes, cancellation, logging and testing.
- Sample application — a complete multi-level CLI that exercises every feature, with the output and exit code of every command.
- Release notes — what changed in each version.
- Dependency updates — how NuGet and GitHub Actions dependencies are kept current, and why NuGet is handled by a scheduled workflow rather than by Dependabot.
- AI knowledge base — architecture, stack, conventions and backlog written
for AI agents;
CLAUDE.mdis its entry point.
Clone mrploch-development as a sibling directory first — Directory.Packages.props imports the
shared package versions from it, so restore fails without it:
git clone https://github.com/mrploch/ploch-commandline.git
git clone https://github.com/mrploch/mrploch-development.git
cd ploch-commandline
dotnet build Ploch.CommandLine.Spectre.slnx
dotnet test Ploch.CommandLine.Spectre.slnxThe main solution needs no GitHub Packages token. It only ever references stable Ploch.*
versions, and those are on nuget.org, so a build with GH_PACKAGES_TOKEN unset normally restores
successfully — the 401 (Unauthorized) warnings from the unauthenticated GitHub Packages feed are
expected. That "stable versions only" rule is a policy, enforced by a check in CI.
Tokenless restore is best-effort rather than guaranteed: the GitHub Packages source stays eligible
while unauthenticated, and NuGet can surface its failure as NU1301 before nuget.org answers. If
you hit that, retry, or set a token. The same applies to the
sample application, which pins the stable release of this
repository's own packages and restores it from nuget.org in its default mode.
See CONTRIBUTING.md for the reasoning, the escape hatch for working against
unreleased ploch-common code, and the rest of the contributor setup.