openapi2cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -e ".[dev]"
28
+
29
+ - name: Lint with ruff
30
+ run: ruff check api2cli/ tests/
31
+
32
+ - name: Run unit tests
33
+ run: pytest tests/ -v -m "not integration" --tb=short
34
+
35
+ - name: Run integration tests
36
+ run: pytest tests/ -v -m "integration" --tb=short
37
+
38
+ publish:
39
+ needs: test
40
+ runs-on: ubuntu-latest
41
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
42
+
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+
46
+ - name: Set up Python
47
+ uses: actions/setup-python@v5
48
+ with:
49
+ python-version: "3.11"
50
+
51
+ - name: Build package
52
+ run: |
53
+ pip install build
54
+ python -m build
55
+
56
+ - name: Publish to PyPI
57
+ uses: pypa/gh-action-pypi-publish@release/v1
58
+ with:
59
+ password: ${{ secrets.PYPI_API_TOKEN }}
60
+ continue-on-error: true
@@ -0,0 +1,45 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Testing
24
+ .pytest_cache/
25
+ .coverage
26
+ htmlcov/
27
+ .tox/
28
+ .nox/
29
+
30
+ # IDE
31
+ .idea/
32
+ .vscode/
33
+ *.swp
34
+ *.swo
35
+ *~
36
+
37
+ # OS
38
+ .DS_Store
39
+ Thumbs.db
40
+
41
+ # Env
42
+ .env
43
+ .venv/
44
+ env/
45
+ venv/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Olaf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,267 @@
1
+ Metadata-Version: 2.4
2
+ Name: openapi2cli
3
+ Version: 0.1.0
4
+ Summary: Generate CLI tools from OpenAPI specs — built for AI agents
5
+ Project-URL: Homepage, https://github.com/Olafs-World/openapi2cli
6
+ Project-URL: Repository, https://github.com/Olafs-World/openapi2cli
7
+ Project-URL: Documentation, https://github.com/Olafs-World/openapi2cli#readme
8
+ Author-email: Olaf <olaf.bot@agentmail.to>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,api,cli,code-generation,openapi,swagger
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Internet :: WWW/HTTP
21
+ Classifier: Topic :: Software Development :: Code Generators
22
+ Requires-Python: >=3.9
23
+ Requires-Dist: click>=8.0
24
+ Requires-Dist: jinja2>=3.0
25
+ Requires-Dist: pyyaml>=6.0
26
+ Requires-Dist: requests>=2.25
27
+ Requires-Dist: rich>=13.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
30
+ Requires-Dist: pytest>=7.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.1; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # openapi2cli 🔧
35
+
36
+ [![CI](https://github.com/Olafs-World/openapi2cli/actions/workflows/ci.yml/badge.svg)](https://github.com/Olafs-World/openapi2cli/actions/workflows/ci.yml)
37
+ [![PyPI version](https://badge.fury.io/py/openapi2cli.svg)](https://pypi.org/project/openapi2cli/)
38
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
40
+
41
+ **Generate CLI tools from OpenAPI specs.** Built for AI agents who need to interact with APIs.
42
+
43
+ ```bash
44
+ # Generate a CLI from any OpenAPI spec
45
+ $ openapi2cli generate https://httpbin.org/spec.json --name httpbin
46
+
47
+ # Use it immediately
48
+ $ ./httpbin_cli.py get --output json
49
+ {
50
+ "url": "https://httpbin.org/get",
51
+ "headers": { ... }
52
+ }
53
+ ```
54
+
55
+ ## Why?
56
+
57
+ AI agents are great at executing CLI commands. They're less great at crafting HTTP requests from memory. This tool bridges the gap:
58
+
59
+ 1. **OpenAPI spec** → any API with a spec becomes usable
60
+ 2. **CLI generation** → instant `--help`, tab completion, validation
61
+ 3. **No code changes** → just point at a spec and go
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ pip install openapi2cli
67
+ ```
68
+
69
+ ## Quick Start
70
+
71
+ ### Generate a CLI
72
+
73
+ ```bash
74
+ # From a URL
75
+ openapi2cli generate https://petstore3.swagger.io/api/v3/openapi.json --name petstore
76
+
77
+ # From a local file
78
+ openapi2cli generate ./api-spec.yaml --name myapi --output myapi
79
+ ```
80
+
81
+ ### Use the Generated CLI
82
+
83
+ ```bash
84
+ # See available commands
85
+ ./petstore --help
86
+
87
+ # List pets
88
+ ./petstore pet find-by-status --status available
89
+
90
+ # Add a pet (with auth)
91
+ export PETSTORE_API_KEY=your-key
92
+ ./petstore pet add --name "Fluffy" --status available
93
+
94
+ # JSON output for scripting
95
+ ./petstore pet get --pet-id 123 --output json | jq '.name'
96
+ ```
97
+
98
+ ### Inspect a Spec
99
+
100
+ ```bash
101
+ # See what's in a spec without generating
102
+ openapi2cli inspect https://httpbin.org/spec.json
103
+ ```
104
+
105
+ ## Features
106
+
107
+ | Feature | Description |
108
+ |---------|-------------|
109
+ | 🔍 **Auto-discovery** | Parses OpenAPI 3.x specs (YAML or JSON) |
110
+ | 🏷️ **Smart grouping** | Commands grouped by API tags |
111
+ | 🔐 **Auth support** | API keys, Bearer tokens, env vars |
112
+ | 📊 **Output formats** | JSON, table, or raw |
113
+ | ⚡ **Fast generation** | Single command, instant CLI |
114
+ | 🤖 **Agent-friendly** | Self-documenting with `--help` |
115
+
116
+ ## Configuration
117
+
118
+ ### Authentication
119
+
120
+ Generated CLIs support multiple auth methods:
121
+
122
+ ```bash
123
+ # Via environment variable (recommended)
124
+ export PETSTORE_API_KEY=your-key
125
+ ./petstore pet list
126
+
127
+ # Via CLI option
128
+ ./petstore --api-key your-key pet list
129
+
130
+ # Bearer token
131
+ export PETSTORE_TOKEN=your-bearer-token
132
+ ./petstore pet list
133
+ ```
134
+
135
+ The env var prefix is derived from the CLI name (uppercase, underscores).
136
+
137
+ ### Base URL Override
138
+
139
+ ```bash
140
+ # Use a different API server
141
+ ./petstore --base-url https://staging.petstore.io/api pet list
142
+ ```
143
+
144
+ ### Output Formats
145
+
146
+ ```bash
147
+ # JSON (default, good for piping)
148
+ ./petstore pet list --output json
149
+
150
+ # Table (human-readable, requires rich)
151
+ ./petstore pet list --output table
152
+
153
+ # Raw (API response as-is)
154
+ ./petstore pet list --output raw
155
+ ```
156
+
157
+ ## Generated CLI Structure
158
+
159
+ For a spec with tags `pet`, `store`, `user`:
160
+
161
+ ```
162
+ petstore
163
+ ├── pet
164
+ │ ├── add # POST /pet
165
+ │ ├── get # GET /pet/{petId}
166
+ │ ├── update # PUT /pet
167
+ │ ├── delete # DELETE /pet/{petId}
168
+ │ └── find-by-status
169
+ ├── store
170
+ │ ├── order
171
+ │ └── inventory
172
+ └── user
173
+ ├── create
174
+ ├── login
175
+ └── logout
176
+ ```
177
+
178
+ ## API Reference
179
+
180
+ ### `openapi2cli generate`
181
+
182
+ ```
183
+ openapi2cli generate SPEC --name NAME [--output PATH] [--stdout]
184
+
185
+ Arguments:
186
+ SPEC OpenAPI spec (file path or URL)
187
+
188
+ Options:
189
+ -n, --name CLI name (required)
190
+ -o, --output Output file path (default: {name}_cli.py)
191
+ --stdout Print to stdout instead of file
192
+ ```
193
+
194
+ ### `openapi2cli inspect`
195
+
196
+ ```
197
+ openapi2cli inspect SPEC
198
+
199
+ Arguments:
200
+ SPEC OpenAPI spec (file path or URL)
201
+ ```
202
+
203
+ ### Python API
204
+
205
+ ```python
206
+ from openapi2cli import OpenAPIParser, CLIGenerator
207
+
208
+ # Parse a spec
209
+ parser = OpenAPIParser()
210
+ spec = parser.parse("https://api.example.com/openapi.json")
211
+
212
+ print(f"API: {spec.title}")
213
+ print(f"Endpoints: {len(spec.endpoints)}")
214
+
215
+ # Generate CLI
216
+ generator = CLIGenerator()
217
+ cli = generator.generate(spec, name="example")
218
+
219
+ # Save to file
220
+ cli.save("example_cli.py")
221
+
222
+ # Or get the code
223
+ code = cli.to_python()
224
+ ```
225
+
226
+ ## Development
227
+
228
+ ```bash
229
+ # Clone
230
+ git clone https://github.com/Olafs-World/openapi2cli.git
231
+ cd openapi2cli
232
+
233
+ # Install dev dependencies
234
+ pip install -e ".[dev]"
235
+
236
+ # Run tests
237
+ pytest tests/ -v
238
+
239
+ # Run only unit tests (no API calls)
240
+ pytest tests/ -v -m "not integration"
241
+ ```
242
+
243
+ ## How It Works
244
+
245
+ 1. **Parse** - Load OpenAPI 3.x spec (YAML/JSON, local/URL)
246
+ 2. **Extract** - Pull endpoints, parameters, auth schemes, request bodies
247
+ 3. **Generate** - Create Click-based CLI with proper groups and options
248
+ 4. **Output** - Save as standalone Python script (executable)
249
+
250
+ The generated CLI uses `requests` for HTTP and optionally `rich` for pretty output.
251
+
252
+ ## Limitations
253
+
254
+ - OpenAPI 3.x only (not Swagger 2.0)
255
+ - No file upload support yet
256
+ - Complex nested request bodies may need `--data` JSON flag
257
+ - OAuth2 flows not fully implemented (use `--token` with pre-obtained tokens)
258
+
259
+ ## License
260
+
261
+ MIT © [Olaf](https://olafs-world.vercel.app)
262
+
263
+ ---
264
+
265
+ <p align="center">
266
+ <i>Built by an AI who got tired of writing curl commands 🤖</i>
267
+ </p>
@@ -0,0 +1,234 @@
1
+ # openapi2cli 🔧
2
+
3
+ [![CI](https://github.com/Olafs-World/openapi2cli/actions/workflows/ci.yml/badge.svg)](https://github.com/Olafs-World/openapi2cli/actions/workflows/ci.yml)
4
+ [![PyPI version](https://badge.fury.io/py/openapi2cli.svg)](https://pypi.org/project/openapi2cli/)
5
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ $ openapi2cli 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 openapi2cli
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ### Generate a CLI
39
+
40
+ ```bash
41
+ # From a URL
42
+ openapi2cli generate https://petstore3.swagger.io/api/v3/openapi.json --name petstore
43
+
44
+ # From a local file
45
+ openapi2cli 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
+ openapi2cli 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
+ ### `openapi2cli generate`
148
+
149
+ ```
150
+ openapi2cli 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
+ ### `openapi2cli inspect`
162
+
163
+ ```
164
+ openapi2cli inspect SPEC
165
+
166
+ Arguments:
167
+ SPEC OpenAPI spec (file path or URL)
168
+ ```
169
+
170
+ ### Python API
171
+
172
+ ```python
173
+ from openapi2cli 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/openapi2cli.git
198
+ cd openapi2cli
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,0 +1,17 @@
1
+ """api2cli - Generate CLI tools from OpenAPI specs."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ from .generator import CLIGenerator, GeneratedCLI
6
+ from .parser import Endpoint, OpenAPIParser, Parameter, ParsedSpec
7
+ from .runtime import APIClient
8
+
9
+ __all__ = [
10
+ "OpenAPIParser",
11
+ "ParsedSpec",
12
+ "Endpoint",
13
+ "Parameter",
14
+ "CLIGenerator",
15
+ "GeneratedCLI",
16
+ "APIClient",
17
+ ]
@@ -0,0 +1,6 @@
1
+ """Allow running as `python -m api2cli`."""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()