Clap.Net 0.2.36

There is a newer version of this package available.
See the version list below for details.
dotnet add package Clap.Net --version 0.2.36
                    
NuGet\Install-Package Clap.Net -Version 0.2.36
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Clap.Net" Version="0.2.36" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Clap.Net" Version="0.2.36" />
                    
Directory.Packages.props
<PackageReference Include="Clap.Net" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Clap.Net --version 0.2.36
                    
#r "nuget: Clap.Net, 0.2.36"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Clap.Net@0.2.36
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Clap.Net&version=0.2.36
                    
Install as a Cake Addin
#tool nuget:?package=Clap.Net&version=0.2.36
                    
Install as a Cake Tool

Clap.Net

A modern, type-safe command-line argument parser for .NET using source generation.

Clap.Net brings the power and elegance of Rust's clap library to the .NET ecosystem. Define your CLI with attributes and properties, and let the source generator handle the rest—no reflection, no runtime overhead, just clean, fast, generated code.

Why Clap.Net?

Zero Runtime Overhead Source generators produce parsing code at compile time. No reflection, no performance penalties—just pure, optimized C# code.

Type Safety First Your command-line interface is defined using strongly-typed classes and properties. Catch errors at compile time, not runtime.

Batteries Included Automatic help generation, version handling, environment variable fallback, subcommands, and rich argument types—all out of the box.

Developer Friendly Leverage C# language features like required properties, nullable types, and pattern matching. Your CLI definition is just normal C# code with a few attributes.

Quick Start

Installation

dotnet add package Clap.Net

Basic Example

Define a command with a simple attribute:

using Clap.Net;

[Command(Name = "greet", About = "A friendly greeter", Version = "1.0.0")]
public partial class GreetCommand
{
    [Arg(Short = 'n', Long = "name", Help = "The name to greet")]
    public string Name { get; init; } = "World";

    [Arg(Short = 'v', Long = "verbose")]
    public bool Verbose { get; init; }

    public required string Message { get; init; }
}

Parse and use it:

var cmd = GreetCommand.Parse(args);
Console.WriteLine($"{cmd.Message}, {cmd.Name}!");
if (cmd.Verbose)
    Console.WriteLine("Verbose mode enabled.");
$ dotnet run -- "Hello" --name "Alice" -v
Hello, Alice!
Verbose mode enabled.

$ dotnet run -- --help
# Displays auto-generated help text

Complete Example with Subcommands

Clap.Net makes complex CLIs easy to build and maintain:

using Clap.Net;

namespace Clap.Examples;

[Command(Name = "image-converter", About = "Convert and manage images")]
public partial class ImageConverter
{
    [Arg(Help = "The path of the image to convert")]
    public required string Path { get; init; }

    [Arg(Help = "The destination path (default: <file-name>.[new-ext])", Last = true)]
    public string? DestinationPath { get; init; }

    [Arg(Short = 'e', Long = "extension", Help = "Target image format")]
    public string? Extension { get; init; }

    [Arg(Short = 'v', Long = "verbose", Help = "Enable verbose output")]
    public bool Verbose { get; set; }

    [Command]
    public ImageConverterCommands? Command { get; init; }
}

[SubCommand]
public partial class ImageConverterCommands
{
    [Command(About = "Show conversion history")]
    public partial class History : ImageConverterCommands;

    [Command(About = "Publish converted images")]
    public partial class Publish : ImageConverterCommands
    {
        [Arg(Help = "The URL to publish the image to")]
        public required string[] UploadUrl { get; init; }
    }
}

Using the parser:

var app = ImageConverter.Parse(args);

switch (app.Command)
{
    case ImageConverterCommands.History:
        Console.WriteLine("Showing conversion history...");
        break;

    case ImageConverterCommands.Publish publish:
        Console.WriteLine($"Publishing to {string.Join(", ", publish.UploadUrl)}");
        break;

    default:
        Console.WriteLine($"Converting {app.Path} to {app.Extension ?? "default format"}");
        break;
}

Command-line usage:

# Basic conversion
$ dotnet run -- -v "~/Downloads/tree.png" "~/Downloads/tree.jpg"

