Skip to content

Writing Commands

JasperFx provides two base classes for building CLI commands.

Synchronous Commands

Extend JasperFxCommand<T> for commands that do not need async operations:

cs
[Description("Say hello to someone")]
public class GreetingCommand : JasperFxCommand<GreetingInput>
{
    public override bool Execute(GreetingInput input)
    {
        Console.WriteLine($"Hello, {input.Name}!");
        return true;
    }
}

snippet source | anchor

cs
[Description("Say hello to someone")]
public class GreetingCommand : JasperFxCommand<GreetingInput>
{
    public override bool Execute(GreetingInput input)
    {
        Console.WriteLine($"Hello, {input.Name}!");
        return true;
    }
}

snippet source | anchor

The Execute method returns true for success or false for failure. The exit code is set accordingly.

Async Commands

Extend JasperFxAsyncCommand<T> when you need to perform async work:

cs
[Description("Say hello to someone asynchronously")]
public class AsyncGreetingCommand : JasperFxAsyncCommand<GreetingInput>
{
    public override async Task<bool> Execute(GreetingInput input)
    {
        await Task.Delay(100);
        Console.WriteLine($"Hello, {input.Name}!");
        return true;
    }
}

snippet source | anchor

cs
[Description("Say hello to someone asynchronously")]
public class AsyncGreetingCommand : JasperFxAsyncCommand<GreetingInput>
{
    public override async Task<bool> Execute(GreetingInput input)
    {
        await Task.Delay(100);
        Console.WriteLine($"Hello, {input.Name}!");
        return true;
    }
}

snippet source | anchor

Input Classes

Every command takes an input class that defines its arguments and flags:

cs
public class GreetingInput
{
    [Description("The name to greet")]
    public string Name { get; set; } = "World";
}

snippet source | anchor

cs
public class GreetingInput
{
    [Description("The name to greet")]
    public string Name { get; set; } = "World";
}

snippet source | anchor

Properties on the input class are automatically mapped to command line arguments. See Arguments and Flags for the full attribute reference.

Command Naming

By default, the command name is derived from the class name by removing the Command suffix and converting to kebab-case. For example, GreetingCommand becomes greeting.

Usage Patterns

Commands can define multiple usage patterns similar to Git:

csharp
public class MyCommand : JasperFxCommand<MyInput>
{
    public MyCommand()
    {
        Usage("Default usage").Arguments(x => x.Name);
    }

    public override bool Execute(MyInput input) => true;
}

Next Steps

Released under the MIT License.