cli-wizard 2.0.0__tar.gz → 3.0.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.
- {cli_wizard-2.0.0/src/cli_wizard.egg-info → cli_wizard-3.0.0}/PKG-INFO +86 -58
- cli_wizard-3.0.0/README.md +204 -0
- cli_wizard-3.0.0/VERSION +1 -0
- cli_wizard-3.0.0/pyproject.toml +117 -0
- cli_wizard-3.0.0/src/cli_wizard/cli.py +67 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/commands/bootstrap.py +121 -160
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/commands/common.py +15 -7
- cli_wizard-3.0.0/src/cli_wizard/commands/config.py +107 -0
- cli_wizard-3.0.0/src/cli_wizard/commands/generate.py +243 -0
- cli_wizard-3.0.0/src/cli_wizard/config/configuration.py +77 -0
- cli_wizard-3.0.0/src/cli_wizard/config/project.py +100 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/config/schema.py +172 -14
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/constants.py +1 -1
- cli_wizard-3.0.0/src/cli_wizard/errors.py +137 -0
- cli_wizard-3.0.0/src/cli_wizard/generator/generator.py +688 -0
- cli_wizard-3.0.0/src/cli_wizard/generator/models.py +220 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/generator/parser.py +75 -28
- cli_wizard-2.0.0/src/cli_wizard/templates/.github/workflows/changelog_enforcer.yaml → cli_wizard-3.0.0/src/cli_wizard/templates/.github/workflows/changelog-enforcer.yaml +1 -1
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/workflows/codeql.yaml +4 -4
- cli_wizard-2.0.0/src/cli_wizard/templates/.github/workflows/docs.yaml → cli_wizard-3.0.0/src/cli_wizard/templates/.github/workflows/docs.yaml.j2 +7 -7
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/workflows/labeler.yaml +1 -1
- cli_wizard-2.0.0/src/cli_wizard/templates/.github/workflows/pr-validation.yaml → cli_wizard-3.0.0/src/cli_wizard/templates/.github/workflows/pr-validation.yaml.j2 +10 -8
- cli_wizard-2.0.0/src/cli_wizard/templates/.github/workflows/release.yaml → cli_wizard-3.0.0/src/cli_wizard/templates/.github/workflows/release.yaml.j2 +5 -5
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/workflows/sync-labels.yaml +2 -2
- cli_wizard-3.0.0/src/cli_wizard/templates/.github/workflows/test.yaml.j2 +46 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/CHANGELOG.md.j2 +0 -4
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/DEVELOPMENT.md.j2 +34 -1
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/Makefile.j2 +6 -4
- cli_wizard-3.0.0/src/cli_wizard/templates/README.md.j2 +168 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/pre-commit-config.yaml.j2 +30 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/pyproject.toml.j2 +100 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/cli.py.j2 +94 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/client.py.j2 +326 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/commands/__init__.py.j2 +4 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/commands/config.py.j2 +146 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/commands/group.py.j2 +185 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/src/{{ PackageName }}/constants.py.j2 +40 -18
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/errors.py.j2 +149 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/log.py.j2 +189 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/options.py.j2 +123 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/output.py.j2 +158 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/profile.py.j2 +283 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/redaction.py.j2 +88 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/runner.py.j2 +77 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/src/{{ PackageName }}/state.py.j2 +41 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/tests/{{ PackageName }}/cli_test.py.j2 +2049 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/tests/{{ PackageName }}/commands_test.py.j2 +73 -0
- cli_wizard-3.0.0/src/cli_wizard/templates/tox.ini.j2 +31 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0/src/cli_wizard.egg-info}/PKG-INFO +86 -58
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard.egg-info/SOURCES.txt +16 -7
- cli_wizard-3.0.0/src/cli_wizard.egg-info/requires.txt +6 -0
- cli_wizard-2.0.0/README.md +0 -158
- cli_wizard-2.0.0/VERSION +0 -1
- cli_wizard-2.0.0/pyproject.toml +0 -90
- cli_wizard-2.0.0/src/cli_wizard/cli.py +0 -39
- cli_wizard-2.0.0/src/cli_wizard/commands/config.py +0 -82
- cli_wizard-2.0.0/src/cli_wizard/commands/generate.py +0 -224
- cli_wizard-2.0.0/src/cli_wizard/config/configuration.py +0 -45
- cli_wizard-2.0.0/src/cli_wizard/generator/generator.py +0 -447
- cli_wizard-2.0.0/src/cli_wizard/generator/models.py +0 -123
- cli_wizard-2.0.0/src/cli_wizard/templates/.github/workflows/test.yaml +0 -46
- cli_wizard-2.0.0/src/cli_wizard/templates/README.md.j2 +0 -23
- cli_wizard-2.0.0/src/cli_wizard/templates/pre-commit-config.yaml.j2 +0 -27
- cli_wizard-2.0.0/src/cli_wizard/templates/pyproject.toml.j2 +0 -83
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/cli.py.j2 +0 -106
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/client.py.j2 +0 -150
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/commands/__init__.py.j2 +0 -14
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/commands/config.py.j2 +0 -384
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/commands/group.py.j2 +0 -272
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/logging.py.j2 +0 -183
- cli_wizard-2.0.0/src/cli_wizard/templates/src/{{ PackageName }}/profile.py.j2 +0 -93
- cli_wizard-2.0.0/src/cli_wizard/templates/tests/{{ PackageName }}/cli_test.py.j2 +0 -1165
- cli_wizard-2.0.0/src/cli_wizard/templates/tox.ini.j2 +0 -27
- cli_wizard-2.0.0/src/cli_wizard.egg-info/requires.txt +0 -26
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/LICENSE +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/MANIFEST.in +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/setup.cfg +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/__init__.py +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/commands/__init__.py +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/config/__init__.py +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/generator/__init__.py +3 -3
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/CODEOWNERS.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/ISSUE_TEMPLATE/bug-report.yml.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/ISSUE_TEMPLATE/config.yml.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/ISSUE_TEMPLATE/feature-request.yml.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/dependabot.yaml +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/labeler.yaml +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.github/labels.yaml.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/.gitignore.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/LICENSE.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/MANIFEST.in.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/VERSION.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/cli-wizard.yaml.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard/templates/src/{{ PackageName }}/__init__.py.j2 +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard.egg-info/dependency_links.txt +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard.egg-info/entry_points.txt +0 -0
- {cli_wizard-2.0.0 → cli_wizard-3.0.0}/src/cli_wizard.egg-info/top_level.txt +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cli-wizard
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: Generate modern CLIs from OpenAPI specifications
|
|
5
5
|
Author-email: Giacomo Marciani <giacomo.marciani@gmail.com>
|
|
6
6
|
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.
|
|
7
|
+
Project-URL: Homepage, https://gmarciani.github.io/cli-wizard/
|
|
8
8
|
Project-URL: Repository, https://github.com/gmarciani/cli-wizard
|
|
9
9
|
Project-URL: Issues, https://github.com/gmarciani/cli-wizard/issues
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -17,30 +17,12 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
17
17
|
Requires-Python: >=3.12
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: click~=8.
|
|
21
|
-
Requires-Dist: Jinja2~=3.1
|
|
22
|
-
Requires-Dist: pydantic~=2.
|
|
23
|
-
Requires-Dist: PyYAML~=6.0
|
|
24
|
-
Requires-Dist: requests~=2.
|
|
25
|
-
|
|
26
|
-
Requires-Dist: autoflake~=2.3; extra == "dev"
|
|
27
|
-
Requires-Dist: black~=26.1; extra == "dev"
|
|
28
|
-
Requires-Dist: build~=1.4; extra == "dev"
|
|
29
|
-
Requires-Dist: flake8~=7.3; extra == "dev"
|
|
30
|
-
Requires-Dist: mypy~=1.19; extra == "dev"
|
|
31
|
-
Requires-Dist: pre-commit~=4.5; extra == "dev"
|
|
32
|
-
Requires-Dist: pytest~=9.0; extra == "dev"
|
|
33
|
-
Requires-Dist: pytest-cov~=7.0; extra == "dev"
|
|
34
|
-
Requires-Dist: tox~=4.34; extra == "dev"
|
|
35
|
-
Requires-Dist: twine~=6.2; extra == "dev"
|
|
36
|
-
Requires-Dist: types-PyYAML~=6.0; extra == "dev"
|
|
37
|
-
Requires-Dist: types-requests~=2.32; extra == "dev"
|
|
38
|
-
Provides-Extra: docs
|
|
39
|
-
Requires-Dist: sphinx~=9.1; extra == "docs"
|
|
40
|
-
Requires-Dist: sphinx-click~=6.2; extra == "docs"
|
|
41
|
-
Requires-Dist: sphinx-rtd-theme~=3.1; extra == "docs"
|
|
42
|
-
Requires-Dist: sphinx-new-tab-link~=0.8; extra == "docs"
|
|
43
|
-
Requires-Dist: autodoc_pydantic~=2.2; extra == "docs"
|
|
20
|
+
Requires-Dist: click~=8.4
|
|
21
|
+
Requires-Dist: Jinja2~=3.1
|
|
22
|
+
Requires-Dist: pydantic~=2.13
|
|
23
|
+
Requires-Dist: PyYAML~=6.0
|
|
24
|
+
Requires-Dist: requests~=2.34
|
|
25
|
+
Requires-Dist: ruff~=0.16.2
|
|
44
26
|
Dynamic: license-file
|
|
45
27
|
|
|
46
28
|
# CLI WIZARD
|
|
@@ -49,12 +31,12 @@ Dynamic: license-file
|
|
|
49
31
|
<img src="https://raw.githubusercontent.com/gmarciani/cli-wizard/main/resources/brand/banner.png" alt="cli-wizard-banner" width="500">
|
|
50
32
|
|
|
51
33
|
[](https://pypi.org/project/cli-wizard)
|
|
52
|
-
[](https://pypi.org/project/cli-wizard)
|
|
53
35
|
[](https://github.com/gmarciani/cli-wizard/blob/main/LICENSE)
|
|
54
36
|
[](https://github.com/gmarciani/cli-wizard/actions)
|
|
55
37
|
[](https://github.com/gmarciani/cli-wizard/actions)
|
|
56
38
|
[](https://codecov.io/gh/gmarciani/cli-wizard)
|
|
57
|
-
[](https://github.com/astral-sh/ruff)
|
|
58
40
|
[](https://pypi.org/project/cli-wizard)
|
|
59
41
|
|
|
60
42
|
</div>
|
|
@@ -78,7 +60,7 @@ Generate modern CLIs from OpenAPI specifications.
|
|
|
78
60
|
- Automatic command grouping based on OpenAPI tags
|
|
79
61
|
- Automatic help generation for all commands
|
|
80
62
|
- Clean, colored terminal output
|
|
81
|
-
- `--debug` flag for verbose logging
|
|
63
|
+
- `--debug` flag for verbose logging, with credentials redacted from the output
|
|
82
64
|
- Built-in API client with configurable base URL and timeout
|
|
83
65
|
- SSL/TLS support with custom CA certificate bundles
|
|
84
66
|
- `--ca-file` option to specify custom CA certificates at runtime
|
|
@@ -94,7 +76,13 @@ Generate modern CLIs from OpenAPI specifications.
|
|
|
94
76
|
|
|
95
77
|
### Developer Experience
|
|
96
78
|
- Generated projects are pip-installable out of the box
|
|
97
|
-
- Auto-generated `pyproject.toml
|
|
79
|
+
- Auto-generated `pyproject.toml` and `VERSION`
|
|
80
|
+
- Auto-generated `README.md` with commands and configuration reference
|
|
81
|
+
- Auto-generated `DEVELOPMENT.md`, `CHANGELOG.md` and `LICENSE`
|
|
82
|
+
- Test suite for the generated CLI, ready to run
|
|
83
|
+
- `tox.ini` with test, lint, type, format and coverage environments, plus a `Makefile` wrapping them
|
|
84
|
+
- Pre-commit configuration running ruff and mypy
|
|
85
|
+
- Optional GitHub setup (`IncludeGithubWorkflows`): test, release, docs, PR validation, CodeQL, changelog and labeler workflows, plus Dependabot, issue and PR templates, and `CODEOWNERS`
|
|
98
86
|
- Resources (CA certs, splash files) bundled in the package
|
|
99
87
|
- Profile management for storing credentials and settings
|
|
100
88
|
|
|
@@ -127,51 +115,74 @@ paths:
|
|
|
127
115
|
description: OK
|
|
128
116
|
```
|
|
129
117
|
|
|
130
|
-
### Step 2:
|
|
118
|
+
### Step 2: Generate the CLI
|
|
131
119
|
|
|
132
|
-
|
|
120
|
+
Run the `generate` command, passing the OpenAPI spec and a project name:
|
|
121
|
+
|
|
122
|
+
```shell
|
|
123
|
+
cli-wizard generate --api openapi.yaml --project-name "My CLI"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This creates a complete Python CLI project in the `my-cli` directory: the
|
|
127
|
+
command name derives from the project name, and every other setting takes its
|
|
128
|
+
default. Pass `--output` to write it elsewhere.
|
|
129
|
+
|
|
130
|
+
### Step 3: Install the Generated CLI
|
|
131
|
+
|
|
132
|
+
Navigate to the generated project and install it:
|
|
133
|
+
|
|
134
|
+
```shell
|
|
135
|
+
pip install -e my-cli
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Step 4: Use Your CLI
|
|
139
|
+
|
|
140
|
+
Your CLI is now ready to use:
|
|
141
|
+
|
|
142
|
+
```shell
|
|
143
|
+
my-cli --help
|
|
144
|
+
my-cli users list-users
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Step 5: Customize with a Configuration File
|
|
148
|
+
|
|
149
|
+
To go beyond the defaults, create a `cli-wizard.yaml` file with the settings you
|
|
150
|
+
want to change. Every parameter is optional:
|
|
133
151
|
|
|
134
152
|
```yaml
|
|
135
|
-
|
|
136
|
-
PackageName: "my-cli"
|
|
153
|
+
ProjectName: "My CLI"
|
|
137
154
|
DefaultBaseUrl: "https://api.example.com"
|
|
138
155
|
|
|
139
|
-
#
|
|
156
|
+
# Customize the splash screen
|
|
140
157
|
SplashFile: "splash.txt"
|
|
141
158
|
SplashColor: "#00FFFF"
|
|
142
159
|
|
|
143
|
-
#
|
|
160
|
+
# Filter which tags to include
|
|
144
161
|
IncludeTags:
|
|
145
162
|
- Users
|
|
146
163
|
- Products
|
|
147
164
|
```
|
|
148
165
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
Run the `generate` command:
|
|
166
|
+
Then generate from it. The project lands in the current directory, in a
|
|
167
|
+
directory named after `CommandName`:
|
|
152
168
|
|
|
153
169
|
```shell
|
|
154
|
-
cli-wizard generate --
|
|
170
|
+
cli-wizard generate --configuration cli-wizard.yaml --api openapi.yaml
|
|
155
171
|
```
|
|
156
172
|
|
|
157
|
-
|
|
173
|
+
### Starting Without a Specification
|
|
158
174
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
175
|
+
To start from scratch instead, run `bootstrap`. It prompts for the main
|
|
176
|
+
settings, writes a commented `cli-wizard.yaml`, and generates a basic CLI from
|
|
177
|
+
it, without API commands. The CLI lands in the current directory, in a
|
|
178
|
+
directory named after `CommandName`; pass `--output` to write it elsewhere:
|
|
162
179
|
|
|
163
180
|
```shell
|
|
164
|
-
|
|
181
|
+
cli-wizard bootstrap --configuration cli-wizard.yaml
|
|
165
182
|
```
|
|
166
183
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
Your CLI is now ready to use:
|
|
170
|
-
|
|
171
|
-
```shell
|
|
172
|
-
my-cli --help
|
|
173
|
-
my-cli users list-users
|
|
174
|
-
```
|
|
184
|
+
Then edit the configuration, point `Api` at your specification, and rebuild
|
|
185
|
+
with `cli-wizard generate --configuration cli-wizard.yaml`.
|
|
175
186
|
|
|
176
187
|
## Configuration
|
|
177
188
|
|
|
@@ -182,17 +193,34 @@ See the [examples](examples/) directory for complete configuration examples.
|
|
|
182
193
|
|
|
183
194
|
### cli-wizard generate
|
|
184
195
|
|
|
185
|
-
Generate a CLI from an OpenAPI specification
|
|
196
|
+
Generate a CLI from an OpenAPI specification, with an optional configuration file.
|
|
186
197
|
|
|
187
198
|
```shell
|
|
188
199
|
cli-wizard generate [OPTIONS]
|
|
189
200
|
```
|
|
190
201
|
|
|
191
202
|
Options:
|
|
192
|
-
- `--
|
|
193
|
-
- `--
|
|
194
|
-
- `--
|
|
195
|
-
- `--
|
|
203
|
+
- `--api, -a` - Path to the OpenAPI spec file, YAML or JSON. Without it and without `Api` in the configuration, the CLI is generated without API commands
|
|
204
|
+
- `--configuration, -c` - Path to the `cli-wizard.yaml` configuration file. Without it, every parameter takes its default
|
|
205
|
+
- `--project-name, -p` - Human-readable project name; the generated command name derives from it, unless the configuration sets it
|
|
206
|
+
- `--output, -o` - Output directory (default: a directory named after `CommandName` in the current directory)
|
|
207
|
+
- `--force, -f` - Skip the confirmation prompt when the output directory is not empty
|
|
208
|
+
|
|
209
|
+
### cli-wizard bootstrap
|
|
210
|
+
|
|
211
|
+
Bootstrap a new CLI project interactively, without an OpenAPI specification.
|
|
212
|
+
It does two things: it writes a configuration file to evolve the project from,
|
|
213
|
+
then generates a basic CLI from that file, without API commands, in the output
|
|
214
|
+
directory.
|
|
215
|
+
|
|
216
|
+
```shell
|
|
217
|
+
cli-wizard bootstrap [OPTIONS]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Options:
|
|
221
|
+
- `--configuration, -c` - Path for the `cli-wizard.yaml` configuration file (default: `./cli-wizard.yaml`). An existing file is overwritten, after confirmation, without keeping any of its values
|
|
222
|
+
- `--output, -o` - Output directory of the basic CLI (default: a directory named after `CommandName` in the current directory)
|
|
223
|
+
- `--force, -f` - Skip the confirmation prompts to overwrite an existing configuration file or to write into a non-empty directory
|
|
196
224
|
|
|
197
225
|
## Issues
|
|
198
226
|
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# CLI WIZARD
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/gmarciani/cli-wizard/main/resources/brand/banner.png" alt="cli-wizard-banner" width="500">
|
|
5
|
+
|
|
6
|
+
[](https://pypi.org/project/cli-wizard)
|
|
7
|
+
[](https://pypi.org/project/cli-wizard)
|
|
8
|
+
[](https://github.com/gmarciani/cli-wizard/blob/main/LICENSE)
|
|
9
|
+
[](https://github.com/gmarciani/cli-wizard/actions)
|
|
10
|
+
[](https://github.com/gmarciani/cli-wizard/actions)
|
|
11
|
+
[](https://codecov.io/gh/gmarciani/cli-wizard)
|
|
12
|
+
[](https://github.com/astral-sh/ruff)
|
|
13
|
+
[](https://pypi.org/project/cli-wizard)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
Generate modern CLIs from OpenAPI specifications.
|
|
18
|
+
|
|
19
|
+
## Table of Contents
|
|
20
|
+
|
|
21
|
+
- [Features](#features)
|
|
22
|
+
- [Installation](#installation)
|
|
23
|
+
- [Usage](#usage)
|
|
24
|
+
- [Configuration](#configuration)
|
|
25
|
+
- [Commands](#commands)
|
|
26
|
+
- [Issues](#issues)
|
|
27
|
+
- [License](#license)
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
### Code Generation
|
|
32
|
+
- Generate complete Python CLI projects from OpenAPI v3 specifications
|
|
33
|
+
- Automatic command grouping based on OpenAPI tags
|
|
34
|
+
- Automatic help generation for all commands
|
|
35
|
+
- Clean, colored terminal output
|
|
36
|
+
- `--debug` flag for verbose logging, with credentials redacted from the output
|
|
37
|
+
- Built-in API client with configurable base URL and timeout
|
|
38
|
+
- SSL/TLS support with custom CA certificate bundles
|
|
39
|
+
- `--ca-file` option to specify custom CA certificates at runtime
|
|
40
|
+
- `--no-verify-ssl` flag to disable certificate verification
|
|
41
|
+
|
|
42
|
+
### Customization
|
|
43
|
+
- YAML-based configuration for full customization
|
|
44
|
+
- Configurable output directory and package name
|
|
45
|
+
- Tag inclusion/exclusion filters
|
|
46
|
+
- Custom command naming via `TagMapping` and `CommandMapping`
|
|
47
|
+
- Customizable splash screen with color support
|
|
48
|
+
- Configurable logging with colors, file output, and rotation
|
|
49
|
+
|
|
50
|
+
### Developer Experience
|
|
51
|
+
- Generated projects are pip-installable out of the box
|
|
52
|
+
- Auto-generated `pyproject.toml` and `VERSION`
|
|
53
|
+
- Auto-generated `README.md` with commands and configuration reference
|
|
54
|
+
- Auto-generated `DEVELOPMENT.md`, `CHANGELOG.md` and `LICENSE`
|
|
55
|
+
- Test suite for the generated CLI, ready to run
|
|
56
|
+
- `tox.ini` with test, lint, type, format and coverage environments, plus a `Makefile` wrapping them
|
|
57
|
+
- Pre-commit configuration running ruff and mypy
|
|
58
|
+
- Optional GitHub setup (`IncludeGithubWorkflows`): test, release, docs, PR validation, CodeQL, changelog and labeler workflows, plus Dependabot, issue and PR templates, and `CODEOWNERS`
|
|
59
|
+
- Resources (CA certs, splash files) bundled in the package
|
|
60
|
+
- Profile management for storing credentials and settings
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```shell
|
|
65
|
+
pip install cli-wizard
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
### Step 1: Prepare Your OpenAPI Specification
|
|
71
|
+
|
|
72
|
+
Ensure you have an OpenAPI v3 specification file (JSON or YAML format). For example, `openapi.yaml`:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
openapi: 3.0.0
|
|
76
|
+
info:
|
|
77
|
+
title: My API
|
|
78
|
+
version: 1.0.0
|
|
79
|
+
paths:
|
|
80
|
+
/users:
|
|
81
|
+
get:
|
|
82
|
+
operationId: listUsers
|
|
83
|
+
summary: List all users
|
|
84
|
+
tags:
|
|
85
|
+
- Users
|
|
86
|
+
responses:
|
|
87
|
+
'200':
|
|
88
|
+
description: OK
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Step 2: Generate the CLI
|
|
92
|
+
|
|
93
|
+
Run the `generate` command, passing the OpenAPI spec and a project name:
|
|
94
|
+
|
|
95
|
+
```shell
|
|
96
|
+
cli-wizard generate --api openapi.yaml --project-name "My CLI"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This creates a complete Python CLI project in the `my-cli` directory: the
|
|
100
|
+
command name derives from the project name, and every other setting takes its
|
|
101
|
+
default. Pass `--output` to write it elsewhere.
|
|
102
|
+
|
|
103
|
+
### Step 3: Install the Generated CLI
|
|
104
|
+
|
|
105
|
+
Navigate to the generated project and install it:
|
|
106
|
+
|
|
107
|
+
```shell
|
|
108
|
+
pip install -e my-cli
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step 4: Use Your CLI
|
|
112
|
+
|
|
113
|
+
Your CLI is now ready to use:
|
|
114
|
+
|
|
115
|
+
```shell
|
|
116
|
+
my-cli --help
|
|
117
|
+
my-cli users list-users
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Step 5: Customize with a Configuration File
|
|
121
|
+
|
|
122
|
+
To go beyond the defaults, create a `cli-wizard.yaml` file with the settings you
|
|
123
|
+
want to change. Every parameter is optional:
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
ProjectName: "My CLI"
|
|
127
|
+
DefaultBaseUrl: "https://api.example.com"
|
|
128
|
+
|
|
129
|
+
# Customize the splash screen
|
|
130
|
+
SplashFile: "splash.txt"
|
|
131
|
+
SplashColor: "#00FFFF"
|
|
132
|
+
|
|
133
|
+
# Filter which tags to include
|
|
134
|
+
IncludeTags:
|
|
135
|
+
- Users
|
|
136
|
+
- Products
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Then generate from it. The project lands in the current directory, in a
|
|
140
|
+
directory named after `CommandName`:
|
|
141
|
+
|
|
142
|
+
```shell
|
|
143
|
+
cli-wizard generate --configuration cli-wizard.yaml --api openapi.yaml
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Starting Without a Specification
|
|
147
|
+
|
|
148
|
+
To start from scratch instead, run `bootstrap`. It prompts for the main
|
|
149
|
+
settings, writes a commented `cli-wizard.yaml`, and generates a basic CLI from
|
|
150
|
+
it, without API commands. The CLI lands in the current directory, in a
|
|
151
|
+
directory named after `CommandName`; pass `--output` to write it elsewhere:
|
|
152
|
+
|
|
153
|
+
```shell
|
|
154
|
+
cli-wizard bootstrap --configuration cli-wizard.yaml
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Then edit the configuration, point `Api` at your specification, and rebuild
|
|
158
|
+
with `cli-wizard generate --configuration cli-wizard.yaml`.
|
|
159
|
+
|
|
160
|
+
## Configuration
|
|
161
|
+
|
|
162
|
+
See [configuration reference](https://gmarciani.github.io/cli-wizard/configuration.html) for full documentation.
|
|
163
|
+
See the [examples](examples/) directory for complete configuration examples.
|
|
164
|
+
|
|
165
|
+
## Commands
|
|
166
|
+
|
|
167
|
+
### cli-wizard generate
|
|
168
|
+
|
|
169
|
+
Generate a CLI from an OpenAPI specification, with an optional configuration file.
|
|
170
|
+
|
|
171
|
+
```shell
|
|
172
|
+
cli-wizard generate [OPTIONS]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Options:
|
|
176
|
+
- `--api, -a` - Path to the OpenAPI spec file, YAML or JSON. Without it and without `Api` in the configuration, the CLI is generated without API commands
|
|
177
|
+
- `--configuration, -c` - Path to the `cli-wizard.yaml` configuration file. Without it, every parameter takes its default
|
|
178
|
+
- `--project-name, -p` - Human-readable project name; the generated command name derives from it, unless the configuration sets it
|
|
179
|
+
- `--output, -o` - Output directory (default: a directory named after `CommandName` in the current directory)
|
|
180
|
+
- `--force, -f` - Skip the confirmation prompt when the output directory is not empty
|
|
181
|
+
|
|
182
|
+
### cli-wizard bootstrap
|
|
183
|
+
|
|
184
|
+
Bootstrap a new CLI project interactively, without an OpenAPI specification.
|
|
185
|
+
It does two things: it writes a configuration file to evolve the project from,
|
|
186
|
+
then generates a basic CLI from that file, without API commands, in the output
|
|
187
|
+
directory.
|
|
188
|
+
|
|
189
|
+
```shell
|
|
190
|
+
cli-wizard bootstrap [OPTIONS]
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Options:
|
|
194
|
+
- `--configuration, -c` - Path for the `cli-wizard.yaml` configuration file (default: `./cli-wizard.yaml`). An existing file is overwritten, after confirmation, without keeping any of its values
|
|
195
|
+
- `--output, -o` - Output directory of the basic CLI (default: a directory named after `CommandName` in the current directory)
|
|
196
|
+
- `--force, -f` - Skip the confirmation prompts to overwrite an existing configuration file or to write into a non-empty directory
|
|
197
|
+
|
|
198
|
+
## Issues
|
|
199
|
+
|
|
200
|
+
Please report any issues or feature requests on the [GitHub Issues](https://github.com/gmarciani/cli-wizard/issues) page.
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
This project is licensed under the MIT License. See the [LICENSE](https://github.com/gmarciani/cli-wizard/blob/main/LICENSE) file for details.
|
cli_wizard-3.0.0/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.0
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cli-wizard"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Generate modern CLIs from OpenAPI specifications"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Giacomo Marciani", email = "giacomo.marciani@gmail.com"}
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Programming Language :: Python :: 3.14",
|
|
22
|
+
]
|
|
23
|
+
requires-python = ">=3.12"
|
|
24
|
+
dependencies = [
|
|
25
|
+
"click~=8.4",
|
|
26
|
+
"Jinja2~=3.1",
|
|
27
|
+
"pydantic~=2.13",
|
|
28
|
+
"PyYAML~=6.0",
|
|
29
|
+
"requests~=2.34",
|
|
30
|
+
"ruff~=0.16.2",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
cli-wizard = "cli_wizard.cli:main"
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://gmarciani.github.io/cli-wizard/"
|
|
38
|
+
Repository = "https://github.com/gmarciani/cli-wizard"
|
|
39
|
+
Issues = "https://github.com/gmarciani/cli-wizard/issues"
|
|
40
|
+
|
|
41
|
+
# Local-only tooling (PEP 735). Groups are never published, so none of this
|
|
42
|
+
# reaches anyone installing cli-wizard from an index. There are no extras: the
|
|
43
|
+
# built distributions carry no tests, so a published test extra would only
|
|
44
|
+
# install pytest for a consumer with nothing to run it against.
|
|
45
|
+
[dependency-groups]
|
|
46
|
+
dev = [
|
|
47
|
+
{include-group = "test"},
|
|
48
|
+
{include-group = "docs"},
|
|
49
|
+
"build~=1.5",
|
|
50
|
+
"pre-commit~=4.6",
|
|
51
|
+
"tox~=4.58",
|
|
52
|
+
"twine>=6.2,<8.0",
|
|
53
|
+
]
|
|
54
|
+
# mypy and the stubs too: the suite type checks the code it generates.
|
|
55
|
+
test = [
|
|
56
|
+
"mypy~=2.3",
|
|
57
|
+
"pytest~=9.1",
|
|
58
|
+
"pytest-cov~=7.1",
|
|
59
|
+
"types-PyYAML~=6.0",
|
|
60
|
+
"types-requests~=2.33",
|
|
61
|
+
]
|
|
62
|
+
docs = [
|
|
63
|
+
"sphinx~=9.1",
|
|
64
|
+
"sphinx-click~=6.2",
|
|
65
|
+
"sphinx-rtd-theme~=3.1",
|
|
66
|
+
"sphinx-new-tab-link~=0.8",
|
|
67
|
+
"autodoc_pydantic~=2.2",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[tool.setuptools.packages.find]
|
|
71
|
+
where = ["src"]
|
|
72
|
+
include = ["cli_wizard*"]
|
|
73
|
+
|
|
74
|
+
[tool.setuptools.package-data]
|
|
75
|
+
cli_wizard = [
|
|
76
|
+
"templates/**/*.j2",
|
|
77
|
+
"templates/**/*.yaml",
|
|
78
|
+
"templates/**/*.yml",
|
|
79
|
+
"templates/**/*.md",
|
|
80
|
+
"config/*.yaml",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.setuptools.dynamic]
|
|
84
|
+
version = {file = "VERSION"}
|
|
85
|
+
|
|
86
|
+
# Ruff targets the oldest supported version: it emits syntax valid for the
|
|
87
|
+
# target, and newer syntax would be a SyntaxError on 3.12.
|
|
88
|
+
[tool.ruff]
|
|
89
|
+
line-length = 88
|
|
90
|
+
target-version = "py312"
|
|
91
|
+
|
|
92
|
+
[tool.ruff.lint]
|
|
93
|
+
# E/W pycodestyle, F pyflakes, I isort, B bugbear, S bandit, UP pyupgrade
|
|
94
|
+
select = ["E", "F", "W", "I", "B", "S", "UP"]
|
|
95
|
+
|
|
96
|
+
[tool.ruff.lint.per-file-ignores]
|
|
97
|
+
# Tests assert by design.
|
|
98
|
+
"tests/**" = ["S101"]
|
|
99
|
+
|
|
100
|
+
# mypy checks against the default interpreter, the newest supported version.
|
|
101
|
+
[tool.mypy]
|
|
102
|
+
python_version = "3.14"
|
|
103
|
+
warn_return_any = true
|
|
104
|
+
warn_unused_configs = true
|
|
105
|
+
disallow_untyped_defs = true
|
|
106
|
+
|
|
107
|
+
[tool.coverage.run]
|
|
108
|
+
omit = ["*/__init__.py"]
|
|
109
|
+
|
|
110
|
+
[tool.coverage.report]
|
|
111
|
+
fail_under = 90
|
|
112
|
+
|
|
113
|
+
[tool.pytest.ini_options]
|
|
114
|
+
# Import cli_wizard from the checkout being tested. The editable install names
|
|
115
|
+
# one checkout in its .pth file, so a run started from a git worktree would
|
|
116
|
+
# otherwise import that other checkout.
|
|
117
|
+
pythonpath = ["src"]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Copyright (c) 2026, Giacomo Marciani
|
|
2
|
+
# Licensed under the MIT License
|
|
3
|
+
|
|
4
|
+
"""Main CLI module for CLI Wizard."""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import traceback
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
|
|
12
|
+
from cli_wizard.commands.bootstrap import bootstrap
|
|
13
|
+
from cli_wizard.commands.common import configure_logging, debug_option
|
|
14
|
+
from cli_wizard.commands.config import config
|
|
15
|
+
from cli_wizard.commands.generate import generate
|
|
16
|
+
from cli_wizard.constants import __version__
|
|
17
|
+
from cli_wizard.errors import UnexpectedError, reported
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RootGroup(click.Group):
|
|
23
|
+
"""The root group, reporting what Click raises on its own as JSON too.
|
|
24
|
+
|
|
25
|
+
Click's main() shows a ClickException and exits with its code; wrapping the
|
|
26
|
+
parsing and the dispatch turns everything else into one of cli-wizard's
|
|
27
|
+
errors first, so every failure is the one JSON document on stdout.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def make_context(
|
|
31
|
+
self,
|
|
32
|
+
info_name: str | None,
|
|
33
|
+
args: list[str],
|
|
34
|
+
parent: click.Context | None = None,
|
|
35
|
+
**extra: Any,
|
|
36
|
+
) -> click.Context:
|
|
37
|
+
with reported():
|
|
38
|
+
return super().make_context(info_name, args, parent, **extra)
|
|
39
|
+
|
|
40
|
+
def invoke(self, ctx: click.Context) -> Any:
|
|
41
|
+
try:
|
|
42
|
+
with reported():
|
|
43
|
+
return super().invoke(ctx)
|
|
44
|
+
except UnexpectedError as e:
|
|
45
|
+
# The traceback the bug came with, kept for --debug
|
|
46
|
+
logger.debug("".join(traceback.format_exception(e.__cause__)))
|
|
47
|
+
raise
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@click.group(cls=RootGroup, help="CLI Wizard - Generate modern CLI from OpenAPI.")
|
|
51
|
+
@click.version_option(version=__version__, prog_name="cli-wizard")
|
|
52
|
+
@debug_option
|
|
53
|
+
@click.pass_context
|
|
54
|
+
def main(ctx: click.Context, debug: bool) -> None:
|
|
55
|
+
"""Main CLI entry point."""
|
|
56
|
+
ctx.ensure_object(dict)
|
|
57
|
+
ctx.obj["debug"] = debug
|
|
58
|
+
configure_logging(debug)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
main.add_command(bootstrap)
|
|
62
|
+
main.add_command(config)
|
|
63
|
+
main.add_command(generate)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
main()
|