# With subcommand
$ dotnet run -- "~/Downloads/tree.png" -e "jpg" publish "https://yourdomain.com/upload"

# Get help for subcommands
$ dotnet run -- publish --help

Argument Validation

Clap.Net supports the full System.ComponentModel.DataAnnotations validation framework, allowing you to validate argument values at parse time with clear error messages.

Built-in Validators

Use standard .NET validation attributes to enforce constraints:

using System.ComponentModel.DataAnnotations;

[Command(Name = "server", About = "Start a web server")]
public partial class ServerCommand
{
    [Arg(Long = "port")]
    [Range(1, 65535, ErrorMessage = "Port must be between 1 and 65535")]
    public required int Port { get; init; }

    [Arg(Long = "host")]
    [RegularExpression(@"^[a-zA-Z0-9.-]+$", ErrorMessage = "Invalid hostname")]
    public string Host { get; init; } = "localhost";

    [Arg(Long = "email")]
    [EmailAddress(ErrorMessage = "Invalid email address")]
    public required string Email { get; init; }

    [Arg(Long = "username")]
    [StringLength(20, MinimumLength = 5)]
    [RegularExpression(@"^[a-zA-Z0-9_]+$", ErrorMessage = "Only letters, numbers, and underscores allowed")]
    public required string Username { get; init; }
}

Available validators:

  • [Range(min, max)] - Numeric range validation
  • [StringLength(max, MinimumLength = min)] - String length constraints
  • [RegularExpression("pattern")] - Regex pattern matching
  • [EmailAddress], [Phone], [Url], [CreditCard] - Format validators
  • Multiple validators can be combined on a single property

Custom Validators

Create your own validators by inheriting from ValidationAttribute:

public class PortRangeAttribute : ValidationAttribute
{
    public override bool IsValid(object? value)
    {
        if (value is int port)
            return port >= 1 && port <= 65535;
        return false;
    }
}

[Command]
public partial class MyApp
{
    [Arg(Long = "port")]
    [PortRange(ErrorMessage = "Invalid port number")]
    public required int Port { get; init; }
}

Handling Validation Errors

Validation failures return a ParseError with detailed messages:

var result = ServerCommand.TryParse(args);

if (result.IsT3) // ParseError
{
    Console.Error.WriteLine(result.AsT3.Message);
    // Output: "Validation failed for 'Port': Port must be between 1 and 65535"
    return 1;
}

var cmd = result.AsT0;
// Use validated command...

Multi-Value Arguments

Clap.Net provides flexible ways to accept multiple values for a single argument, with different behaviors depending on how you define your properties.

Array Arguments (Per-Flag Values)

For named arguments with array types (string[], int[], etc.), each flag invocation captures one value. To collect multiple values, repeat the flag:

[Command]
public partial class BenchmarkCommand
{
    [Arg(Short = 't', Long = "test", Help = "Tests to run")]
    public string[]? Tests { get; init; }

    // Positional array consumes all remaining positional values
    public string[] Extensions { get; init; } = ["js", "ts"];
}

Usage:

# Single value - Tests gets ["unit"], Extensions gets ["py", "go"]
$ app -t unit py go

# Multiple values - repeat the flag for each value
$ app -t unit -t integration py go
# Tests gets ["unit", "integration"], Extensions gets ["py", "go"]

# Without -t, all values go to positional
$ app py go js
# Tests is null/empty, Extensions gets ["py", "go", "js"]

Key behavior:

  • Named array arguments: One value per flag invocation
  • Positional array arguments: Greedy - consumes all remaining positional values
  • This prevents named arrays from "stealing" values intended for positional arguments

Action.Append (Alternative Pattern)

For collection types with Action.Append, the behavior is similar but uses IEnumerable<T>:

[Command]
public partial class TagCommand
{
    [Arg(Short = 't', Long = "tag", Action = ArgAction.Append)]
    public IEnumerable<string> Tags { get; init; } = [];
}

Usage:

$ app -t "v1.0" -t "release" -t "stable"
# Tags gets ["v1.0", "release", "stable"]

When to Use Each

Pattern Type Behavior Use Case
Array string[] One value per flag Named args that need to work with positional args
Action.Append IEnumerable<T> One value per flag Named args only, more explicit about appending
Positional Array string[] Greedy (all remaining) Variadic trailing arguments (like files...)

