{"id":918,"url":"https://github.com/kylef/Commander","last_synced_at":"2025-08-06T13:32:08.495Z","repository":{"id":18340706,"uuid":"21520325","full_name":"kylef/Commander","owner":"kylef","description":"Compose beautiful command line interfaces in Swift","archived":false,"fork":false,"pushed_at":"2022-03-26T09:37:37.000Z","size":230,"stargazers_count":1529,"open_issues_count":3,"forks_count":86,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-12-06T14:03:52.884Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kylef.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-07-05T13:15:26.000Z","updated_at":"2024-11-02T17:58:45.000Z","dependencies_parsed_at":"2022-08-09T03:00:02.994Z","dependency_job_id":null,"html_url":"https://github.com/kylef/Commander","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylef%2FCommander","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylef%2FCommander/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylef%2FCommander/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kylef%2FCommander/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kylef","download_url":"https://codeload.github.com/kylef/Commander/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228905448,"owners_count":17989770,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-01-05T20:15:34.624Z","updated_at":"2024-12-09T14:30:45.132Z","avatar_url":"https://github.com/kylef.png","language":"Swift","funding_links":[],"categories":["Command Line","Libs","Swift","CLI and Server","[Swift](https://www.swift.org/)","Command Line [🔝](#readme)","Additional Languages","The Index"],"sub_categories":["Linter","Command Line","Other free courses","Useful awesome list for Ruby cli","Swift 🦉","Command Line UI tools"],"readme":"\u003cimg src=\"Commander.png\" width=80 height=83 alt=\"Commander\" /\u003e\n\n# Commander\n\n[![Build Status](https://img.shields.io/travis/kylef/Commander/master.svg?style=flat)](https://travis-ci.org/kylef/Commander)\n\nCommander is a small Swift framework allowing you to craft beautiful command\nline interfaces in a composable way.\n\n## Usage\n\n##### Simple Hello World\n\n```swift\nimport Commander\n\nlet main = command { (filename:String) in\n  print(\"Reading file \\(filename)...\")\n}\n\nmain.run()\n```\n\n##### Type-safe argument handling\n\nThe closure passed to the command function takes any arguments that\nconform to `ArgumentConvertible`, Commander will automatically convert the\narguments to these types. If they can't be converted the user will receive a\nnice error message informing them that their argument doesn't match the\nexpected type.\n\n`String`, `Int`, `Double`, and `Float` are extended to conform to\n`ArgumentConvertible`, you can easily extend any other class or structure\nso you can use it as an argument to your command.\n\n```swift\ncommand { (hostname:String, port:Int) in\n  print(\"Connecting to \\(hostname) on port \\(port)...\")\n}\n```\n\n##### Grouping commands\n\nYou can group a collection of commands together.\n\n```swift\nGroup {\n  $0.command(\"login\") { (name:String) in\n    print(\"Hello \\(name)\")\n  }\n\n  $0.command(\"logout\") {\n    print(\"Goodbye.\")\n  }\n}\n```\n\nUsage:\n\n```shell\n$ auth\nUsage:\n\n    $ auth COMMAND\n\nCommands:\n\n    + login\n    + logout\n\n$ auth login Kyle\nHello Kyle\n$ auth logout\nGoodbye.\n```\n\n#### Describing arguments\n\nYou can describe positional arguments and options for a command to auto-generate help.\nThis is done by passing in descriptors of these arguments.\n\nFor example, for fixed positional arguments with descriptions, you can use:\n\n```swift\ncommand(\n    Argument\u003cString\u003e(\"name\", description: \"Your name\"),\n    Argument\u003cString\u003e(\"surname\", description: \"Your surname\"),\n    Argument\u003cInt\u003e(\"count\", description: \"Number of times to print\")\n) { name, surname, count in\n    for _ in 0..\u003ccount {\n        print(\"Hello \\(name) \\(surname)\")\n    }\n   }.run()\n```\n\nKeep in mind you have to pass 3 required arguments.\n\nAnother example, to describe a command which takes two (optional) options, `--name` and\n`--count` where the default value for name is `world` and the default value for\ncount is `1`.\n\n```swift\ncommand(\n  Option(\"name\", default: \"world\"),\n  Option(\"count\", default: 1, description: \"The number of times to print.\")\n) { name, count in\n  for _ in 0..\u003ccount {\n    print(\"Hello \\(name)\")\n  }\n}\n```\n\n```shell\n$ hello --help\nUsage:\n\n    $ hello\n\nOptions:\n    --name\n    --count - The number of times to print.\n\n$ hello\nHello world\n\n$ hello --name Kyle\nHello Kyle\n\n$ hello --name Kyle --count 4\nHello Kyle\nHello Kyle\nHello Kyle\nHello Kyle\n```\n\n##### Types of descriptors\n\n- Option - An optional option with a value.\n- Options - A option with a value which can be used multiple times, your command is passed an array containing all option values. You need to specify ahead of time how many values you expect. Example: `--myOption value1 value2 value3` \n- VariadicOption - Same as options, but instead of a fixed `count` of values, the user can just repeat the option with additional values. Example: `--myOption value1 --myOption value2`  \n- Flag - A boolean, on/off flag.\n- Argument - A positional argument.\n- VariadicArgument - A variadic argument\n\n**NOTE**: *It's important to describe your arguments after options and flags so the parser can differentiate between `--option value` and `--flag argument`.*\n\n#### Using the argument parser\n\n**NOTE**: *`ArgumentParser` itself is `ArgumentConvertible` so you can also\nget hold of the raw argument parser to perform any custom parsing.*\n\n```swift\ncommand { (name:String, parser:ArgumentParser) in\n  if parser.hasOption(\"verbose\") {\n    print(\"Verbose mode enabled\")\n  }\n\n  print(\"Hello \\(name)\")\n}\n```\n\n```shell\n$ tool Kyle --verbose\nVerbose mode enabled\nHello Kyle\n```\n\n### Examples tools using Commander\n\n- [QueryKit](https://github.com/QueryKit/querykit-cli) via CocoaPods Rome\n- [SwiftGen](https://github.com/SwiftGen/SwiftGen)\n- [RasterizeXCAssets](https://github.com/LinusU/RasterizeXCAssets)\n\n## Installation\n\nYou can install Commander in many ways, with SPM (Swift Package Manager), [Conche](https://github.com/Conche/Conche), CocoaPods or [CocoaPods-Rome](https://github.com/neonichu/Rome).\n\n### Frameworks and `rpath`\n\nIt's important to note that the `.framework` or dynamic library file for\nCommander (and any other dependency) must be available at run-time for your\ncommand line tool. Unless you are using SPM.\n\nApplications will look in their `rpath` which contains paths of where it expects\nthe `.framework`s to be found at.\n\nUsing a Swift script, you can use the `-F` flag for setting framework search\npaths, as follows:\n\n```swift\n#!/usr/bin/env xcrun swift -F Rome\n\nimport Commander\n```\n\nFor compiled Swift code, you will need to add an rpath pointing to your\ndependency frameworks, as follows:\n\n```shell\n$ install_name_tool -add_rpath \"@executable_path/../Frameworks/\"  \"bin/querykit\"\n```\n\nWhere \"../Frameworks\" relative to the executable path is used to find the\nframeworks and `bin/querykit` is the executable.\n\nWhen installing your executable on other systems it's important to copy the\nframeworks and the binary.\n\n### Architecture\n\n##### `CommandType`\n\n`CommandType` is the core protocol behind commands, it's an object or\nstructure that has a `run` method which takes an `ArgumentParser`.\n\nBoth the `command` functions and `Group` return a command that conforms to\n`CommandType` which can easily be interchanged.\n\n```swift\nprotocol CommandType {\n  func run(parser:ArgumentParser) throws\n}\n```\n\n##### `ArgumentConvertible`\n\nThe convenience `command` function takes a closure for your command that\ntakes arguments which conform to the `ArgumentConvertible` protocol. This\nallows Commander to easily convert arguments to the types you would like\nto use for your command.\n\n```swift\nprotocol ArgumentConvertible {\n  init(parser: ArgumentParser) throws\n}\n```\n\n##### `ArgumentParser`\n\nThe `ArgumentParser` is an object that allowing you to pull out options,\nflags and positional arguments.\n\n## License\n\nCommander is available under the BSD license. See the [LICENSE file](LICENSE)\nfor more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkylef%2FCommander","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkylef%2FCommander","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkylef%2FCommander/lists"}