This content originally appeared on DEV Community and was authored by Maria
Building Command-Line Tools with C# and System.CommandLine
Command-line tools are the unsung heroes of developer productivity. From simplifying complex workflows to automating repetitive tasks, CLI applications can make life easier for developers, administrators, and power users alike. If you’re a C# developer, you have a powerful library at your disposal: System.CommandLine. This library makes it easy to build robust, user-friendly CLI tools with minimal boilerplate code.
In this blog post, we’ll dive deep into System.CommandLine, exploring how to build feature-rich command-line applications in C#. We’ll cover argument parsing, subcommands, help generation, common pitfalls, and more. By the end of this article, you’ll have the knowledge and confidence to create your own developer-friendly CLI tools.
Why Build Command-Line Tools?
Before we dive into the nitty-gritty, let’s briefly consider why you might want to build CLI tools in the first place:
- Automation: Streamline repetitive tasks, like database migrations or file processing.
- Developer Productivity: Build tools for your team, such as custom code generators.
- System Administration: Manage servers, run scripts, or interact with APIs.
- Cross-Platform: Build a single tool that works on Windows, macOS, and Linux.
CLI tools are lightweight, fast, and often the most efficient way to perform specific tasks. Plus, with C# and System.CommandLine, you can create tools that are both powerful and intuitive.
Getting Started with System.CommandLine
What Is System.CommandLine?
System.CommandLine is a modern library for building command-line interfaces in .NET applications. It simplifies parsing arguments, managing subcommands, and generating help text. The library is modular, flexible, and designed to make your CLI tools easy to use.
To get started, you’ll need to install the package via NuGet:
dotnet add package System.CommandLine
Once installed, you’re ready to start building your CLI tool!
Building Your First CLI Tool
Let’s start with the basics: a simple command-line application that accepts arguments and performs an operation.
Step 1: Define the Root Command
The RootCommand is the main entry point of your CLI tool. It’s where you define the primary functionality of your application.
Here’s an example of a tool that greets the user:
using System.CommandLine;
class Program
{
static async Task<int> Main(string[] args)
{
// Define the root command
var rootCommand = new RootCommand("A simple CLI tool for greeting users.");
// Add an argument for the user's name
var nameArgument = new Argument<string>("name", "The name of the person to greet.");
rootCommand.AddArgument(nameArgument);
// Add a handler for the command
rootCommand.SetHandler((string name) =>
{
Console.WriteLine($"Hello, {name}!");
}, nameArgument);
// Invoke the command
return await rootCommand.InvokeAsync(args);
}
}
What’s Happening Here?
- RootCommand: This is the main command of your application. Think of it as the “homepage” of your CLI tool.
-
Argument: We define an argument called
name
that the user must provide. - SetHandler: This is where we define what happens when the command is executed. In this case, we print a greeting.
Run the application like this:
dotnet run -- John
Output:
Hello, John!
Adding Subcommands
Subcommands allow you to organize your application into multiple tasks or functionalities. For example, consider a CLI tool for managing tasks. You might have subcommands like add
, list
, and delete
.
Here’s how you can implement subcommands:
using System.CommandLine;
class Program
{
static async Task<int> Main(string[] args)
{
var rootCommand = new RootCommand("Task Manager CLI");
var addCommand = new Command("add", "Add a new task")
{
new Argument<string>("description", "The description of the task to add.")
};
addCommand.SetHandler((string description) =>
{
Console.WriteLine($"Task added: {description}");
}, addCommand.Arguments[0]);
var listCommand = new Command("list", "List all tasks");
listCommand.SetHandler(() =>
{
Console.WriteLine("Listing all tasks...");
});
var deleteCommand = new Command("delete", "Delete a task")
{
new Argument<int>("id", "The ID of the task to delete.")
};
deleteCommand.SetHandler((int id) =>
{
Console.WriteLine($"Task deleted: {id}");
}, deleteCommand.Arguments[0]);
rootCommand.AddCommand(addCommand);
rootCommand.AddCommand(listCommand);
rootCommand.AddCommand(deleteCommand);
return await rootCommand.InvokeAsync(args);
}
}
How It Works
-
Commands: Each subcommand is defined using the
Command
class. - Handlers: Each subcommand has its own handler that executes the desired functionality.
-
Hierarchy: Subcommands are added to the
RootCommand
to form a hierarchy.
Try running the following commands:
dotnet run -- add "Finish the blog post"
dotnet run -- list
dotnet run -- delete 1
Output:
Task added: Finish the blog post
Listing all tasks...
Task deleted: 1
Generating Help Text
One of the best features of System.CommandLine is its built-in help text generation. Users can type --help
or -h
to see detailed usage instructions.
For example, if you run:
dotnet run -- --help
It will automatically generate help text based on your commands and arguments:
Task Manager CLI
Usage:
add <description>
list
delete <id>
Options:
-h, --help Show help and usage information
No extra work is required! System.CommandLine takes care of this for you.
Handling Common Pitfalls
1. Forgetting to Set Handlers
If you add commands but forget to set handlers, your CLI tool won’t do anything. Always double-check that each command has an associated handler.
2. Argument Confusion
It’s easy to mix up Argument and Option. Use arguments for required inputs and options for optional flags or parameters.
For example:
var option = new Option<int>("--timeout", "The timeout duration in seconds.");
3. Overcomplicating the Command Hierarchy
If your tool has too many nested subcommands, it might become confusing for users. Aim for simplicity and clarity.
Key Takeaways
- System.CommandLine is a powerful library for building CLI tools in C#.
- You can define arguments, options, and subcommands to create feature-rich applications.
- Help text generation is built-in, making your tools more user-friendly.
- Avoid common pitfalls like missing handlers and overly complex hierarchies.
Next Steps
Here’s how you can continue advancing your knowledge:
- Explore the System.CommandLine Documentation: Dive deeper into advanced features like validations, custom argument parsers, and middleware.
- Build a Real-World CLI Tool: Try creating a tool for a specific use case, such as a file organizer or API client.
- Share Your Work: Open-source your CLI tool and share it with the developer community!
Building command-line tools with C# and System.CommandLine is incredibly rewarding. You’ll not only sharpen your programming skills but also create tools that make life easier for others. So, what are you waiting for? Start building your CLI masterpiece today!
Happy coding!
This content originally appeared on DEV Community and was authored by Maria