openapi-cli-gen
An OpenAPI CLI generator for Python. Generate a typed CLI from any OpenAPI 3.x spec in seconds. Nested request bodies become flat --flags automatically.
Use openapi-cli-gen when you want an OpenAPI-to-CLI tool, Swagger CLI generator, or FastAPI CLI generator that produces Python-native command line apps.
If this is useful, a star helps other developers find it. If it breaks on your spec, please send it over: open a spec compatibility report.
# Instead of this:
curl -X POST /api/users -d '{"name": "John", "address": {"city": "NYC", "state": "NY"}}'
# You get this:
mycli users create --name John --address.city NYC --address.state NY
Install
# Recommended: pipx (installs in isolated environment)
pipx install openapi-cli-gen
# Or with uv
uv tool install openapi-cli-gen
# Or in a virtual environment
pip install openapi-cli-gen
Try It Now
Point at any public API — no setup, no files needed:
# Get a random cat fact
openapi-cli-gen run --spec https://catfact.ninja/docs --base-url https://catfact.ninja \
facts get-random
# Browse cat breeds as a table
openapi-cli-gen run --spec https://catfact.ninja/docs --base-url https://catfact.ninja \
breeds get --limit 5 --output-format table
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ breed ┃ country ┃ origin ┃ coat ┃ pattern ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ Abyssinian │ Ethiopia │ Natural/Stand… │ Short │ Ticked │
│ Aegean │ Greece │ Natural/Stand… │ Semi-long │ Bi- or tri-… │
│ American Curl │ United States │ Mutation │ Short/Long │ All │
└────────────────┴───────────────┴────────────────┴────────────┴───────────────┘
# Inspect any spec to see what commands you'd get
openapi-cli-gen inspect --spec https://petstore3.swagger.io/api/v3/openapi.json
Generate Your Own CLI
openapi-cli-gen generate --spec https://api.example.com/openapi.json --name mycli
cd mycli && pip install -e .
mycli users list
mycli users create --name John --email john@example.com --address.city NYC
Ship it to your users: pip install mycli.
Useful guides:
- Generate a CLI from an OpenAPI Spec
- Generate a CLI from a FastAPI App
- OpenAPI Generator vs openapi-cli-gen
When to Use It
Use this when you have an OpenAPI or Swagger spec and want a human-facing command line app, not another SDK directory.
- Generate an internal admin CLI from a FastAPI app's
/openapi.json. - Turn a public REST API into a scriptable Python CLI.
- Give support, ops, or QA teams typed commands instead of copy-pasted
curl. - Publish a lightweight API wrapper on PyPI without hand-writing every endpoint.
If you need SDKs in many languages, OpenAPI Generator is usually the right
tool. If you need a Python command line app that exposes API endpoints as
discoverable subcommands and flags, openapi-cli-gen is built for that lane.
Nested Model Flattening
The core feature. Works at any depth:
--address.city NYC # depth 1
--ceo.name Bob --ceo.email bob@acme.com # depth 2
--retry.backoff.strategy exponential # depth 3
--tags admin --tags reviewer # arrays
--environment JAVA_HOME=/usr/lib/jvm # dicts
--role admin # enums (validated)
--address '{"street": "123 Main", "city": "NYC"}' # JSON fallback
As a Library
from openapi_cli_gen import build_cli
app = build_cli(spec="openapi.yaml", name="mycli")
app()
Or plug API commands into your existing CLI:
from openapi_cli_gen import build_command_group
registry = build_command_group(spec="openapi.yaml", name="mycli")
Auth
Auto-configures from your spec's securitySchemes:
export MYCLI_TOKEN=sk-xxx # env var
mycli users list --token sk-xxx # or flag (overrides env)
HTTPS / Self-Signed Certs
For APIs behind TLS with self-signed or internal certificates:
# Skip certificate verification
export MYCLI_VERIFY_SSL=false
# Or use a custom CA bundle
export MYCLI_CA_CERT=/path/to/ca-bundle.pem
# mTLS (client certificate)
export MYCLI_CLIENT_CERT=/path/to/client.pem
export MYCLI_CLIENT_KEY=/path/to/client-key.pem
The generate and run commands also accept --no-verify-ssl, --ca-cert, --client-cert, and --client-key flags.
Pre-Built CLIs
Six ready-to-use CLI wrappers, each generated from its API's official OpenAPI spec. Install one and start using it instantly:
# OpenAI — every endpoint (chat, embeddings, images, audio, files,
# vector stores, batch, fine-tuning, ...) as a typed subcommand
pipx install openai-rest-cli
export OPENAI_REST_CLI_TOKEN=sk-...
openai-rest-cli chat create-completion --model gpt-4o-mini \
--messages '[{"role":"user","content":"Hi"}]'
# Qdrant — collections, points, search, snapshots, distributed
pipx install qdrant-rest-cli
qdrant-rest-cli collections get-collections
qdrant-rest-cli search points --collection-name pets \
--root '{"vector":[0.1,0.2,0.3,0.4],"limit":5,"with_payload":true}'
# Meilisearch — indexes, documents, search, settings, tasks
pipx install meilisearch-rest-cli
meilisearch-rest-cli indexes list
meilisearch-rest-cli documents replace --index-uid movies \
--root '[{"id":1,"title":"The Matrix"}]'
# Typesense — collections, documents, search (72 search flags typed)
pipx install typesense-rest-cli
export TYPESENSE_REST_CLI_API_KEY=xyz
typesense-rest-cli documents search-collection --collection-name books \
-q programmer --query-by title,author
# AdGuard Home — filtering, clients, DHCP, rewrite, TLS, stats
pipx install adguard-home-cli
export ADGUARD_HOME_CLI_USERNAME=admin
export ADGUARD_HOME_CLI_PASSWORD=xxx
adguard-home-cli filtering add-url --name "OISD" --url "https://big.oisd.nl/" --no-whitelist
# Immich — ~250 subcommands across 36 groups including multipart upload
pipx install immich-rest-cli
export IMMICH_REST_CLI_TOKEN=your-key
immich-rest-cli assets upload --asset-data photo.jpg \
--device-asset-id "id-1" --device-id "script" \
--file-created-at 2026-04-10T00:00:00.000Z \
--file-modified-at 2026-04-10T00:00:00.000Z --filename photo.jpg
Each wrapper's source README (install, auth, real verified commands) lives under wrappers/ in this monorepo.
| Wrapper | PyPI | Source |
|---|---|---|
| openai-rest-cli | pypi | wrappers/openai-rest-cli/ |
| qdrant-rest-cli | pypi | wrappers/qdrant-rest-cli/ |
| meilisearch-rest-cli | pypi | wrappers/meilisearch-rest-cli/ |
| typesense-rest-cli | pypi | wrappers/typesense-rest-cli/ |
| adguard-home-cli | pypi | wrappers/adguard-home-cli/ |
| immich-rest-cli | pypi | wrappers/immich-rest-cli/ |
Tested Against Real APIs
36/36 regression tests passing across 6 live APIs. Full CRUD validated — not just reads.
| API | Type | Tests | Notes |
|---|---|---|---|
| OpenAI | AI/LLM | 8/8 | Models, Chat Completions, Embeddings, Images (DALL-E), Moderations, Files, Vector Stores |
| Qdrant (collections) | Vector DB | 7/7 | Service root, healthz, collections CRUD, exists |
| Qdrant Points | Vector DB | 7/7 | Upsert, get, scroll, count, query-points, cleanup — vector search with real similarity scores |
| Meilisearch | Search | 7/7 | Health, version, indexes, stats, tasks |
| Typesense | Search | 1/1 | Health verified live; documents index --root + search-collection -q ... verified via wrapper |
| GitHub | Public | 6/6 | Meta, licenses, users, rate limit, zen, octocat |
Real commands that work today:
# OpenAI Chat — one command, real GPT-4o-mini response
openapi-cli-gen run --spec <openai-spec> chat create-completion \
--model gpt-4o-mini \
--messages '[{"role":"user","content":"Hello"}]'
# Qdrant vector search — create collection, insert vectors, semantic search
openapi-cli-gen run --spec <qdrant-spec> --base-url http://localhost:6333 \
collections create --collection-name pets \
--vectors '{"size": 4, "distance": "Cosine"}'
openapi-cli-gen run --spec <qdrant-spec> --base-url http://localhost:6333 \
search query-points --collection-name pets \
--query '[0.1, 0.2, 0.3, 0.4]' --limit 5
# Meilisearch — add documents and search, verified against live 1.41
openapi-cli-gen run --spec <meili-spec> --base-url http://localhost:7700 \
documents replace --index-uid movies \
--root '[{"id":1,"title":"The Matrix"}]'
# GitHub — public API, no auth needed
openapi-cli-gen run --spec <github-spec> --base-url https://api.github.com \
users users/get-by-username --username torvalds
See CHANGELOG.md for the full list of bug fixes and improvements.
Compared to Alternatives
| Feature | openapi-cli-gen | specli | restish | Stainless |
|---|---|---|---|---|
| Nested model flattening | All depths | Scalars only | No | 2 levels |
| Generates distributable code | Yes | No | No | Yes |
| Runtime mode (no codegen) | Yes | Yes | Yes | No |
| Pluggable into existing CLI | Yes | No | No | No |
| Open source | Yes | Yes | Yes | No |
See also: OpenAPI Generator vs openapi-cli-gen.
Status
Early release. Core features work. If you have a FastAPI app, internal API, or public OpenAPI spec with unusual auth, nested bodies, arrays, unions, or multipart uploads, please open a spec compatibility report.
License
MIT
Metadata
Release files for openapi-cli-gen 0.0.20
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| openapi_cli_gen-0.0.20.tar.gz | 7.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openapi_cli_gen-0.0.20-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 7.1 MB
Release files / openapi_cli_gen-0.0.20.tar.gz
| Download URL | openapi_cli_gen-0.0.20.tar.gz |
|---|---|
| Size | 7.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7831b183da3e8d90dae7c121fa33785ff5e39b47708ddedbd70e9367965897de
|
|
BLAKE2b-256 checksum How to use checksums |
96f8ba2cb7983eb9285a4b27a1f44ca783dc84d9513358bb6a84f5f551d5b107
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / openapi_cli_gen-0.0.20-py3-none-any.whl
| Download URL | openapi_cli_gen-0.0.20-py3-none-any.whl |
|---|---|
| Size | 38.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
320ff4761cde0426f8855cfa9c4e207a5604f7702bb7dffb92aa7abb8df083c5
|
|
BLAKE2b-256 checksum How to use checksums |
2241627fb9b646929c7cc59a2b4a6b182e41f67fcc0c5464ffeee1063428cdda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|