{"id":13582039,"url":"https://github.com/danielgtaylor/openapi-cli-generator","last_synced_at":"2025-07-01T18:03:41.397Z","repository":{"id":55562044,"uuid":"150926514","full_name":"danielgtaylor/openapi-cli-generator","owner":"danielgtaylor","description":"Generate a CLI from an OpenAPI 3 specification","archived":false,"fork":false,"pushed_at":"2023-10-25T21:22:27.000Z","size":230,"stargazers_count":190,"open_issues_count":24,"forks_count":49,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-20T00:03:14.270Z","etag":null,"topics":["cli","code-generator","openapi","rest-api","rest-client"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/danielgtaylor.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-30T03:27:34.000Z","updated_at":"2025-05-17T20:15:50.000Z","dependencies_parsed_at":"2024-06-18T15:30:32.271Z","dependency_job_id":"3841f782-7fb0-4e88-a6be-d7faddbf59e9","html_url":"https://github.com/danielgtaylor/openapi-cli-generator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/danielgtaylor/openapi-cli-generator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielgtaylor%2Fopenapi-cli-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielgtaylor%2Fopenapi-cli-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielgtaylor%2Fopenapi-cli-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielgtaylor%2Fopenapi-cli-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danielgtaylor","download_url":"https://codeload.github.com/danielgtaylor/openapi-cli-generator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielgtaylor%2Fopenapi-cli-generator/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263013703,"owners_count":23399812,"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":["cli","code-generator","openapi","rest-api","rest-client"],"created_at":"2024-08-01T15:02:23.941Z","updated_at":"2025-07-01T18:03:41.297Z","avatar_url":"https://github.com/danielgtaylor.png","language":"Go","readme":"# OpenAPI CLI Generator\n\n[![GoDoc](https://godoc.org/github.com/danielgtaylor/openapi-cli-generator?status.svg)](https://godoc.org/github.com/danielgtaylor/openapi-cli-generator)\n[![Build Status](https://travis-ci.org/danielgtaylor/openapi-cli-generator.svg?branch=master)](https://travis-ci.org/danielgtaylor/openapi-cli-generator)\n[![Go Report Card](https://goreportcard.com/badge/github.com/danielgtaylor/openapi-cli-generator)](https://goreportcard.com/report/github.com/danielgtaylor/openapi-cli-generator)\n[![Platforms](https://img.shields.io/badge/platform-win%20%7C%20mac%20%7C%20linux-ligh.svg)](https://github.com/danielgtaylor/openapi-cli-generator/releases)\n\n\u003cimg alt=\"openapi-to-cli\" src=\"https://user-images.githubusercontent.com/106826/46594546-a8bb2480-ca88-11e8-90ec-fb87e51009a8.png\"\u003e\n\n---\n\n**Note: this project has been superceded by Restish, an advanced auto-configured OpenAPI CLI that just works:**\n\n- https://rest.sh/\n- https://github.com/danielgtaylor/restish\n\n---\n\nThis project can be used to generate CLIs from OpenAPI 3 specs. The generated CLIs have the following features:\n\n- Authentication support for API keys and [Auth0](https://auth0.com/).\n- Commands, subcommands, \u0026 flag parsing through [Cobra](https://github.com/spf13/cobra)\n- Configuration through [Viper](https://github.com/spf13/viper)\n  - JSON, YAML, or TOML config files in `/etc/` and `$HOME`, e.g. `{\"verbose\": true}` in `~/.my-app/config.json`\n  - From environment: `APP_NAME_VERBOSE=1`\n  - From flags: `--verbose`\n- HTTP middleware through [Gentleman](https://github.com/h2non/gentleman/)\n- Command middleware with custom parameters (see customization below)\n- Input through `stdin` or [CLI shorthand](https://github.com/danielgtaylor/openapi-cli-generator/tree/master/shorthand)\n- Built-in cache to save data between runs\n- Fast structured logging via [zerolog](https://github.com/rs/zerolog)\n- Pretty output colored by [Chroma](https://github.com/alecthomas/chroma)\n- Response filtering \u0026 projection by [JMESPath](http://jmespath.org/) plus [enhancements](https://github.com/danielgtaylor/go-jmespath-plus#enhancements)\n\n## Getting Started\n\nFirst, make sure you have Go installed. Then, you can grab this project:\n\n```sh\n$ go get -u github.com/danielgtaylor/openapi-cli-generator\n```\n\nNext, make your project directory and generate the commands file.\n\n```sh\n# Set up your new project\n$ mkdir my-cli \u0026\u0026 cd my-cli\n\n# Create the default main file. The app name is used for config and env settings.\n$ openapi-cli-generator init \u003capp-name\u003e\n\n# Generate the commands\n$ openapi-cli-generator generate openapi.yaml\n```\n\nLast, add a line like the following to your `main.go` file:\n\n```go\nopenapiRegister(false)\n```\n\nIf you would like to generate a client for many APIs and have each available under their own namespace, pass `true` instead. Next, build your client:\n\n```sh\n# Build \u0026 install the generated client.\n$ go install\n\n# Test it out!\n$ my-cli --help\n```\n\n## OpenAPI Extensions\n\nSeveral extensions properties may be used to change the behavior of the CLI.\n\n| Name                | Description                                                        |\n| ------------------- | ------------------------------------------------------------------ |\n| `x-cli-aliases`     | Sets up command aliases for operations.                            |\n| `x-cli-description` | Provide an alternate description for the CLI.                      |\n| `x-cli-ignore`      | Ignore this path, operation, or parameter.                         |\n| `x-cli-hidden`      | Hide this path, or operation.                                      |\n| `x-cli-name`        | Provide an alternate name for the CLI.                             |\n| `x-cli-waiters`     | Generate commands/params to wait until a certain state is reached. |\n\n### Aliases\n\nThe following example shows how you would set up a command that can be invoked by either `list-items` or simply `ls`:\n\n```yaml\npaths:\n  /items:\n    get:\n      operationId: ListItems\n      x-cli-aliases:\n        - ls\n```\n\n### Description\n\nYou can override the default description easily:\n\n```yaml\npaths:\n  /items:\n    description: Some info talking about HTTP headers.\n    x-cli-description: Some info talking about command line arguments.\n```\n\n### Exclusion\n\nIt is possible to exclude paths, operations, and/or parameters from the generated CLI. No code will be generated as they will be completely skipped.\n\n```yaml\npaths:\n  /included:\n    description: I will get included in the CLI.\n  /excluded:\n    x-cli-ignore: true\n    description: I will not be in the CLI :-(\n```\n\nAlternatively, you can have the path or operation exist in the UI but be hidden from the standard help list. Specific help is still available via `my-cli my-hidden-operation --help`:\n\n```yaml\npaths:\n  /hidden:\n    x-cli-hidden: true\n```\n\n### Name\n\nYou can override the default name for the API, operations, and params:\n\n```yaml\ninfo:\n  x-cli-name: foo\npaths:\n  /items:\n    operationId: myOperation\n    x-cli-name: my-op\n    parameters:\n      - name: id\n        x-cli-name: item-id\n        in: query\n```\n\nWith the above, you would be able to call `my-cli my-op --item-id=12`.\n\n### Waiters\n\nWaiters allow you to declaratively define special commands and parameters that will cause a command to block and wait until a particular condition has been met. This is particularly useful for asyncronous operations. For example, you might submit an order and then wait for that order to have been charged successfully before continuing on.\n\nAt a high level, waiters consist of an operation and a set of matchers that select a value and compare it to an expectation. For the example above, you might call the `GetOrder` operation every 30 seconds until the response's JSON `status` field is equal to `charged`. Here is what that would look like in your OpenAPI YAML file:\n\n```yaml\ninfo:\n  title: Orders API\npaths:\n  /order/{id}:\n    get:\n      operationId: GetOrder\n      description: Get an order's details.\n      parameters:\n        - name: id\n          in: path\n      responses:\n        200:\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  status:\n                    type: string\n                    enum: ['placed', 'charged', 'shipped', 'returned']\nx-cli-waiters:\n  order-charged:\n    delay: 30\n    attempts: 10\n    operationId: GetOrder\n    matchers:\n      - select: response.body#status\n        expected: charged\n```\n\nThe generated CLI will work like this: `my-cli wait order-charged $ID` where `$ID` corresponds to the `GetOrder` operation's `id` parameter. It will try to get and match the status 10 times, with a pause of 30 seconds between tries. If it matches, it will exit with a zero status code. If it fails, it will exit with a non-zero exit code and log a message.\n\nThis is a great start, but we can make this a little bit friendlier to use. Take a look at this modified waiter configuration:\n\n```yaml\nx-cli-waiters:\n  order-charged:\n    short: Short description for CLI `--help`\n    long: Long description for CLI `--help`\n    delay: 30\n    attempts: 10\n    operationId: GetOrder\n    matchers:\n      - select: response.body#status\n        expected: charged\n      - select: response.status\n        expected: 404\n        state: failure\n    after:\n      CreateOrder:\n        id: response.body#order_id\n```\n\nHere we added two new features:\n\n1. A short-circuit to fail fast. If we type an invalid order ID then we want the command to exit immediately with a non-zero exit code.\n\n2. The `after` block allows us to add a parameter to an _existing_ operation to invoke the waiter. This block says that after a call to `CreateOrder` with a `--wait-order-charged` param, it should call the waiter's `GetOrder` operation with the `id` param set to the result of the `response.body#order_id` selector.\n\nYou can now create and wait on an order via `my-cli create-order \u003corder.json --wait-order-charged`.\n\n#### Matchers\n\nThe following matcher fields are available:\n\n| Field      | Description                                                                                     | Example           |\n| ---------- | ----------------------------------------------------------------------------------------------- | ----------------- |\n| `select`   | The value selection criteria. See the selector table below.                                     | `response.status` |\n| `test`     | The test to perform. Defaults to `equal` but can be set to `any` and `all` to match list items. | `equal`           |\n| `expected` | The expected value                                                                              | `charged`         |\n| `state`    | The state to set. Defaults to `success` but can be set to `failure`.                            | `success`         |\n\nThe following selectors are available:\n\n| Selector          | Description               | Argument       | Example                         |\n| ----------------- | ------------------------- | -------------- | ------------------------------- |\n| `request.param`   | Request parameter         | Parameter name | `request.param#id`              |\n| `request.body`    | Request body query        | JMESPath query | `request.body#order.id`         |\n| `response.status` | Response HTTP status code | -              | `response.status`               |\n| `response.header` | Response HTTP header      | Header name    | `response.header#content-type`  |\n| `response.body`   | Response body query       | JMESPath query | `response.body#orders[].status` |\n\n## Customization\n\nYour `main.go` is the entrypoint to your generated CLI, and may be customized to add additional logic and features. For example, you might set custom headers or handle auth before a request goes out on the wire. The `apikey` module provides a sample implementation.\n\n### Configuration Description\n\nTODO: Show table describing all well-known configuration keys.\n\n### Custom Global Flags\n\nIt's possible to supply custom flags and a pre-run function. For example, say your OpenAPI spec has two servers: production and testing. You could add a `--test` flag to select the second server.\n\n```go\nfunc main() {\n\t// ... init code ...\n\n\t// Add a `--test` flag to enable hitting testing.\n\tcli.AddGlobalFlag(\"test\", \"\", \"Use test endpoint\", false)\n\n\tcli.PreRun = func(cmd *cobra.Command, args []string) error {\n\t\tif viper.GetBool(\"test\") {\n\t\t\t// Use the test server\n\t\t\tviper.Set(\"server-index\", 1)\n\t\t}\n}\n```\n\n### HTTP Middleware\n\n[Gentleman](https://github.com/h2non/gentleman/) provides support for HTTP request and response middleware. Don't forget to call `h.Next(ctx)` in your handler! For example:\n\n```go\n// Register a request middleware handler to print the path.\ncli.Client.UseRequest(func(ctx *context.Context, h context.Handler) {\n\tfmt.Printf(\"Request path: %s\\n\", ctx.Request.URL.Path)\n\th.Next(ctx)\n})\n\n// Register a response middleware handler to print the status code.\ncli.Client.UseResponse(func(ctx *context.Context, h context.Handler) {\n\tfmt.Printf(\"Response status: %d\\n\", ctx.Response.StatusCode)\n\th.Next(ctx)\n})\n```\n\n### Custom Command Flags \u0026 Middleware\n\nWhile the above HTTP middleware is great for adding headers or logging various things, there are times when you need to modify the behavior of a generated command. You can do so by registering custom command flags and using command middleware.\n\nFlags and middleware are applied to a _command path_, which is a space-separated list of commands in a hierarchy. For example, if you have a command `foo` which has a subcommand `bar`, then the command path to reference `bar` for flags and middleware would be `foo bar`.\n\nNote that any calls to `cli.AddFlag` must be made **before** calling the generated command registration function (e.g. `openapiRegister(...)`) or the flags will not get created properly.\n\nHere's an example showing how a custom flag can change the command response:\n\n```go\n// Register a new custom flag for the `foo` command.\ncli.AddFlag(\"foo\", \"custom\", \"\", \"description\", \"\")\n\ncli.RegisterAfter(\"foo\", func(cmd *cobra.Command, params *viper.Viper, resp *gentleman.Response, data interface{}) interface{} {\n  m := data.(map[string]interface{})\n  m[\"custom\"] = params.GetString(\"custom\")\n  return m\n})\n\n// Register our generated commands with the CLI after the above.\nopenapiRegister(false)\n```\n\nIf the `foo` command would normally return a JSON object like `{\"hello\": \"world\"}` it would now return the following if called with `--custom=test`:\n\n```json\n{\n  \"custom\": \"test\",\n  \"hello\": \"world\"\n}\n```\n\n### Authentication \u0026 Authorization\n\nSee the `apikey` module for a simple example of a pre-shared key.\n\nIf instead you use a third party auth system that vends tokens and want your users to be able to log in and use the API, here's an example using Auth0:\n\n```go\nfunc main() {\n\tcli.Init(\u0026cli.Config{\n\t\tAppName:   \"example\",\n\t\tEnvPrefix: \"EXAMPLE\",\n\t\tVersion:   \"1.0.0\",\n\t})\n\n  // Auth0 requires a client ID, issuer base URL, and audience fields when\n  // requesting a token. We set these up here and use the Authorization Code\n  // with PKCE flow to log in, which opens a browser for the user to log into.\n  clientID := \"abc123\"\n  issuer := \"https://mycompany.auth0.com/\"\n\n  cli.UseAuth(\"user\", \u0026oauth.AuthCodeHandler{\n    ClientID: \"clientID\",\n    AuthorizeURL: issuer+\"authorize\",\n    TokenURL: issuer+\"oauth/token\",\n    Keys: []string{\"audience\"},\n    Params: []string{\"audience\"},\n    Scopes: []string{\"offline_access\"},\n  })\n\n  // TODO: Register API commands here\n  // ...\n\n\tcli.Root.Execute()\n}\n```\n\nNote that there is a convenience module when using Auth0 specifically, allowing you to do this:\n\n```go\nauth0.InitAuthCode(clientID, issuer,\n  auth0.Type(\"user\"),\n  auth0.Scopes(\"offline_access\"))\n```\n\nThe expanded example above is more useful when integrating with other services since it uses basic OAuth 2 primitives.\n\n## Development\n\n### Working with Templates\n\nThe code generator is configured to bundle all necessary assets into the final executable by default. If you wish to modify the templates, you can use the `go-bindata` tool to help:\n\n```sh\n# One-time setup of the go-bindata tool:\n$ go get -u github.com/shuLhan/go-bindata/...\n\n# Set up development mode (load data from actual files in ./templates/)\n$ go-bindata -debug ./templates/...\n\n# Now, do all your edits to the templates. You can test with:\n$ go run *.go generate my-api.yaml\n\n# Build the final static embedded files and code generator executable.\n$ go generate\n$ go install\n```\n\n## License\n\nhttps://dgt.mit-license.org/\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielgtaylor%2Fopenapi-cli-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielgtaylor%2Fopenapi-cli-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielgtaylor%2Fopenapi-cli-generator/lists"}