Examples

File processor with filters and files:

[Command]
public partial class ProcessFiles
{
    [Arg(Short = 'e', Long = "exclude")]
    public string[] ExcludePatterns { get; init; } = [];

    public string[] Files { get; init; } = [];  // Positional
}

// Usage:
$ app -e "*.tmp" -e "*.log" file1.txt file2.txt file3.txt
// ExcludePatterns: ["*.tmp", "*.log"]
// Files: ["file1.txt", "file2.txt", "file3.txt"]

Test runner with specific tests and extensions:

[Command]
public partial class TestRunner
{
    [Arg(Short = 't')]
    public string[]? Tests { get; init; }

    public string[] Extensions { get; init; } = ["js", "ts", "py"];
}

// Usage:
$ app -t unit -t integration go rb
// Tests: ["unit", "integration"]
// Extensions: ["go", "rb"]

Key Features

Strongly-Typed Parsing Define your CLI interface using classes, properties, and attributes. Get compile-time safety and IntelliSense support.

Powerful Subcommands Create complex command hierarchies using nested classes. Each subcommand can have its own arguments and options.

Rich Argument Types Support for strings, numbers, bools, enums, arrays, and any type with TryParse. Custom parsing logic is straightforward.

Automatic Help Generation Help text is generated from your attributes and XML documentation comments. Use --help on any command or subcommand.

Environment Variable Fallback Options can fallback to environment variables when not provided on the command line.

Negatable Flags Boolean flags can be negated with --no-* syntax for flexible configuration.

Debugging Generated Code

If you're troubleshooting source generation issues or want to inspect the generated parser code, add this to your .csproj:

<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
    <CompilerGeneratedFilesOutputPath>bin/Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

Generated files will be written to bin/Generated/, allowing you to step through the parser logic and understand how arguments are processed.

Feature Roadmap

Clap.Net aims for near feature-parity with clap-rs. Here's what's implemented and what's coming:

Implemented

  • Commands

    • Root command definition with Name, About, and Version
    • Subcommands with nested class hierarchies
    • Automatic help text for all commands
  • Arguments & Options

    • Short (-v) and long (--verbose) flags
    • Positional arguments with order-based mapping
    • Required vs optional arguments
    • Environment variable fallback
    • Default values via C# property initializers
    • Multiple values (arrays and collections)
    • TryParse support for custom types
    • Custom parser functions via ValueParser attribute
    • Argument actions (Set, Append, Count)
    • Full ValidationAttribute support (Range, StringLength, RegularExpression, EmailAddress, custom validators)
  • Flags

    • Boolean flags (presence/absence)
    • Negatable flags (--no-debug)
  • Help & Version

    • Automatic --help generation
    • Automatic --version handling
    • Custom help text from XML docs

Coming Soon

  • Argument value suggestions and completion
  • More flexible argument ordering
  • Improved error messages

Contributing

Clap.Net is actively developed and there's plenty of work to do! Pull requests are welcome for:

  • Bug fixes and performance improvements
  • New features from the roadmap
  • Documentation and examples
  • Test coverage

Check out the CLAUDE.md file for architectural guidance and development patterns.

License

MIT License - see LICENSE for details

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.39 432 2/20/2026
0.2.38 117 2/19/2026
0.2.37 108 2/16/2026
0.2.36 111 2/11/2026
0.1.35-beta 103 2/11/2026
0.1.34-beta 105 2/11/2026
0.1.33-beta 106 2/11/2026
0.1.32-beta 416 1/17/2026
0.1.31-beta 141 12/29/2025
0.1.30-beta 254 10/30/2025
0.1.29-beta 547 9/17/2025
0.1.28-beta 358 9/16/2025
0.1.27-beta 532 9/2/2025
0.1.26-beta 255 8/29/2025
0.1.24-beta 263 8/27/2025
0.1.23-beta 267 8/27/2025
0.1.22-beta 291 8/7/2025
0.1.21-beta 288 8/6/2025
0.1.20-beta 299 8/6/2025
0.1.19-beta 292 8/6/2025
Loading failed