Skip to main content

Generate typed Python CLIs from OpenAPI specs with Pydantic model flattening into CLI flags

Project description

openapi-cli-gen

Generate a full CLI from any OpenAPI spec in seconds. Nested request bodies become flat --flags automatically.

PyPI Python License: MIT

# 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

No tool existed to take an OpenAPI spec and produce a typed Python CLI where nested request bodies are flattened into individual --flag arguments. Until now.

Why openapi-cli-gen?

  • Zero boilerplate -- point at a spec, get a working CLI
  • Nested model flattening -- --address.city NYC not --data '{"address":{"city":"NYC"}}'
  • Works at any depth -- 1, 2, 3+ levels of nesting with automatic dot-notation
  • Arrays, dicts, enums -- all handled (--tags dev --tags lead, --env KEY=val, --role {admin,user})
  • Auth from your spec -- reads securitySchemes, wires up --token + env vars automatically
  • Two modes -- generate a pip-installable package OR run instantly without code generation
  • Pluggable -- use standalone or plug API commands into your existing CLI

Quick Start

pip install openapi-cli-gen

Generate a CLI Package

openapi-cli-gen generate --spec https://api.example.com/openapi.json --name mycli
cd mycli && pip install -e .

Now your users can:

mycli users list
mycli users create --name John --email john@example.com --address.city NYC
mycli jobs create --retry.backoff.strategy exponential --retry.backoff.initial-delay-ms 2000

Run Instantly (No Code Generation)

Don't want to generate files? Point directly at any spec:

openapi-cli-gen run --spec api.yaml users list --limit 10

Inspect a Spec

See what commands would be generated before committing:

$ openapi-cli-gen inspect --spec api.yaml

API: My API v1.0
Endpoints: 14
Groups: 6
Auth schemes: 2

  users:
    GET     /users                  List all users
    POST    /users                  Create a new user [body]
    GET     /users/{user_id}        Get a user by ID
  orders:
    POST    /orders                 Create an order [body]
  ...

The Core Feature: Nested Model Flattening

This is what makes openapi-cli-gen different from every other tool. Your API has nested request bodies -- we flatten them into ergonomic CLI flags:

# Depth 1: address nested inside user
mycli users create --name John --address.city NYC --address.state NY

# Depth 2: CEO nested inside company
mycli companies create --name Acme --ceo.name Bob --ceo.email bob@acme.com

# Depth 3: backoff nested inside retry nested inside job config
mycli jobs create --name etl --retry.backoff.strategy exponential --retry.backoff.initial-delay-ms 2000

# JSON fallback for anything complex
mycli users create --address '{"street": "123 Main", "city": "NYC"}'

# Mix both -- dot-notation overrides JSON
mycli users create --address '{"city": "NYC"}' --address.city SF  # city=SF wins

Arrays

# Repeated flags for primitives
mycli users create --tags admin --tags reviewer
# Or comma-separated
mycli users create --tags admin,reviewer
# Or JSON
mycli users create --tags '["admin", "reviewer"]'

# JSON for arrays of objects
mycli orders create --items '[{"product_id": "abc", "quantity": 2}]'

Dicts

# Key=value syntax
mycli jobs create --environment JAVA_HOME=/usr/lib/jvm --environment PATH=/usr/bin
# Or JSON
mycli jobs create --environment '{"JAVA_HOME": "/usr/lib/jvm"}'

Enums

mycli users create --role admin   # choices shown in --help: {admin, user, viewer}
mycli users create --role superadmin  # ValidationError: Input should be 'admin', 'user' or 'viewer'

As a Library

Build a full CLI from a spec

from openapi_cli_gen import build_cli

app = build_cli(spec="openapi.yaml", name="mycli")
app()

Plug API commands into your existing CLI

Already have a CLI with custom commands? Add auto-generated API commands alongside them:

from openapi_cli_gen import build_command_group

# Returns {group: {command: CommandInfo}}
registry = build_command_group(spec="openapi.yaml", name="mycli")
# Integrate with your existing argparse-based CLI

Authentication

Auth auto-configures from your spec's securitySchemes:

# Via environment variable (recommended for CI/CD)
export MYCLI_TOKEN=sk-xxx
mycli users list

# Via flag (overrides env var)
mycli users list --token sk-xxx
Spec scheme CLI flag Env var
Bearer token --token {NAME}_TOKEN
API key --api-key {NAME}_API_KEY
Basic auth --username, --password {NAME}_USERNAME, {NAME}_PASSWORD

How It Works

Your OpenAPI spec (YAML/JSON)
    |
    v
1. Load & resolve all $ref references (jsonref)
2. Parse into typed models (openapi-pydantic)
3. Group endpoints by tag -> command groups
4. Flatten request body schemas into CLI flags (pydantic-settings)
5. Build CLI with dispatch: mycli <group> <command> --flags
    |
    v
Working CLI in seconds

Compared to Alternatives

Feature openapi-cli-gen specli restish Stainless
Language Python TypeScript Go Go
Generates distributable code Yes No No Yes
Runtime mode (no codegen) Yes Yes Yes No
Nested model flattening All depths Scalars only No 2 levels
Typed Pydantic models Yes No No N/A
Auth from spec Yes Partial Manual Yes
Pluggable into existing CLI Yes No No No
Open source Yes Yes Yes No

Supported

  • OpenAPI 3.0 and 3.1
  • All HTTP methods (GET, POST, PUT, PATCH, DELETE)
  • Local, external, and circular $ref resolution
  • Path parameters, query parameters, request bodies
  • Nested objects, arrays, dicts, enums, nullable fields
  • Bearer token and API key authentication
  • JSON, YAML, table (rich), and raw output formats

Status

Early release (v0.0.1). Core features work. Roadmap includes Typer output target (rich --help, shell completion), auto-pagination, OAuth2, and more.

Issues and feedback welcome.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openapi_cli_gen-0.0.1.tar.gz (68.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openapi_cli_gen-0.0.1-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file openapi_cli_gen-0.0.1.tar.gz.

File metadata

  • Download URL: openapi_cli_gen-0.0.1.tar.gz
  • Upload date:
  • Size: 68.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for openapi_cli_gen-0.0.1.tar.gz
Algorithm Hash digest
SHA256 1031d40eb20c6de6626d6f919db1549e6fb1a0cf8a0673ae12d6c97621b76423
MD5 37f2c542f7a68444b29dcef6c5406727
BLAKE2b-256 e7496162bf04ca8a1723eba32dacfa7f6aef1b85f087aeb1e5b0d6eef596bd8a

See more details on using hashes here.

File details

Details for the file openapi_cli_gen-0.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for openapi_cli_gen-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6cb2347b60b110d664e45d9b4a5a763c330a9c8da6bbea848b4613889f511175
MD5 4b1fc56740dbc2d93533e62cf5c6186b
BLAKE2b-256 3c06c424ea9ddb0db2621c8e6b118f4f88960cd61a5eaf516f7bd82809ec3fbf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page