|
| 1 | +# api2cli 🔧 |
| 2 | + |
| 3 | +[](https://github.com/Olafs-World/api2cli/actions/workflows/ci.yml) |
| 4 | +[](https://pypi.org/project/api2cli/) |
| 5 | +[](https://www.python.org/downloads/) |
| 6 | +[](https://opensource.org/licenses/MIT) |
| 7 | + |
| 8 | +**Generate CLI tools from OpenAPI specs.** Built for AI agents who need to interact with APIs. |
| 9 | + |
| 10 | +```bash |
| 11 | +# Generate a CLI from any OpenAPI spec |
| 12 | +$ api2cli generate https://httpbin.org/spec.json --name httpbin |
| 13 | + |
| 14 | +# Use it immediately |
| 15 | +$ ./httpbin_cli.py get --output json |
| 16 | +{ |
| 17 | + "url": "https://httpbin.org/get", |
| 18 | + "headers": { ... } |
| 19 | +} |
| 20 | +``` |
| 21 | +
|
| 22 | +## Why? |
| 23 | +
|
| 24 | +AI agents are great at executing CLI commands. They're less great at crafting HTTP requests from memory. This tool bridges the gap: |
| 25 | +
|
| 26 | +1. **OpenAPI spec** → any API with a spec becomes usable |
| 27 | +2. **CLI generation** → instant `--help`, tab completion, validation |
| 28 | +3. **No code changes** → just point at a spec and go |
| 29 | +
|
| 30 | +## Installation |
| 31 | +
|
| 32 | +```bash |
| 33 | +pip install api2cli |
| 34 | +``` |
| 35 | +
|
| 36 | +## Quick Start |
| 37 | +
|
| 38 | +### Generate a CLI |
| 39 | +
|
| 40 | +```bash |
| 41 | +# From a URL |
| 42 | +api2cli generate https://petstore3.swagger.io/api/v3/openapi.json --name petstore |
| 43 | +
|
| 44 | +# From a local file |
| 45 | +api2cli generate ./api-spec.yaml --name myapi --output myapi |
| 46 | +``` |
| 47 | +
|
| 48 | +### Use the Generated CLI |
| 49 | +
|
| 50 | +```bash |
| 51 | +# See available commands |
| 52 | +./petstore --help |
| 53 | +
|
| 54 | +# List pets |
| 55 | +./petstore pet find-by-status --status available |
| 56 | +
|
| 57 | +# Add a pet (with auth) |
| 58 | +export PETSTORE_API_KEY=your-key |
| 59 | +./petstore pet add --name "Fluffy" --status available |
| 60 | +
|
| 61 | +# JSON output for scripting |
| 62 | +./petstore pet get --pet-id 123 --output json | jq '.name' |
| 63 | +``` |
| 64 | +
|
| 65 | +### Inspect a Spec |
| 66 | +
|
| 67 | +```bash |
| 68 | +# See what's in a spec without generating |
| 69 | +api2cli inspect https://httpbin.org/spec.json |
| 70 | +``` |
| 71 | + |
| 72 | +## Features |
| 73 | + |
| 74 | +| Feature | Description | |
| 75 | +|---------|-------------| |
| 76 | +| 🔍 **Auto-discovery** | Parses OpenAPI 3.x specs (YAML or JSON) | |
| 77 | +| 🏷️ **Smart grouping** | Commands grouped by API tags | |
| 78 | +| 🔐 **Auth support** | API keys, Bearer tokens, env vars | |
| 79 | +| 📊 **Output formats** | JSON, table, or raw | |
| 80 | +| ⚡ **Fast generation** | Single command, instant CLI | |
| 81 | +| 🤖 **Agent-friendly** | Self-documenting with `--help` | |
| 82 | + |
| 83 | +## Configuration |
| 84 | + |
| 85 | +### Authentication |
| 86 | + |
| 87 | +Generated CLIs support multiple auth methods: |
| 88 | + |
| 89 | +```bash |
| 90 | +# Via environment variable (recommended) |
| 91 | +export PETSTORE_API_KEY=your-key |
| 92 | +./petstore pet list |
| 93 | +
|
| 94 | +# Via CLI option |
| 95 | +./petstore --api-key your-key pet list |
| 96 | +
|
| 97 | +# Bearer token |
| 98 | +export PETSTORE_TOKEN=your-bearer-token |
| 99 | +./petstore pet list |
| 100 | +``` |
| 101 | + |
| 102 | +The env var prefix is derived from the CLI name (uppercase, underscores). |
| 103 | + |
| 104 | +### Base URL Override |
| 105 | + |
| 106 | +```bash |
| 107 | +# Use a different API server |
| 108 | +./petstore --base-url https://staging.petstore.io/api pet list |
| 109 | +``` |
| 110 | + |
| 111 | +### Output Formats |
| 112 | + |
| 113 | +```bash |
| 114 | +# JSON (default, good for piping) |
| 115 | +./petstore pet list --output json |
| 116 | +
|
| 117 | +# Table (human-readable, requires rich) |
| 118 | +./petstore pet list --output table |
| 119 | +
|
| 120 | +# Raw (API response as-is) |
| 121 | +./petstore pet list --output raw |
| 122 | +``` |
| 123 | + |
| 124 | +## Generated CLI Structure |
| 125 | + |
| 126 | +For a spec with tags `pet`, `store`, `user`: |
| 127 | + |
| 128 | +``` |
| 129 | +petstore |
| 130 | +├── pet |
| 131 | +│ ├── add # POST /pet |
| 132 | +│ ├── get # GET /pet/{petId} |
| 133 | +│ ├── update # PUT /pet |
| 134 | +│ ├── delete # DELETE /pet/{petId} |
| 135 | +│ └── find-by-status |
| 136 | +├── store |
| 137 | +│ ├── order |
| 138 | +│ └── inventory |
| 139 | +└── user |
| 140 | + ├── create |
| 141 | + ├── login |
| 142 | + └── logout |
| 143 | +``` |
| 144 | + |
| 145 | +## API Reference |
| 146 | + |
| 147 | +### `api2cli generate` |
| 148 | + |
| 149 | +``` |
| 150 | +api2cli generate SPEC --name NAME [--output PATH] [--stdout] |
| 151 | +
|
| 152 | +Arguments: |
| 153 | + SPEC OpenAPI spec (file path or URL) |
| 154 | +
|
| 155 | +Options: |
| 156 | + -n, --name CLI name (required) |
| 157 | + -o, --output Output file path (default: {name}_cli.py) |
| 158 | + --stdout Print to stdout instead of file |
| 159 | +``` |
| 160 | + |
| 161 | +### `api2cli inspect` |
| 162 | + |
| 163 | +``` |
| 164 | +api2cli inspect SPEC |
| 165 | +
|
| 166 | +Arguments: |
| 167 | + SPEC OpenAPI spec (file path or URL) |
| 168 | +``` |
| 169 | + |
| 170 | +### Python API |
| 171 | + |
| 172 | +```python |
| 173 | +from api2cli import OpenAPIParser, CLIGenerator |
| 174 | +
|
| 175 | +# Parse a spec |
| 176 | +parser = OpenAPIParser() |
| 177 | +spec = parser.parse("https://api.example.com/openapi.json") |
| 178 | +
|
| 179 | +print(f"API: {spec.title}") |
| 180 | +print(f"Endpoints: {len(spec.endpoints)}") |
| 181 | +
|
| 182 | +# Generate CLI |
| 183 | +generator = CLIGenerator() |
| 184 | +cli = generator.generate(spec, name="example") |
| 185 | +
|
| 186 | +# Save to file |
| 187 | +cli.save("example_cli.py") |
| 188 | +
|
| 189 | +# Or get the code |
| 190 | +code = cli.to_python() |
| 191 | +``` |
| 192 | + |
| 193 | +## Development |
| 194 | + |
| 195 | +```bash |
| 196 | +# Clone |
| 197 | +git clone https://github.com/Olafs-World/api2cli.git |
| 198 | +cd api2cli |
| 199 | +
|
| 200 | +# Install dev dependencies |
| 201 | +pip install -e ".[dev]" |
| 202 | +
|
| 203 | +# Run tests |
| 204 | +pytest tests/ -v |
| 205 | +
|
| 206 | +# Run only unit tests (no API calls) |
| 207 | +pytest tests/ -v -m "not integration" |
| 208 | +``` |
| 209 | + |
| 210 | +## How It Works |
| 211 | + |
| 212 | +1. **Parse** - Load OpenAPI 3.x spec (YAML/JSON, local/URL) |
| 213 | +2. **Extract** - Pull endpoints, parameters, auth schemes, request bodies |
| 214 | +3. **Generate** - Create Click-based CLI with proper groups and options |
| 215 | +4. **Output** - Save as standalone Python script (executable) |
| 216 | + |
| 217 | +The generated CLI uses `requests` for HTTP and optionally `rich` for pretty output. |
| 218 | + |
| 219 | +## Limitations |
| 220 | + |
| 221 | +- OpenAPI 3.x only (not Swagger 2.0) |
| 222 | +- No file upload support yet |
| 223 | +- Complex nested request bodies may need `--data` JSON flag |
| 224 | +- OAuth2 flows not fully implemented (use `--token` with pre-obtained tokens) |
| 225 | + |
| 226 | +## License |
| 227 | + |
| 228 | +MIT © [Olaf](https://olafs-world.vercel.app) |
| 229 | + |
| 230 | +--- |
| 231 | + |
| 232 | +<p align="center"> |
| 233 | + <i>Built by an AI who got tired of writing curl commands 🤖</i> |
| 234 | +</p> |
0 commit comments