Release Notes
8.0.9 - Roslyn Code Analysis
New Package
Albatross.CommandLine.CodeAnalysis- New companion Roslyn analyzer package that catches common attribute misuse at compile time. Reference it as a development-only dependency — it adds no runtime overhead:<PackageReference Include="Albatross.CommandLine.CodeAnalysis" Version="*"> <PrivateAssets>all</PrivateAssets> </PackageReference>
Diagnostics
| ID | Severity | Description |
|---|---|---|
| ACL0001 | Warning | Two or more [Option]-annotated properties on a [Verb] class have names that are identical case-insensitively, producing duplicate CLI options (e.g. Name and name both map to --name). |
| ACL0002 | Warning | When VerbAttribute.BaseParamsClass is set, the params class must derive from the specified type. Applies to both class-targeted and assembly-targeted verb attributes. |
| ACL0003 | Error | The first type argument TOption of OptionHandlerAttribute<TOption, THandler> (or the three-argument variant) must be the attributed class itself or one of its base classes. Violations cause a compiler error in the generated code. |
| ACL0004 | Warning | A property has both [Option] and [Argument] applied simultaneously, which is not allowed. |
8.0.8 - Bug Fix & Tracker Improvements
Bug Fix
CommandOptionParameterSetup.ContextValueTypeType Correction - Fixed the property type fromINamedTypeSymbol?toITypeSymbol?in the source generator IR. This was causing aInvalidCastExceptionat code generation time when a[OptionHandler<TOption, THandler, TContextValue>]attribute used an array type (e.g.,int[]) as the context value type, since array types areIArrayTypeSymboland cannot be cast toINamedTypeSymbol.
Improvements
- Tracker File Read Sharing -
TrackerOptionnow opens the tracker file withFileShare.Read, allowing other processes (log viewers, monitoring tools) to read the file concurrently while the tracker is writing. Previously the file was opened exclusively, blocking any concurrent readers. - Tracker StreamWriter
leaveOpen- Added explicitleaveOpen: trueto theStreamWriterconstructor inTrackerOptionto prevent premature stream closure and ensure the underlyingFileStreamlifetime is correctly managed.
Tests
- Added
TestTrackerFileSharetest class verifying that the tracker file can be opened for reading by another handle while actively being written.
8.0.7 - Logging Bug Fix
Bug Fix
- Albatross.Logging 10.0.2 Bug -
Albatross.Logging10.0.2 has a bug whereUseConsoledoes not set the global minimum level. This caused the console sink to not respect the--verbosityoption correctly. Updated toAlbatross.Logging10.0.3 which fixes this issue.
Dependency Update
- Updated
Albatross.Loggingfrom 10.0.2 to 10.0.3
8.0.6 - Improved Serilog Configuration
Improvements
File-Based Serilog Configuration - The
WithSerilog()extension now supports loading Serilog settings from configuration files:- Loads
serilog.jsonfrom the application's base directory (if present) - Supports environment-specific files like
serilog.Development.json - Console logging is added on top of file-based configuration based on the
--verbosityoption - This allows advanced Serilog configuration (file sinks, seq, etc.) without code changes
- Loads
Dependency Update - Updated
Albatross.Loggingfrom 10.0.1 to 10.0.2
Internal
- Fixed multiline package description in
Albatross.CommandLine.csproj
8.0.5 - TrackerOption & Automatic Resource Disposal
New Features
TrackerOption- New reusable option inAlbatross.CommandLine.Inputsfor resumable long-running jobs:- Tracks processed items in a file, automatically skipping already-completed work on restart
- Immediate write-through persistence (survives process kill, power failure)
- Thread-safe for concurrent batch processing
- Case-insensitive by default, with
CaseSensitiveTrackerOptionvariant - Proper cancellation handling (
OperationCanceledExceptionpropagates, other errors are logged)
[UseOption<TrackerOption>] public Tracker? Tracker { get; init; } // In handler: await tracker.ProcessIfNew(itemId, (ct) => ProcessItem(ct), logger, cancellationToken);Automatic Resource Disposal -
CommandContextnow implementsIAsyncDisposableand automatically disposes values stored via option handlers:- Values implementing
IAsyncDisposableare disposed asynchronously - Values implementing
IDisposableare disposed synchronously - No manual cleanup required for resources created by option handlers
- Values implementing
Documentation
- Added comprehensive TrackerOption guide
- Updated Command Context with automatic disposal documentation
8.0.4 - Customizable Verbosity & New Inputs
New Features
- Customizable Default Verbosity - The global
VerbosityOptionnow supports changing the default verbosity level:// Change global default CommandBuilder.VerbosityOption.DefaultValueFactory = _ => VerbosityOption.Info; - Per-Command Verbosity Override - Individual commands can override the default verbosity using
partial void Initialize()to add their ownVerbosityOption - New
TimeZoneOption- Added a reusable option inAlbatross.CommandLine.Inputsfor time zone input with validation (supports both Windows and IANA formats) - Disable Logging Option - New
Parse(args, false)overload allows disabling logging entirely when not needed
Improvements
- Reduced Log Noise - Internal framework logging changed from
InformationtoDebuglevel for cleaner output - New Extension Method - Added
GetVerbosityOption()extension onParseResultto retrieve the active verbosity option
Documentation
- Added comprehensive Logging & Verbosity guide
- Added System.CommandLine Migration guide for migrating from beta4 to 2.0.2
8.0.3 - Bug Fix & Documentation
- Bug Fix - Changed
MaxArityfor collection arguments fromint.MaxValueto100_000to align with theMaximumArityconstant defined in System.CommandLine 2.0.2 - Dependency Update - Updated
System.CommandLineto version 2.0.2 - Packaging - Disabled symbol package generation for
Albatross.CommandLine.CodeGen(analyzer packages do not support symbol packages) - Documentation - Added comprehensive XML documentation comments to all public APIs across the library
8.0.2 - Documentation & Packaging
- Documentation - Published comprehensive documentation site with quick start guide, core concepts, migration instructions, and AI agent guidance
- SourceLink - Added
Microsoft.SourceLink.GitHubfor source-stepping debugging support - Symbol packages - Now publishing
.snupkgsymbol packages to NuGet - Package metadata - Added package tags for improved discoverability, release notes URL, and documentation link
8.0.1 - Major Rewrite
Version 8 is a complete redesign of Albatross.CommandLine, driven by the stable release of System.CommandLine 2.0.1 (previously 2.0.0-beta4). The upstream library introduced significant breaking changes that required rethinking our approach.
Why a Rewrite?
- System.CommandLine 2.0.1 removed
InvocationContextand changed how commands, options, and handlers interact - This created an opportunity to simplify the library's architecture and improve the developer experience
- The new design is more idiomatic, leverages modern C# features, and provides better async/cancellation support
Key Architectural Changes
| Area | v7 | v8 |
|---|---|---|
| Handler execution | Sync Invoke(InvocationContext) |
Async InvokeAsync(CancellationToken) |
| Parameter injection | IOptions<T> wrapper |
Direct T injection |
| Handler specification | Constructor parameter | Generic type argument [Verb<THandler>] |
| Attributes namespace | Albatross.CommandLine |
Albatross.CommandLine.Annotations |
| Property annotation | Implicit (all properties are options) | Explicit (must use [Option] or [Argument]) |
| Entry point | Custom Setup class |
Generic CommandHost |
| Class naming | *Options suffix |
*Params suffix |
New Capabilities
- Reusable Parameters - Create custom
Option<T>andArgument<T>classes with[UseOption<T>]and[UseArgument<T>] - Option Preprocessing - Async validation with dependency injection via
IAsyncOptionHandler<T> - Input Transformation - Transform raw input into complex objects before reaching the handler
- Partial Command Classes - Customize generated commands via
partial void Initialize() - Built-in Input Types - Ready-to-use file/directory validators in
Albatross.CommandLine.Inputs
Migration
This is a breaking release. See the Migration Guide for step-by-step upgrade instructions.
7.8.7
- Change the property type of ArgumentAttribute.ArityMin and ArgumentAttribute.ArityMax from int? to int because Nullable
is not a valid Attribute property type
7.8.5
VerbAttributecan now target an assembly. When doing so, a command will be generated if itsOptionsClassproperty is populated.albatross.commandline.codegen.debug.txtwill no longer be generated by default. To turn it on, create the following entries in the project file:<PropertyGroup> <EmitAlbatrossCodeGenDebugFile>true</EmitAlbatrossCodeGenDebugFile> </PropertyGroup> <ItemGroup> <CompilerVisibleProperty Include="EmitAlbatrossCodeGenDebugFile" /> </ItemGroup>
7.8.3
- Bug fix on the
OptionAttribute.Requiredproperty. It is now working as expected for required collection and boolean types.
7.8.1 - Add Argument Support
- ^ Incorrect version for this release. Should have been a minor instead of patch release
- Add support for arguments.
- Remove
OptionAttribute.Ignoreproperty and replace its functionality with a new attribute classAlbatross.CommandLine.IgnoreAttribute
7.8.0 - Add and implement the logic for the OptionAttribute.DefaultToInitializer Property
- If the
OptionAttribute.DefaultToInitializerproperty is set totrue, the code generator will generate a default value using the initializer value of the property.
7.7.0 - Behavior Adjustment
- If the
VerbAttributeis created without the handler type parameter, it will default to useHelpCommandHandlerinstead ofDefaultCommandHandler. - References
Spectre.Consoleversion 0.49.1 and Add extension methods for Spectre atSpectreExtensions. - Rename
OptionAttribute.Skipproperty toOptionAttribute.Ignoreproperty.
7.6.0 - Sub Command Support + Upgrades in Different Areas
- The
VerbAttributecan now be created without the handler type parameter. The system will use theDefaultCommandHandler. - New sub command support. See Sub Commands.
- Create
HelpCommandHandlerthat will display the help message of a command - If the RootCommand is invoke without any command, it will display the help message without the error message -
Required command was not provided.. Same behavior applies to any other parent commands. - If a command has its own handler, it will no longer be overwritten with the
GlobalCommandHandler. This gives developers more flexibility in creating custom commands. - Add help messages to the global options.