Promty 0.1.0

dotnet add package Promty --version 0.1.0
                    
NuGet\Install-Package Promty -Version 0.1.0
                    
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="Promty" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Promty" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Promty" />
                    
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 Promty --version 0.1.0
                    
#r "nuget: Promty, 0.1.0"
                    
#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 Promty@0.1.0
                    
#: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=Promty&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Promty&version=0.1.0
                    
Install as a Cake Tool

<div align="center"> <img src="gpx/logo6.png" alt="Promty Logo" width="200"/>

Promty

A powerful and flexible command-line parser and command executor framework for .NET applications. Build beautiful CLI tools with minimal boilerplate code. </div>

Features

  • 🎯 Type-safe argument binding - Automatically bind command-line arguments to strongly-typed classes
  • 🚩 Long and short flags - Support for both --verbose and -v style flags
  • 📝 Automatic help generation - Beautiful, table-formatted help text generated from attributes
  • Process command execution - Easily wrap external CLI tools
  • 🎨 Attribute-based configuration - Use simple attributes to configure commands and arguments
  • Validation - Automatic validation for required arguments
  • 🔄 Flexible architecture - Extend Command<TArgs> or ProcessCommand base classes

Installation

dotnet add package Promty

Quick Start

1. Create a Command

using Promty;

[Description("greet", "Greets a person by name")]
public class GreetCommand : Command<GreetCommand.Args>
{
    public class Args
    {
        [Description("name", "The name of the person to greet")]
        public string Name { get; set; } = string.Empty;

        [FlagAlias("uppercase", 'u')]
        [Description("Print the greeting in uppercase")]
        public bool Uppercase { get; set; }

        [FlagAlias("repeat", 'r')]
        [Description("Number of times to repeat the greeting")]
        public int? Repeat { get; set; }
    }

    public override Task<int> ExecuteAsync(Args args)
    {
        var greeting = $"Hello, {args.Name}!";

        if (args.Uppercase)
        {
            greeting = greeting.ToUpper();
        }

        var repeat = args.Repeat ?? 1;
        for (int i = 0; i < repeat; i++)
        {
            Console.WriteLine(greeting);
        }

        return Task.FromResult(0);
    }
}

2. Set Up the Executor

using System.Reflection;
using Promty;

var executor = new CommandExecutor();
executor.RegisterCommandsFromAssembly(Assembly.GetExecutingAssembly());

return await executor.ExecuteAsync(args);

3. Run Your CLI

# Show available commands
dotnet run

# Run with arguments
dotnet run -- greet Alice --uppercase -r 3

# Output:
# HELLO, ALICE!
# HELLO, ALICE!
# HELLO, ALICE!

Command Types

Standard Commands

Standard commands use typed argument binding with automatic parsing and validation.

[Description("copy", "Copies a file from source to destination")]
public class CopyCommand : Command<CopyCommand.Args>
{
    public class Args
    {
        [Description("source", "The source file path")]
        public string Source { get; set; } = string.Empty;

        [Description("destination", "The destination file path")]
        public string Destination { get; set; } = string.Empty;

        [FlagAlias("verbose", 'v')]
        [Description("Show detailed output")]
        public bool Verbose { get; set; }

        [FlagAlias("overwrite", 'o')]
        [Description("Overwrite existing files")]
        public bool Overwrite { get; set; }
    }

    public override Task<int> ExecuteAsync(Args args)
    {
        // Implementation here
        File.Copy(args.Source, args.Destination, args.Overwrite);
        return Task.FromResult(0);
    }
}

Process Commands

Process commands forward all arguments to an external executable. Perfect for wrapping existing CLI tools.

[Description("git", "Execute git commands")]
public class GitCommand : ProcessCommand
{
    protected override string ExecutablePath => "git";
}

Usage:

dotnet run -- git status
dotnet run -- git commit -m "Initial commit"
dotnet run -- git --version

Attributes

DescriptionAttribute

Use [Description] for both commands and arguments:

For Commands:

[Description("command-name", "Command description")]
public class MyCommand : Command<MyCommand.Args>

For Positional Arguments:

[Description("arg-name", "Argument description")]
public string MyArgument { get; set; }

For Flag Arguments:

[FlagAlias("verbose", 'v')]
[Description("Show detailed output")]
public bool Verbose { get; set; }

FlagAliasAttribute

  • [FlagAlias(long, short)] - Defines flag aliases
    • [FlagAlias("verbose", 'v')] - Both long and short
    • [FlagAlias("verbose")] - Long only
    • [FlagAlias('v')] - Short only

Argument Types

