Do you use Cocona for building great command line tools in .NET?


When building command line applications in .NET, you need a framework that makes argument parsing, validation, and help generation simple and intuitive. Cocona is a lightweight and powerful framework that turns your C# methods into fully-featured CLI commands with minimal boilerplate code.

Cocona has many built-in features that make it feel familiar to .NET developers.

Why use Cocona?

Cocona offers several advantages over manual argument parsing or other CLI frameworks:

  • Simple and intuitive: Transform regular C# methods into CLI commands
  • Automatic help generation: Built-in help text and usage information
  • Type safety: Strong typing for command parameters and options
  • Dependency injection: Built-in DI container support
  • Validation support: Integration with data annotations for parameter validation
  • Async support: First-class support for async/await patterns
  • Multiple commands: Easy support for sub-commands and complex CLI structures

Basic Example

Here's how to create a simple CLI tool with Cocona:

// Manual argument parsing - error-prone and verbose
class Program
{
    static void Main(string[] args)
    {
        if (args.Length == 0)
        {
            Console.WriteLine("Usage: myapp <name> [--greeting <greeting>]");
            return;
        }

        string name = args[0];
        string greeting = "Hello";

        for (int i = 1; i < args.Length; i++)
        {
            if (args[i] == "--greeting" && i + 1 < args.Length)
            {
                greeting = args[i + 1];
                i++;
            }
        }

        Console.WriteLine($"{greeting}, {name}!");
    }
}

Figure: Bad example - Manual argument parsing is error-prone and verbose.

using Cocona;

var app = CoconaApp.Create();
app.AddCommand("greet", (string name, string greeting = "Hello") => 
{
    Console.WriteLine($"{greeting}, {name}!");
});
app.Run();

Figure: Good example - Cocona simplifies command line argument parsing and usage. 😌

Validation

Cocona integrates seamlessly with data annotations for parameter validation.

using Cocona;
using System.ComponentModel.DataAnnotations;

public class FileProcessor
{
    public void ProcessFiles(
        [Argument] string inputPath,
        [Argument, StringLength(50)] string fileName,
        [Argument] string? optionalMetadata,
        [Option('o', Description = "Output directory")] string outputPath = "./output",
        [Option, Range(1, 10)] int threads = 1,
        [Option] bool verbose = false)
    {
        if (verbose)
            Console.WriteLine($"Processing {inputPath} with {threads} threads...");

        // Your file processing logic here
        Console.WriteLine($"Files processed and saved to {outputPath}");
    }
}

var app = CoconaApp.Create();
app.AddCommands<FileProcessor>();
app.Run();

Multiple Commands Example

For more complex CLI tools with multiple commands:

using Cocona;

public class DatabaseCommands
{
    [Command("migrate")]
    public async Task MigrateDatabase(
        [Option] string connectionString,
        [Option] bool dryRun = false)
    {
        Console.WriteLine($"Migrating database (dry run: {dryRun})...");
        // Migration logic
    }

    [Command("seed")]
    public async Task SeedDatabase(
        [Option] string connectionString,
        [Option] string dataFile = "seed.json")
    {
        Console.WriteLine($"Seeding database from {dataFile}...");
        // Seeding logic
    }
}

var app = CoconaApp.Create();
app.AddCommands<DatabaseCommands>();
app.Run();

This creates a CLI with commands like:

  • myapp migrate --connection-string "..." --dry-run
  • myapp seed --connection-string "..." --data-file "custom.json"

Integration with Dependency Injection

Cocona works great with .NET's built-in dependency injection:

public class EmailCommands
{
    private readonly EmailService _emailService;

    public EmailCommands(EmailService emailService)
    {
        _emailService = emailService;
    }

    [Command]
    public void Send(string to, string subject, string body)
    {
        _emailService.SendEmail(to, subject, body);
    }
}

var builder = CoconaApp.CreateBuilder();
builder.Services.AddTransient<EmailService>();
builder.Services.AddLogging(b => b.AddConsole());

var app = builder.Build();
app.AddCommands<EmailCommands>();
app.Run();

For more information, visit the Cocona GitHub repository.

Tip: Improve your CLI tool's UI with tools like Colorful.Console for colored output, or Spectre.Console for rich terminal applications.


We open source.Loving SSW Rules? Star us on GitHub. Star
Stand by... we're migrating this site to TinaCMS