{"id":38963951,"url":"https://github.com/xenomachina/kotlin-argparser","last_synced_at":"2026-01-17T16:27:30.262Z","repository":{"id":15489010,"uuid":"78251219","full_name":"xenomachina/kotlin-argparser","owner":"xenomachina","description":"Easy to use and concise yet powerful and robust command line argument parsing for Kotlin","archived":false,"fork":false,"pushed_at":"2022-05-31T00:36:10.000Z","size":516,"stargazers_count":492,"open_issues_count":34,"forks_count":34,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-12-03T12:19:53.273Z","etag":null,"topics":["argument-parser","command-line-parser","kotlin","kotlin-library","option-parser"],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xenomachina.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-07T01:26:57.000Z","updated_at":"2025-11-26T10:25:38.000Z","dependencies_parsed_at":"2022-07-18T03:00:36.093Z","dependency_job_id":null,"html_url":"https://github.com/xenomachina/kotlin-argparser","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/xenomachina/kotlin-argparser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenomachina%2Fkotlin-argparser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenomachina%2Fkotlin-argparser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenomachina%2Fkotlin-argparser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenomachina%2Fkotlin-argparser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xenomachina","download_url":"https://codeload.github.com/xenomachina/kotlin-argparser/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xenomachina%2Fkotlin-argparser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28511864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: 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":["argument-parser","command-line-parser","kotlin","kotlin-library","option-parser"],"created_at":"2026-01-17T16:27:29.600Z","updated_at":"2026-01-17T16:27:30.247Z","avatar_url":"https://github.com/xenomachina.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg alt=\"Kotlin --argparser\" src=\"https://rawgit.com/xenomachina/kotlin-argparser/master/logo.svg\" style=\"transform:scale(.6)\" \u003e\n\n\u003c!--\nRemoved until either Bintray makes a badge with a configurable label, or\nshields.io can make a reliable bintray badge.\n\n[![Bintray](https://img.shields.io/bintray/v/xenomachina/maven/kotlin-argparser.svg)](https://bintray.com/xenomachina/maven/kotlin-argparser/%5FlatestVersion)\n--\u003e\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.xenomachina/kotlin-argparser.svg)](https://mvnrepository.com/artifact/com.xenomachina/kotlin-argparser)\n[![Build Status](https://travis-ci.org/xenomachina/kotlin-argparser.svg?branch=master)](https://travis-ci.org/xenomachina/kotlin-argparser)\n[![codebeat badge](https://codebeat.co/badges/902174e2-31be-4f9d-a4ba-40178b075d2a)](https://codebeat.co/projects/github-com-xenomachina-kotlin-argparser-master)\n[![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin)\n[![Javadocs](https://www.javadoc.io/badge/com.xenomachina/kotlin-argparser.svg)](https://www.javadoc.io/doc/com.xenomachina/kotlin-argparser)\n[![License: LGPL 2.1](https://img.shields.io/badge/license-LGPL--2.1-blue.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)\n\n\nThis is a library for parsing command-line arguments.  It can parse both\noptions and positional arguments.  It aims to be easy to use and concise yet\npowerful and robust.\n\n\n## Overview\n\nDefining options and positional arguments is as simple as:\n\n```kotlin\nimport com.xenomachina.argparser.ArgParser\n\nclass MyArgs(parser: ArgParser) {\n    val v by parser.flagging(\"enable verbose mode\")\n\n    val name by parser.storing(\"name of the user\")\n\n    val count by parser.storing(\"number of the widgets\") { toInt() }\n\n    val source by parser.positional(\"source filename\")\n\n    val destination by parser.positional(\"destination filename\")\n}\n```\n\nAn instance of `MyArgs` will represent the set of parsed arguments. Each option\nand positional argument is declared as a property that delegates through a\ndelegate factory method on an instance of `ArgParser`.\n\nThe name of an option is inferred from the name of the property it is bound to.\nThe options above are named `-v`, `--name` and `--count`, respectively. There\nare also two positional arguments.\n\nDirect control over an option's name is also possible, and for most types of\noptions it is also possible to have multiple names, like a short and long name:\n\n\n```kotlin\nclass MyArgs(parser: ArgParser) {\n    val verbose by parser.flagging(\n        \"-v\", \"--verbose\",\n        help = \"enable verbose mode\")\n\n    val name by parser.storing(\n        \"-N\", \"--name\",\n        help = \"name of the user\")\n\n    val count by parser.storing(\n        \"-c\", \"--count\",\n        help = \"number of widgets\") { toInt() }\n\n    val source by parser.positional(\n        \"SOURCE\",\n        help = \"source filename\")\n\n    val destination by parser.positional(\n        \"DEST\",\n        help = \"destination filename\")\n}\n```\n\nThe unparsed command-line arguments are passed to the `ArgParser` instance at\nconstruction:\n\n```kotlin\nfun main(args: Array\u003cString\u003e) = mainBody {\n    ArgParser(args).parseInto(::MyArgs).run {\n        println(\"Hello, ${name}!\")\n        println(\"I'm going to move ${count} widgets from ${source} to ${destination}.\")\n        // TODO: move widgets\n    }\n}\n```\n\nSee [kotlin-argparser-example](https://github.com/xenomachina/kotlin-argparser-example)\nfor a complete example project.\n\n\n## Nomenclature\n\nOptions, arguments, flags... what's the difference?\n\nAn application's `main` function is passed an array of strings. These are\nthe *unparsed command-line arguments*, or *unparsed arguments* for short.\n\nThe unparsed arguments can then be parsed into *options*, which start\nwith a hyphen (\"`-`\"), and *positional arguments*. For example, in the command\n`ls -l /tmp/`, the unparsed arguments would be `\"-l\", \"/tmp\"` where `-l`\nis an option, while `/tmp/` is a positional argument.\n\nOptions can also have *option arguments*. In the command `ls --time-style=iso`,\nthe option is `--time-style` and that options argument is `iso`. Note that in\nparsing a single unparsed argument can be split into an option and an option\nargument, or even into multiple options in some cases.\n\nA *flag* is a boolean option which has no arguments and which is false if not\nprovided, but true if provided. The `-l` option of `ls` is a flag.\n\n## Option Types\n\n### Boolean Flags\n\nBoolean flags are created by asking the parser for a `flagging` delegate.  One\nor more option names, may be provided:\n\n```kotlin\nval verbose by parser.flagging(\"-v\", \"--verbose\",\n                               help = \"enable verbose mode\")\n```\n\nHere the presence of either `-v` or `--verbose` options in the\narguments will cause the `Boolean` property `verbose` to be `true`, otherwise\nit will be `false`.\n\n### Storing a Single Argument\n\nSingle argument options are created by asking the parser for a\n`storing` delegate.\n\n```kotlin\nval name by parser.storing(\"-N\", \"--name\",\n                           help = \"name of the user\")\n```\n\nHere either `-N` or `--name` with an argument will cause the `name` property to\nhave that argument as its value.\n\nA function can also be supplied to transform the argument into the desired\ntype. Here the `size` property will be an `Int` rather than a `String`:\n\n```kotlin\nval size by parser.storing(\"-c\", \"--count\",\n                           help = \"number of widgets\") { toInt() }\n```\n\n### Adding to a Collection\n\nOptions that add to a `Collection` each time they appear in the arguments are\ncreated with using the `adding` delegate. Just like `storing` delegates, a\ntransform function may optionally be supplied:\n\n```kotlin\nval includeDirs by parser.adding(\n        \"-I\", help = \"directory to search for header files\") { File(this) }\n```\n\nNow each time the `-I` option appears, its transformed argument is appended to\n`includeDirs`.\n\n### Mapping from an option to a fixed value\n\nFor choosing between a fixed set of values (typically, but not necessarily,\nfrom an enum), a `mapping` delegate can be used:\n\n```kotlin\nval mode by parser.mapping(\n        \"--fast\" to Mode.FAST,\n        \"--small\" to Mode.SMALL,\n        \"--quiet\" to Mode.QUIET,\n        help = \"mode of operation\")\n```\n\nHere the `mode` property will be set to the corresponding `ArgParser.Mode` value depending\non which of `--fast`, `--small`, and `--quiet` appears (last) in the arguments.\n\n`mapping` is one of the few cases where it is not possible to infer the option\nname from the property name.\n\n### More advanced options\n\nFor all other types of options, the `option` method should be used. The\nmethods mentioned above are, in fact, convenience methods built on top of the\n`option` method.\n\nFor example, it is possible to create an option that has multiple arguments:\n\n```kotlin\n  fun ArgParser.putting(vararg names: String, help: String) =\n          option\u003cMutableMap\u003cString, String\u003e\u003e(*names,\n                  argNames = listOf(\"KEY\", \"VALUE\"),\n                  help = help) {\n              value.orElse { mutableMapOf\u003cString, String\u003e() }.apply {\n                  put(arguments.first(), arguments.last()) }\n          }\n```\n\nNote that the `option` method does not have an auto-naming overload. If you\nneed this capability, create a `DelegateProvider` that creates your `Delegate`:\n\n```kotlin\n  fun ArgParser.putting(help: String) =\n          ArgParser.DelegateProvider { identifier -\u003e\n              putting(identifierToOptionName(identifier), help = help) }\n```\n\n\n## Positional Arguments\n\nPositional arguments are collected by using the `positional` and\n`positionalList` methods.\n\nFor a single positional argument:\n\n```kotlin\nval destination by parser.positional(\"destination filename\")\n```\n\nAn explicit name may also be specified:\n\n```kotlin\nval destination by parser.positional(\"DEST\",\n                                     help = \"destination filename\")\n```\n\nThe name (\"DEST\", here) is used in error handling and help text.\n\nFor a list of positional arguments:\n\n```kotlin\nval sources by parser.positionalList(\"SOURCE\", 1..Int.MAX_VALUE,\n                                     help = \"source filename\")\n```\n\nThe range indicates how many arguments should be collected, and defaults to the\nvalue shown in this example. As the name suggests, the resulting property will\nbe a `List`.\n\nBoth of these methods accept an optional transform function for converting\narguments from `String` to whatever type is actually desired:\n\n```kotlin\nval destination by parser.positional(\"DEST\",\n                                     help = \"...\") { File(this) }\n\nval sources by parser.positionalList(\"SOURCE\", 1..Int.MAX_VALUE,\n                                     help = \"...\") { File(this) }\n```\n\n\n## Modifying Delegates\n\nThe delegates returned by any of these methods also have a few methods for setting\noptional attributes:\n\n### Adding a Default Value\n\nCertain types of delegates (notably `storing`, `mapping`, and `positional`)\nhave no default value, and hence will be required options unless a default\nvalue is provided. This is done with the `default` method:\n\n```kotlin\nval name by parser.storing(\"-N\", \"--name\", help = \"...\").default(\"John Doe\")\n```\n\nNote that it *is* possible to use `null` for the default, though this may\nrequire specifying the type parameter for `default` explicitly:\n\n```kotlin\nval name by parser.storing(\"-N\", \"--name\", help = \"...\").default\u003cString?\u003e(null)\n```\n\nThe type of the resulting property be nullable (a `String?` in this case).\n\n\n### Adding a Validator\n\nSometimes it's easier to validate an option at the end of parsing, in which\ncase the `addValidator` method can be used.\n\n```kotlin\nval percentages by parser.adding(\"--percentages\", help = \"...\") { toInt() }\n        .addValidator {\n              if (value.sum() != 100)\n                  throw InvalidArgumentException(\n                          \"Percentages must add up to 100%\")\n        }\n```\n\n## Error Handling\n\nIf the parser determines that execution should not continue it will throw a\n`SystemExitException` which has a status code appropriate for passing to\n`exitProcess` as well as a message for the user.\n\nThese exceptions can be caused by user error, or even if the user requests help\n(eg: via the `--help` option).\n\nIt is recommended that transform functions (given to `storing`,\n`positionalList`, etc.) and post-parsing validation, including that performed\nvia, `addValidator` also throw a `SystemExitException` on failure.\n\nAs a convenience, these exceptions can be handled by using the `mainBody`\nfunction:\n\n```kotlin\nclass ParsedArgs(parser: ArgParser) {\n    val name by positional(\"The user's name\").default(\"world\")\n}\n\nfun main(args: Array\u003cString\u003e) = mainBody {\n    ArgParser(args).parseInto(::ParsedArgs).run {\n        println(\"Hello, {name}!\")\n    }\n}\n```\n\n## Parsing\n\nParsing of command-line arguments is performed sequentially. So long as\noption-processing is enabled, each not-yet-processed command-line argument that\nstarts with a hyphen (`-`) is treated as an option.\n\n### Short Options\n\nShort options start with a single hyphen. If the option takes an argument, the\nargument can either be appended:\n\n```bash\n# \"-o\" with argument \"ARGUMENT\"\nmy_program -oARGUMENT\n```\n\nor can be the following command-line argument:\n\n```bash\n# \"-o\" with argument \"ARGUMENT\"\nmy_program -o ARGUMENT\n```\n\nZero argument short options can also be appended to each other without\nintermediate hyphens:\n\n```bash\n# \"-x\", \"-y\" and \"-z\" options\nmy_program -xyz\n```\n\nAn option that accepts arguments is also allowed at the end of such a chain:\n\n```bash\n# \"-x\", \"-y\" and \"-z\" options, with argument for \"-z\"\nmy_program -xyzARGUMENT\n```\n\n### Long Options\n\nLong options start with a double hyphen (`--`). An argument to a long option\ncan\neither be delimited with an equal sign (`=`):\n\n```bash\n# \"--foo\" with argument \"ARGUMENT\"\nmy_program --foo=ARGUMENT\n```\n\nor can be the following command-line argument:\n\n```bash\n# \"--foo\" with argument \"ARGUMENT\"\nmy_program --foo ARGUMENT\n```\n\n### Multi-argument Options\n\nMulti-argument options are supported, though currently not by any of the\nconvenience methods. Option-arguments after the first must be separate\ncommand-line arguments, for both an long and short forms of an option.\n\n### Positional Arguments\n\nIn GNU mode (the default), options can be interspersed with positional\narguments, but in POSIX mode the first positional argument that is encountered\ndisables option processing for the remaining arguments. In either mode, if the\nargument \"--\" is encountered while option processing is enabled, then option\nprocessing is disabled for the rest of the command-line. Once the options and\noption-arguments have been eliminated, what remains are considered to be\npositional arguments.\n\nEach positional argument delegate can specify a minimum and maximum number of\narguments it is willing to collect.\n\nThe positional arguments are distributed to the delegates by allocating each\npositional delegate at least as many arguments as it requires. If more than the\nminimum number of positional arguments have been supplied then additional\narguments will be allocated to the first delegate up to its maximum, then the\nsecond, and so on, until all arguments have been allocated to a delegate.\n\nThis makes it easy to create a program that behaves like `grep`:\n\n```kotlin\nclass Args(parser: ArgParser) {\n    // accept 1 regex followed by n filenames\n    val regex by parser.positional(\"REGEX\",\n            help = \"regular expression to search for\")\n    val files by parser.positionalList(\"FILE\",\n            help = \"file to search in\")\n}\n```\n\nAnd equally easy to create a program that behaves like `cp`:\n\n```kotlin\nclass Args(parser: ArgParser) {\n    // accept n source files followed by 1 destination\n    val sources by parser.positionalList(\"SOURCE\",\n            help = \"source file\")\n    val destination by parser.positional(\"DEST\",\n            help = \"destination file\")\n}\n```\n\n\n## Forcing Parsing\n\nParsing normally does not begin until a delegate's value is accessed. Sometimes\nthis is not desirable, so it is possible to enforce the parsing of arguments\ninto a class of values. This ensures that all arguments that are required are\nprovided, and all arguments provided are consumed.\n\nForcing can be done in a separate step using the `force` method:\n\n```kotlin\nval parser = ArgParser(args)\nval parsedArgs = ParsedArgs(parser)\nparser.force()\n// now you can use parsedArgs\n```\n\nAlternatively, forcing can be done inline via the `parseInto` method:\n\n```kotlin\nval parsedArgs = ArgParser(args).parseInto(::ParsedArgs)\n// now you can use parsedArgs\n```\n\nIn both cases exceptions will be thrown where parsing or validation errors are found.    \n\n## Help Formatting\n\nBy default, `ArgParser` will add a `--help` option (short name `-h`) for\ndisplaying usage information. If this option is present a `ShowHelpException` will be thrown.\nIf the default exception handling is being used (see [Error Handling](#error-handling)) the\nprogram will halt and print a help message like the one below, based on the `ArgParser`\nconfiguration:\n\n    usage: program_name [-h] [-n] [-I INCLUDE]... -o OUTPUT\n                        [-v]... SOURCE... DEST\n\n\n    This is the prologue. Lorem ipsum dolor sit amet, consectetur\n    adipiscing elit. Aliquam malesuada maximus eros. Fusce\n    luctus risus eget quam consectetur, eu auctor est\n    ullamcorper. Maecenas eget suscipit dui, sed sodales erat.\n    Phasellus.\n\n\n    required arguments:\n      -o OUTPUT,          directory in which all output should\n      --output OUTPUT     be generated\n\n\n    optional arguments:\n      -h, --help          show this help message and exit\n\n      -n, --dry-run       don't do anything\n\n      -I INCLUDE,         search in this directory for header\n      --include INCLUDE   files\n\n      -v, --verbose       increase verbosity\n\n\n    positional arguments:\n      SOURCE              source file\n\n      DEST                destination file\n\n\n    This is the epilogue. Lorem ipsum dolor sit amet,\n    consectetur adipiscing elit. Donec vel tortor nunc. Sed eu\n    massa sed turpis auctor faucibus. Donec vel pellentesque\n    tortor. Ut ultrices tempus lectus fermentum vestibulum.\n    Phasellus.\n\nThe creation of the `--help` option can be disabled by passing `null` as the\n`helpFormatter` when constructing the `ArgParser`, or configured by manually\nconstructing a `HelpFormatter` instance. In the above example a\n`DefaultHelpFormatter` was created with the prologue and epilogue.\n\n\n## Caveats\n\n- This library should be considered to be *very beta*. While there are no plans\n  to make any breaking changes to the API, it's possible that there may be some\n  until it is mature.\n\n- Upon reading the value any of the delegated properties created by an\n  `ArgParser`, the arguments used to construct that `ArgParser` will be\n  parsed. This means it's important that you don't attempt to create delegates\n  on an `ArgParser` after any of its existing delegated properties have been\n  read. Attempting to do so will cause an `IllegalStateException`. It would be\n  nice if Kotlin had facilities for doing some of the work of `ArgParser` at\n  compile time rather than run time, but so far the run time errors seem to be\n  reasonably easy to avoid.\n\n\n## Configuring Your Build\n\n\u003c!-- TODO move detailed instructions elsewhere, just have brief instructions here --\u003e\n\nKotlin-argparser binaries are hosted on Maven Central and also Bintray's\nJCenter.\n\nIn Gradle, add something like this in your `build.gradle`:\n\n```groovy\n// you probably already have this part\nbuildscript {\n    repositories {\n        mavenCentral() // or jcenter()\n    }\n}\n\ndependencies {\n    compile \"com.xenomachina:kotlin-argparser:$kotlin_argparser_version\"\n}\n```\n\nIn Maven add something like this to your `pom.xml`:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.xenomachina\u003c/groupId\u003e\n    \u003cartifactId\u003ekotlin-argparser\u003c/artifactId\u003e\n    \u003cversion\u003eVERSION\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nInformation on setting up other build systems, as well as the current version\nnumber, can be found on\n[MVN Repository's page for Kotlin-argparser](https://mvnrepository.com/artifact/com.xenomachina/kotlin-argparser/latest).\n\n## Thanks\n\nThanks to the creators of Python's\n[`argparse`](https://docs.python.org/3/library/argparse.html) module, which\nprovided the initial inspiration for this library.\n\nThanks also to the team behind [Kotlin](https://kotlinlang.org/).\n\nFinally, thanks to all of the people who have contributed\n[code](https://github.com/xenomachina/kotlin-argparser/graphs/contributors)\nand/or\n[issues](https://github.com/xenomachina/kotlin-argparser/issues).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxenomachina%2Fkotlin-argparser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxenomachina%2Fkotlin-argparser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxenomachina%2Fkotlin-argparser/lists"}