Promty supports automatic type conversion for:

  • string
  • int, long, double
  • bool
  • Nullable versions: int?, bool?, etc.
  • [Flags] enums (see below)

Argument Rules

  1. Positional arguments (without [FlagAlias] and not [Flags] enums) are required and must come before flags
  2. Flag arguments (with [FlagAlias]) are optional
  3. [Flags] enum properties are automatically treated as optional flags
  4. Boolean flags don't require values: --verbose is equivalent to --verbose true

Flags Enums

Instead of defining multiple boolean properties, you can use a [Flags] enum to group related flags together. Each enum value becomes an individual command-line flag that can be combined.

[Description("build", "Build a project with options")]
public class BuildCommand : Command<BuildCommand.Args>
{
    [Flags]
    public enum BuildOptions
    {
        None = 0,
        [FlagAlias("verbose", 'v')]
        [Description("Enable verbose output")]
        Verbose = 1,
        [FlagAlias("debug", 'd')]
        [Description("Build in debug mode")]
        Debug = 2,
        [Description("Disable build cache")]
        NoCache = 4,
        [Description("Skip running tests")]
        SkipTests = 8
    }

    public class Args
    {
        [Description("project", "Project name")]
        public string Project { get; set; } = string.Empty;

        // No [FlagAlias] needed on the property!
        public BuildOptions Options { get; set; }
    }

    public override Task<int> ExecuteAsync(Args args)
    {
        Console.WriteLine($"Building {args.Project}");

        if (args.Options.HasFlag(BuildOptions.Verbose))
            Console.WriteLine("Verbose mode enabled");

        if (args.Options.HasFlag(BuildOptions.Debug))
            Console.WriteLine("Debug mode enabled");

        return Task.FromResult(0);
    }
}

Usage:

# Combine multiple flags
dotnet run -- build MyProject --verbose --debug --skip-tests

# Use short aliases
dotnet run -- build MyProject -v -d

# Mix aliases with kebab-case names
dotnet run -- build MyProject -v --no-cache

Flags Enum Features:

  • Each enum field becomes an individual flag in the help text
  • Use [FlagAlias] on enum fields for custom long/short aliases
  • Enum fields without [FlagAlias] auto-convert to kebab-case (e.g., NoCache--no-cache)
  • Use [Description] on enum fields to provide help text
  • The None = 0 value is automatically excluded from help output
  • Multiple flags can be combined and are stored as a bitwise combination

Help Text

Promty automatically generates beautiful help text:

Usage: greet <name> [options]

Greets a person by name

Arguments:
  <name>  The name of the person to greet

Options:
  -u, --uppercase          Print the greeting in uppercase
  -r, --repeat <repeat>    Number of times to repeat the greeting

For commands with [Flags] enums, each flag is displayed individually:

Usage: build <project> [options]

Build a project with options

Arguments:
  <project>  Project name

Options:
  -v, --verbose     Enable verbose output
  -d, --debug       Build in debug mode
  --no-cache        Disable build cache
  --skip-tests      Skip running tests

Command list is formatted as a table:

Available commands:

  build    Build a project with options
  copy     Copies a file from source to destination
  git      Execute git commands
  greet    Greets a person by name

Error Handling

Return appropriate exit codes from your commands:

public override Task<int> ExecuteAsync(Args args)
{
    if (!File.Exists(args.Source))
    {
        Console.WriteLine($"Error: Source file '{args.Source}' not found");
        return Task.FromResult(1); // Error exit code
    }

    // Success
    return Task.FromResult(0);
}

Advanced Usage

Multiple Assemblies

Register commands from multiple assemblies:

using Promty;

var executor = new CommandExecutor();
executor.RegisterCommandsFromAssembly(Assembly.GetExecutingAssembly());
executor.RegisterCommandsFromAssembly(typeof(PluginCommand).Assembly);

return await executor.ExecuteAsync(args);

Custom Validation

Implement validation in your command:

public override Task<int> ExecuteAsync(Args args)
{
    if (args.Port < 1 || args.Port > 65535)
    {
        Console.WriteLine("Error: Port must be between 1 and 65535");
        return Task.FromResult(1);
    }

    // Continue with valid arguments
}

Examples

Check out the example commands in the repository:

  • GreetCommand - Demonstrates typed arguments and flags
  • CopyCommand - Shows file operations with validation
  • GitCommand - Example of wrapping an external CLI tool
  • DotNetCommand - Another process command example

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net9.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.1.0 171 10/7/2025
0.0.5 179 10/6/2025
0.0.4 166 10/6/2025
0.0.2 168 10/6/2025