{"id":37053356,"url":"https://github.com/sigurn/commandline","last_synced_at":"2026-01-14T06:01:07.009Z","repository":{"id":92329357,"uuid":"458330148","full_name":"sigurn/CommandLine","owner":"sigurn","description":"C# command based command line parser library","archived":false,"fork":false,"pushed_at":"2025-11-17T18:21:34.000Z","size":116,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-17T19:23:34.717Z","etag":null,"topics":["cli","commandline","net6","nuget","nuget-package","parser"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sigurn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-02-11T20:24:47.000Z","updated_at":"2025-11-17T18:18:24.000Z","dependencies_parsed_at":"2023-11-14T20:45:07.852Z","dependency_job_id":null,"html_url":"https://github.com/sigurn/CommandLine","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/sigurn/CommandLine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurn%2FCommandLine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurn%2FCommandLine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurn%2FCommandLine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurn%2FCommandLine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sigurn","download_url":"https://codeload.github.com/sigurn/CommandLine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sigurn%2FCommandLine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28412181,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","commandline","net6","nuget","nuget-package","parser"],"created_at":"2026-01-14T06:01:05.824Z","updated_at":"2026-01-14T06:01:06.997Z","avatar_url":"https://github.com/sigurn.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CommandLine\n![main workflow](https://github.com/sigurn/CommandLine/actions/workflows/build.yml/badge.svg) [![nuget](https://img.shields.io/nuget/v/Sigurn.CommandLine)](https://www.nuget.org/packages/Sigurn.CommandLine/)\n\n\n## Why\n\nI looked through NuGet.org packages and haven't found decent command line parser.\nThey are either not command oriented so doesn't support deep command nesting (which is what I need)\nor they are in integral part of other projects which next to impossible use separately.\n[System.CommandLine](https://github.com/dotnet/command-line-api) looks promisisng but it is in pre-release state for two years.\nSo I decided to make a parser to cover my needs.\n\n## Supported Frameworks\n\nCurrently the project is built for .NET 6 and .NET 8\n\n\n## Features\n\n* Command based parser which supports nested commands\n* Options and arguments are supported\n* Provides help and version commands and options out of the box\n* Enums (including flags) and arrays are supported\n* Supports boolean flags\n* Supports many built-in types as well as custom types which can be cnstructed from string or provide static method Parse.\n* Basic validation (checks that all required options and arguments are provided)\n* Default values for options and arguments\n* Async commands\n* Termination handling\n* Supports setting application exit code\n\n\n## Terms and conventions used in parser\n\n* Command -- command line parameter which goes first in the command line and defines how the rest of the command line should be parsed.\n* Argument -- command line parameter without name which is identified by position in the command line string.\n* Option -- command line parameter which have a name and starts with `--` or `-`.\n\n* \\[name\\] -- Optional value.\n* \\[\\\u003cname\\\u003e\\] -- Optional argument.\n* \\\u003cname\\\u003e -- Required argument, or value.\n* {value} -- Default value for optional arguments and options.\n\n\nBasically command line looks like this:\n```\n\u003capplication-name\u003e [commands] [arguments] [options]\n```\n\n## Get started\n\nAdd reference to `Sigurn.CommandLine` NuGet package to your project.\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Sigurn.CommandLine\" Version=\"1.*\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\nDefine class describing options and arguments. Use `Option`, `Argument`, `HelpText` attributes to define options, arguments and help texts.\nThen create parser with root command and options:\n```C#\nusing Sigurn.CommandLine;\n\nnamespace GetStarted;\n\nclass GreetingOptions\n{\n    [Argument(0)]\n    [HelpText(\"Name to be shown in the greeting\")]\n    public string Name { get; set; } = \"world\";\n\n    [Option('s', \"short\")]\n    [HelpText(\"Flag defines if the short version of the greeting should be shown\")]\n    public bool IsShort { get; set; }\n}\n\nclass Program\n{\n    public static void Main(string[] args)\n    {\n        var parser = Parser.New\u003cGreetingOptions\u003e(options =\u003e\n        {\n            if (options.IsShort)\n                Console.WriteLine($\"Hi, {options.Name}!\");\n            else\n                Console.WriteLine($\"Hello, {options.Name}!\");\n        }, \"Basic 'Get started' application\");\n\n        parser.Run(args);\n    }\n}\n```\n\nHere is the `--help` option output for the `GetStarted` application:\n```shell\nDescription:\n  Basic 'Get started' application\n\nUsage:\n  GetStarted [\u003cname\u003e] [options]\n\nArguments:\n  \u003cname\u003e  Name to be shown in the greeting {world}\n\nOptions:\n  -s, --short [true|false]  Flag defines if the short version of the greeting should be shown {false}\n  --version                 Show version information\n  -?, -h, --help            Show help and usage information\n```\n\n## Advanced example\n\nFor more advanced example look at [Sigurn.CommandLine.Sample](src/Sigurn.CommandLine.Sample) project.\n\n## Details\n\nBy default all names are optional. Commands, arguments, options will be named after methods and properties using dash notation.\nSo the name `IsShort` like in the 'get started' example will be `is-short`. To override it the name is defined in the `Option` attribute.\nThe same applies to arguments and commands.\n\n### HelpText attribute\n\nThe attribute can be applied to properties and methods. It allows to define help text which will be shown when help command is activated.\n\nHelpText attribute supports multi lines helps. If you want to provide several lines of help text just pass several strings into construxtor like this:\n```C#\n[HelpText(\n    \"This is the first line of the help text\",\n    \"This is the second line of the help text\",\n    \"You may define as many lines of the help text as you like\")]\n```\n\n### Option attribute\n\nThe attribute can be applied to any public property to consider that property as an option by the command line parser.\n\nThe attribute optionally allows to define short and long name for the option.\n\nThere can be several long names defined for the single option: first name is considered as a option name and all others are treated like aliases of the option. You can define as many aliases as you like.\n\nThe attribute also supports flag `IsRequired` to define thet the option is mandatory.\n\nHere is an example of the option with all possible parameters.\n```C#\n[Option('c', \"color\", \"colour\", IsRequired=true)]\n```\n\n### Argument attribute\n\nThe attrubute can be applied to any public property to consider that property as an attribute by the command line parser.\n\nThe attribute has a manatory parameter `Position` it is an integer number which defines order of the attribute in the command line. The bigger numbers go later in the command line.\n\nOptionally the attribute allows to define name of the argument which will be shown in help and flag `IsRequired` to define that the argument is mandatory.\n\nHere is an example of the argument with all possible parameters.\n```C#\n[Argument(0, Name=\"test\", IsRequired=true)]\n```\n\n### CommandName attribute\n\nThe attribute can be applied to a method to change the default command name. By default command will be named after the method name with dash notation.\n\nThe attrobute takes a signe parameter: the command name.\nHere is an example of the command name.\n```C#\n[CommandName(\"hello\")]\n```\n\n### Default values\n\nTo defien a default value for option or argument just provide a default value for class property.\n\n### Commands\n\nThe command line parser is command based so the command is a central part of the parser configuration.\n\nCommand is represented by class `Command` and generic сlass `Command\u003cT\u003e` the later represents a command with options or arguments where as the first one represents a command without options and arguments.\n\nEverything starts from the root command which has empty name and is executed when application without parameters is started.\n\nStatic methods `New` of the `Parser` class accept a delegate or `Command` instance as a parameter this very command will be a root command.\n\nThere is also method `New` without arguments which adds and empty root command that doesn't do anything.\n\n#### Empty root command\n```C#\nvar parser = Parser.New();\n```\n\n#### Empty root command with help text\n```C#\nvar parser = Parser.New(\"Help text here\");\n```\n\n```C#\nvar parser = Parser.New(new Command(\"Help text here\"));\n```\n\n#### Root command with help text\n```C#\nvar parser = Parser.New(() =\u003e Console.WriteLine(\"Hello, world!\"), \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command(\n  () =\u003e Console.WriteLine(\"Hello, world!\"),\n  \"Hello world application\"));\n```\n\n#### Root command with help text which returns result\n```C#\nvar parser = Parser.New(() =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return 0;\n}, \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command(() =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return 0;\n}, \"Hello world application\"));\n```\n\n#### Async root command with help text\n```C#\nvar parser = Parser.New(() =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.CompletedTask;\n}, \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command(() =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.CompletedTask;\n}, \"Hello world application\"));\n```\n\n#### Async root command with help text which returns result\n```C#\nvar parser = Parser.New(() =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.FromResult(0);\n}, \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command(() =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.FromResult(0);\n}, \"Hello world application\"));\n```\n\n#### Root command with options and help text\n```C#\nvar parser = Parser.New\u003cTestOptions\u003e(options =\u003e Console.WriteLine(\"Hello, world!\"), \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command\u003cTestOptions\u003e(\n  options =\u003e Console.WriteLine(\"Hello, world!\"),\n  \"Hello world application\"));\n```\n\n#### Root command with options and help text and returning result\n```C#\nvar parser = Parser.New\u003cTestOptions\u003e(options =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return 0;\n}, \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command\u003cTestOptions\u003e(options =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return 0;\n}, \"Hello world application\"));\n```\n\n#### Async root command with options and help text\n```C#\nvar parser = Parser.New\u003cTestOptions\u003e((options, cancellationToken) =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.CompletedTask;\n}, \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command\u003cTestOptions\u003e((options, cancellationToken) =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.CompletedTask;\n}, \"Hello world application\"));\n```\n\n#### Async root command with options and help text and returning result\n```C#\nvar parser = Parser.New\u003cTestOptions\u003e((options, cancellationToken) =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.FromResult(0);\n}, \"Hello world application\");\n```\n\n```C#\nvar parser = Parser.New(new Command\u003cTestOptions\u003e((options, cancellationToken) =\u003e \n{\n  Console.WriteLine(\"Hello, world!\");\n  return Task.FromResult(0);\n}, \"Hello world application\"));\n```\n\n### Subcommands\n\nSubcommands are just commands which were added to parent command.\nSubcommands may also have their own subcommands and so on as many time as needed.\n\n#### Add subcommand to root command\n```C#\nvar parser = Parser.New()\n  .WithCommand(\"hello\", () =\u003e Console.WriteLine(\"Hello, world!\"), \"Hello command help text\");\n```\n\n#### Add subcommand to subcommand\n```C#\nvar parser = Parser.New()\n  .WithCommand(new Command(\"hello\", () =\u003e {Console.WriteLine(\"Hello, world!\"), \"Hello command help text\")\n    .WithCommand(\"subcommand\", () =\u003e Concole.WriteLine(\"subcommand\")));\n```\n\n### Use methods as commands\n```C#\nstatic class Commands\n{\n  [CommandName(\"hello\")]\n  [HelpText(\"Hello comamahd help text\")]\n  public static void Hello()\n  {\n    Console.WriteLine(\"Hello, world!\");\n  }\n\n  public static void Subcommand()\n  {\n    Console.WriteLine(\"subcommand\");\n  }\n}\n\nclass Program\n{\n  public static void Main(string[] args)\n  {\n    var parser = Parser.New()\n      .WithCommand(new Command(Commands.Hello)\n        .WithCommand(Commands.Subcommand));\n  }\n}\n```\n\n### Custom version handler\nBy default option --version prints assembly version to the console like\n```shell\n1.0.0.0\n```\n\nYou can provide custom handler for version command\n```C#\nvar parser = Parser.New()\n  .WithVersionCommand(() =\u003e Console.WriteLine(\"Custom version\"));\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsigurn%2Fcommandline","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsigurn%2Fcommandline","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsigurn%2Fcommandline/lists"}