Skip to content

Arguments & Flags ​

Promty supports two types of command-line arguments: positional arguments and flag arguments.

Positional Arguments ​

Positional arguments are required and must be provided in order. They don't have a [FlagAlias] attribute.

csharp
public class Args
{
    [Description("name", "The name argument")]
    public string Name { get; set; } = string.Empty;

    [Description("age", "The age argument")]
    public int Age { get; set; }
}

Usage:

bash
dotnet run -- mycommand John 25

Rules for Positional Arguments ​

  1. Always required - must be provided
  2. Order matters - must be provided in the order they're defined
  3. Must come before any flags
  4. Cannot be nullable

Flag Arguments ​

Flag arguments are optional and can be provided in any order. They have a [FlagAlias] attribute.

csharp
public class Args
{
    [FlagAlias("verbose", 'v')]
    [Description("Enable verbose output")]
    public bool Verbose { get; set; }

    [FlagAlias("port", 'p')]
    [Description("Port number")]
    public int? Port { get; set; }
}

Usage:

bash
# Long form
dotnet run -- mycommand --verbose --port 8080

# Short form
dotnet run -- mycommand -v -p 8080

# Mixed
dotnet run -- mycommand --verbose -p 8080

Supported Types ​

Promty automatically converts argument strings to the following types:

Primitive Types ​

  • string
  • int
  • long
  • double
  • bool

Nullable Types ​

  • int?
  • long?
  • double?
  • bool?

Enums ​

Boolean Flags ​

Boolean flags have special behavior - they don't require a value:

csharp
[FlagAlias("force", 'f')]
public bool Force { get; set; }

Both of these work:

bash
dotnet run -- mycommand --force       # Implicitly true
dotnet run -- mycommand --force true  # Explicitly true

Nullable Arguments ​

Use nullable types for optional flags with values:

csharp
public class Args
{
    [FlagAlias("timeout", 't')]
    [Description("Timeout in seconds")]
    public int? Timeout { get; set; }
}

If not provided, the value will be null:

csharp
public override Task<int> ExecuteAsync(Args args)
{
    var timeout = args.Timeout ?? 30; // Use 30 if not provided
    Console.WriteLine($"Timeout: {timeout}s");
    return Task.FromResult(0);
}

Description Attribute ​

Use [Description] to provide help text:

For Commands ​

csharp
[Description("greet", "Greets a person by name")]
public class GreetCommand : Command<GreetCommand.Args>

For Positional Arguments ​

csharp
[Description("name", "The name of the person to greet")]
public string Name { get; set; }

For Flags ​

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

FlagAlias Attribute ​

Define long and/or short aliases for flags:

Both Long and Short ​

csharp
[FlagAlias("verbose", 'v')]

Long Only ​

csharp
[FlagAlias("verbose")]

Short Only ​

csharp
[FlagAlias('v')]

Examples ​

Simple Command ​

csharp
public class Args
{
    [Description("message", "The message to display")]
    public string Message { get; set; } = string.Empty;

    [FlagAlias("uppercase", 'u')]
    [Description("Convert to uppercase")]
    public bool Uppercase { get; set; }
}
bash
dotnet run -- mycommand "Hello World" --uppercase

Multiple Positional Arguments ​

csharp
public class Args
{
    [Description("source", "Source file")]
    public string Source { get; set; } = string.Empty;

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

    [FlagAlias("overwrite", 'o')]
    [Description("Overwrite if exists")]
    public bool Overwrite { get; set; }
}
bash
dotnet run -- copy input.txt output.txt --overwrite

Mixed Types ​

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

    [FlagAlias("port", 'p')]
    [Description("Port number")]
    public int? Port { get; set; }

    [FlagAlias("timeout", 't')]
    [Description("Timeout in seconds")]
    public double? Timeout { get; set; }

    [FlagAlias("verbose", 'v')]
    [Description("Verbose output")]
    public bool Verbose { get; set; }
}
bash
dotnet run -- server MyServer -p 8080 -t 30.5 --verbose

Validation ​

Add custom validation in your command:

csharp
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);
    }

    if (!File.Exists(args.Source))
    {
        Console.WriteLine($"Error: Source file '{args.Source}' not found");
        return Task.FromResult(1);
    }

    // Continue with valid arguments...
    return Task.FromResult(0);
}

Released under the MIT License.