openapi2cli

Turn any OpenAPI 3.x or Swagger 2.0 spec into a fully functional CLI — instantly, no code generation required.
openapi2cli reads a spec file at runtime and dynamically generates a CLI with resource-based commands, typed flags, authentication, and formatted output.
Install
Prebuilt binaries
Download the archive for your platform from the releases page, extract it, and put openapi2cli on your PATH.
With Go
go install github.com/s04/openapi2cli@latest
Build locally
git clone https://github.com/s04/openapi2cli.git
cd openapi2cli
go build -o openapi2cli .
Quick start
# Point at any spec and explore
openapi2cli --spec petstore.json --help
# Make a request
openapi2cli --spec petstore.json --server https://petstore.io/api/v3 \
pet find-pets-by-status --status available
# Load specs from URLs
openapi2cli --spec https://petstore.swagger.io/v2/swagger.json \
store get-inventory
Profiles
Save connection details so you don't repeat yourself:
# Create a profile
openapi2cli config set-profile myrouter \
--spec /path/to/spec.json \
--server https://192.168.1.1/rest \
--auth-type basic \
--auth-username admin \
--auth-password "" \
--insecure
# Use it
openapi2cli --profile myrouter interface get-interface
openapi2cli --profile myrouter ip get-ip-address -o table
# Manage profiles
openapi2cli config list
openapi2cli config show myrouter
openapi2cli config delete-profile myrouter
Authentication
Supports API key, Bearer token, and HTTP Basic auth via flags, environment variables, or profiles:
# Basic auth
openapi2cli --spec api.json --server https://host \
--username admin --password secret resource list
# Bearer token
openapi2cli --spec api.json --server https://host \
--token eyJhbGci... resource list
# API key
openapi2cli --spec api.json --server https://host \
--api-key "MyToken=abc123" resource list
Command and flag names
Resources come from the spec's tags (or the first path segment when untagged), operations from operationId, and flags from parameter names. All are converted to lowercase kebab-case, so petId becomes --pet-id and the tag Access applications becomes access-applications.
Every operation's --help lists its flags with the spec's descriptions, required markers, and allowed enum values.
If a spec parameter would collide with one of the CLI's own flags (for example a query parameter called token), it is exposed as --param-token.
Write operations
# Raw JSON body
openapi2cli --profile myapi resource create \
--data '{"name": "example", "enabled": true}'
# Body from file
openapi2cli --profile myapi resource create \
--data-file ./payload.json
# Individual body property flags
openapi2cli --profile myapi resource create \
--body-name example --body-enabled true
# Array properties: repeat the flag, comma-separate, or pass a JSON array
openapi2cli --profile myapi resource create \
--body-tags a,b --body-tags c
openapi2cli --profile myapi resource create \
--body-items '[{"id": 1}, {"id": 2}]'
# Object properties take a JSON object
openapi2cli --profile myapi resource create \
--body-category '{"id": 1, "name": "dogs"}'
--data and --data-file take precedence over --body-* flags.
openapi2cli --profile myapi resource list -o json # default, pretty-printed
openapi2cli --profile myapi resource list -o yaml # YAML
openapi2cli --profile myapi resource list -o table # ASCII table
openapi2cli --profile myapi resource list -o raw # raw response body
Debugging
# See the HTTP request without sending it
openapi2cli --profile myapi resource list --dry-run
# Verbose mode — request/response headers on stderr
openapi2cli --profile myapi resource list -v
# Skip TLS verification (self-signed certs)
openapi2cli --spec api.json --server https://host -k resource list
Shell completions
# Bash
openapi2cli completion bash >> ~/.bashrc
# Zsh
openapi2cli completion zsh >> ~/.zshrc
# Fish
openapi2cli completion fish > ~/.config/fish/completions/openapi2cli.fish
Tested with
| System |
Spec Version |
Endpoints |
Status |
| MikroTik RouterOS 7.22 |
Swagger 2.0 |
6,184 |
Working |
| TrueNAS SCALE 24.04 |
OpenAPI 3.0 |
643 |
Working |
| Proxmox VE |
OpenAPI 3.0 |
61+ |
Working |
| OPNsense 25.7 |
OpenAPI 3.0 |
701 |
Working |
| Swagger Petstore v2 |
Swagger 2.0 |
20 |
Working |
| Swagger Petstore v3 |
OpenAPI 3.0 |
19 |
Working |
Community spec sources:
Relative servers URLs (for example /api/v3) are resolved against the spec's own URL when the spec is loaded over HTTP, so --spec https://host/openapi.json usually needs no --server.
Large specs
Specs are parsed on every invocation. A spec with a few thousand operations loads in well under a second, so there is no build or cache step to manage. Loading from a URL re-downloads the spec each time; save it locally or in a profile for anything you use often.
How it works
spec file/URL → parse (libopenapi) → normalize to unified model → build cobra commands → execute
- Loads the spec from a file, URL, or stdin
- Detects OpenAPI 3.x vs Swagger 2.0 and parses with libopenapi
- Normalizes into a unified internal model (same structure for both versions)
- Generates a Cobra command tree grouped by tags (or path segments when untagged)
- At runtime, builds HTTP requests from flags, applies auth, formats responses
Global flags
| Flag |
Short |
Description |
--spec |
|
Path or URL to spec file |
--server |
|
API server base URL (overrides spec) |
--profile |
|
Use a saved configuration profile |
--output |
-o |
Output format: json, yaml, table, raw |
--username |
|
Username for basic auth |
--password |
|
Password for basic auth |
--token |
|
Bearer token |
--api-key |
|
API key value |
--insecure |
-k |
Skip TLS certificate verification |
--verbose |
-v |
Print request/response headers |
--dry-run |
|
Show request without executing |
--timeout |
|
HTTP request timeout (default: 30s) |
--version |
|
Print the version and exit |
Development
go test ./...
golangci-lint run ./...
Releases are built by GoReleaser when a v* tag is pushed.
License
MIT