devstuff 1.16.0__tar.gz → 1.18.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.
- {devstuff-1.16.0 → devstuff-1.18.0}/.github/workflows/test-installs.yml +2 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/CHANGELOG.md +13 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/CLAUDE.md +127 -2
- {devstuff-1.16.0 → devstuff-1.18.0}/PKG-INFO +206 -2
- {devstuff-1.16.0 → devstuff-1.18.0}/README.md +205 -1
- {devstuff-1.16.0 → devstuff-1.18.0}/docs/specs/README.md +2 -0
- devstuff-1.18.0/docs/specs/commitizen-config/development-plan.md +80 -0
- devstuff-1.18.0/docs/specs/commitizen-config/specifications.md +119 -0
- devstuff-1.18.0/docs/specs/commitizen-config/stack-decisions.md +183 -0
- devstuff-1.18.0/docs/specs/starship-config/development-plan.md +74 -0
- devstuff-1.18.0/docs/specs/starship-config/specifications.md +164 -0
- devstuff-1.18.0/docs/specs/starship-config/stack-decisions.md +187 -0
- devstuff-1.18.0/pyproject.toml +174 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/cli.py +3 -0
- devstuff-1.18.0/src/dev_setup/commands/configure_cmd.py +123 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/help_cmd.py +2 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/install_cmd.py +19 -1
- devstuff-1.18.0/src/dev_setup/configure/__init__.py +62 -0
- devstuff-1.18.0/src/dev_setup/configure/commitizen/__init__.py +1 -0
- devstuff-1.18.0/src/dev_setup/configure/commitizen/detect.py +213 -0
- devstuff-1.18.0/src/dev_setup/configure/commitizen/model.py +510 -0
- devstuff-1.18.0/src/dev_setup/configure/commitizen/render.py +552 -0
- devstuff-1.18.0/src/dev_setup/configure/commitizen/validate.py +321 -0
- devstuff-1.18.0/src/dev_setup/configure/commitizen/wizard.py +613 -0
- devstuff-1.18.0/src/dev_setup/configure/starship/__init__.py +1 -0
- devstuff-1.18.0/src/dev_setup/configure/starship/fonts.py +47 -0
- devstuff-1.18.0/src/dev_setup/configure/starship/model.py +850 -0
- devstuff-1.18.0/src/dev_setup/configure/starship/preview.py +157 -0
- devstuff-1.18.0/src/dev_setup/configure/starship/render.py +268 -0
- devstuff-1.18.0/src/dev_setup/configure/starship/wizard.py +396 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/tools.yaml +60 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/ui.py +4 -2
- devstuff-1.18.0/tests/integration/test_commitizen_config.py +135 -0
- devstuff-1.18.0/tests/test_configure_commitizen.py +759 -0
- devstuff-1.18.0/tests/test_configure_starship.py +682 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/uv.lock +1 -1
- devstuff-1.16.0/pyproject.toml +0 -75
- {devstuff-1.16.0 → devstuff-1.18.0}/.claude/skills/run-stuff/SKILL.md +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/.claude/skills/run-stuff/smoke.sh +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/.github/workflows/bump.yml +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/.github/workflows/ci.yml +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/.github/workflows/publish.yml +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/.gitignore +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/dev/Dockerfile +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/dev/Dockerfile.ci +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/dev/Makefile +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/dev/docker-compose.yml +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/dev-setup +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/docs/specs/agent/development-plan.md +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/docs/specs/agent/specifications.md +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/docs/specs/agent/stack-decisions.md +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/install.sh +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/__init__.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/__main__.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/__init__.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/approval.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/bridges.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/catalog.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/completion.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/config.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/loop.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/ollama.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/preflight.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/primitives.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/registry.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/sandbox.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/session.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/transcript.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent/wizard.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent_tools.schema.json +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/agent_tools.yaml +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/base.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/catalog.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/__init__.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/add_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/agent_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/catalog_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/delete_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/docs_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/functions_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/list_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/remove_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/run_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/skills_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/commands/update_cmd.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/function_runner.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/functions.schema.json +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/functions.yaml +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/functions_catalog.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/functions_registry.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/generic.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/src/dev_setup/registry.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/__init__.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/integration/__init__.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/integration/conftest.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/integration/test_agent_smoke.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/integration/test_agent_tui.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/integration/test_tools.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_agent.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_agent_completion.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_agent_loop.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_agent_sandbox.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_agent_tools.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_agent_wizard.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_catalog.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_functions.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_generic.py +0 -0
- {devstuff-1.16.0 → devstuff-1.18.0}/tests/test_registry.py +0 -0
|
@@ -52,6 +52,7 @@ jobs:
|
|
|
52
52
|
matrix:
|
|
53
53
|
tool:
|
|
54
54
|
- aws
|
|
55
|
+
- commitizen # uvx tool, requires uv
|
|
55
56
|
- eza
|
|
56
57
|
- gh
|
|
57
58
|
- git-lfs
|
|
@@ -61,6 +62,7 @@ jobs:
|
|
|
61
62
|
- java
|
|
62
63
|
- lazygit
|
|
63
64
|
- mkcert
|
|
65
|
+
- nerd-font
|
|
64
66
|
- nvm
|
|
65
67
|
- php
|
|
66
68
|
- pi # installs nvm first via its declared `requires`
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## v1.18.0 (2026-08-01)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **configure**: add commitizen tool and configuration wizard
|
|
6
|
+
|
|
7
|
+
## v1.17.0 (2026-07-31)
|
|
8
|
+
|
|
9
|
+
### Feat
|
|
10
|
+
|
|
11
|
+
- starship config font validation and install
|
|
12
|
+
- **configure**: add a starship prompt setup wizard with live preview
|
|
13
|
+
|
|
1
14
|
## v1.16.0 (2026-07-24)
|
|
2
15
|
|
|
3
16
|
### Feat
|
|
@@ -21,8 +21,10 @@ uv run pytest tests/test_catalog.py::test_user_catalog_overrides_bundled_tool_in
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
`pip` is not available in this dev environment — `uv pip install -e .` / `uv run` are the way in.
|
|
24
|
-
Interactive commands (`install`, `add`, `remove`, `delete`) open questionary/click
|
|
25
|
-
hang in non-TTY shells; don't try to drive them from a piped/non-interactive shell.
|
|
24
|
+
Interactive commands (`install`, `add`, `remove`, `delete`, `configure`) open questionary/click
|
|
25
|
+
prompts and hang in non-TTY shells; don't try to drive them from a piped/non-interactive shell.
|
|
26
|
+
To exercise one end-to-end anyway, fork a pty (`pty.fork()`) and write keystrokes to the fd —
|
|
27
|
+
that is how the starship wizard's full flow was verified.
|
|
26
28
|
|
|
27
29
|
### Integration tests (real installs, Docker-isolated)
|
|
28
30
|
|
|
@@ -60,6 +62,7 @@ src/dev_setup/
|
|
|
60
62
|
├── generic.py # GenericTool — the ONE engine that implements every install type
|
|
61
63
|
├── tools.yaml # Bundled built-in catalog (core/tools/languages categories)
|
|
62
64
|
├── ui.py # Rich console + questionary wrappers (spinners, prompts, styled output)
|
|
65
|
+
├── configure/ # Per-tool setup wizards (see "Configurators" below)
|
|
63
66
|
└── commands/ # One Click command per file: list, install, remove, add, delete, docs, catalog
|
|
64
67
|
```
|
|
65
68
|
|
|
@@ -167,6 +170,122 @@ non-interactive `bash <tmpfile>`, so `~/.bashrc`/nvm's shell init never runs on
|
|
|
167
170
|
Not yet built: an `add` wizard and `catalog import`/`export` for functions, analogous to the
|
|
168
171
|
ones tools already have.
|
|
169
172
|
|
|
173
|
+
## Configurators (`configure/`) — tool-specific wizards, deliberately *not* catalog-driven
|
|
174
|
+
|
|
175
|
+
`src/dev_setup/configure/` holds per-tool setup wizards (`devstuff configure <tool>`), registered
|
|
176
|
+
in a `CONFIGURATORS` dict keyed by catalog tool key. There are two:
|
|
177
|
+
`configure/starship/{model,render,preview,wizard}.py` and
|
|
178
|
+
`configure/commitizen/{model,render,detect,validate,wizard}.py`.
|
|
179
|
+
|
|
180
|
+
**Why this one breaks the YAML-catalog rule.** Installation generalises into ~7 mechanisms, which
|
|
181
|
+
is what makes `GenericTool` possible. Configuration does not: starship's config is a TOML file of
|
|
182
|
+
format strings, palette tables and powerline transition glyphs; another tool's would be shell
|
|
183
|
+
exports or `git config` calls. Expressing this wizard in YAML would need conditional questions, an
|
|
184
|
+
ordered section model with colour roles, and a template language — a programming language spelled
|
|
185
|
+
in YAML. So configurators are Python, dispatched from a dict, the same shape as `_INSTALLERS` in
|
|
186
|
+
`generic.py`. Full reasoning in `docs/specs/starship-config/stack-decisions.md` (SD-1).
|
|
187
|
+
|
|
188
|
+
A configurator that finds a missing *prerequisite* should offer to install it through
|
|
189
|
+
`install_cmd.install_by_key(key)` rather than telling the user to run a second command — that is
|
|
190
|
+
what the starship wizard does for `nerd-font`.
|
|
191
|
+
|
|
192
|
+
**Adding a configurator** — a new module plus one dict entry. The module must expose
|
|
193
|
+
`run(*, target: Path | None = None)` (returns `None` if the user cancelled; writes nothing until
|
|
194
|
+
they confirm) and `config_path() -> Path`. Everything generic — the picker, install-state check,
|
|
195
|
+
`--list`/`--path`/`--output`, and the post-install offer in `install_cmd.py` — reads the registry,
|
|
196
|
+
so none of it needs touching. There is deliberately **no `configure:` field in `tools.yaml`**: user
|
|
197
|
+
catalogs are strictly validated, so a catalog naming a nonexistent configurator would add a
|
|
198
|
+
load-time failure mode for nothing.
|
|
199
|
+
|
|
200
|
+
**Within the starship configurator, `model.py` is the data and everything else reads it.**
|
|
201
|
+
`SECTIONS` (ordered — declaration order *is* prompt order), `PALETTES` and `PRESETS` drive both the
|
|
202
|
+
TOML emitter and the offline preview, which is what stops those two from drifting. Adding a section
|
|
203
|
+
or palette is one entry; no other file changes.
|
|
204
|
+
|
|
205
|
+
**Things learned from the real binary — don't "simplify" these away:**
|
|
206
|
+
- `symbol` is emitted for every section whose body contains `$symbol`, *including as an empty
|
|
207
|
+
string*. Omit it and starship's built-in Nerd Font glyph leaks into the `plain` preset. The
|
|
208
|
+
converse is unit-tested: a section carrying an icon its body can't render is a bug (that's why
|
|
209
|
+
`directory`, which has no `symbol` key at all, has no icon).
|
|
210
|
+
- Not every module spells the colour key `style` — hence `Section.style_key` (`username` wants
|
|
211
|
+
`style_user`). `battery` is deliberately absent: it accepts neither `style` nor `symbol` (both
|
|
212
|
+
live in its `[[battery.display]]` array), so it would cost three quirk fields for one section.
|
|
213
|
+
- `kubernetes`, `time`, `azure`, `status` and `shlvl` ship *disabled*; listing them in `format`
|
|
214
|
+
isn't enough, they need `disabled = false`. `os` and `git_metrics` are absent for the same
|
|
215
|
+
reason `battery` is: `os` takes its symbol from an `[os.symbols]` distro table, `git_metrics`
|
|
216
|
+
has `added_style`/`deleted_style` instead of `style`.
|
|
217
|
+
- Format strings are emitted as TOML **literal** strings (`'…'`) so starship's `$`, `[`, and `\[`
|
|
218
|
+
grammar needs no escaping. The multi-line top-level `format` is the one basic string, and it
|
|
219
|
+
contains no backslashes of its own beyond the line continuations.
|
|
220
|
+
- Powerline transitions are emitted per **run of consecutive sections sharing a palette role**, not
|
|
221
|
+
per section — otherwise two adjacent language segments draw an arrow between two identical
|
|
222
|
+
backgrounds. The three powerline presets differ *only* in the four glyphs in their `Powerline`
|
|
223
|
+
record (`POWERLINES` in `model.py`); nothing in the emitter knows which variant it is drawing.
|
|
224
|
+
- Any literal text the emitter writes into a format string is escaped with `_escape_format()`.
|
|
225
|
+
This is not theoretical: `success_symbol = '[$](bold fg:ok)'` made starship read `$` as the start
|
|
226
|
+
of a variable name, so the `plain` preset shipped with *no prompt symbol at all* until it was
|
|
227
|
+
caught by sweeping every combination and asserting empty stderr.
|
|
228
|
+
- A custom module (`custom.compose`) is a normal `Section`, but its dotted key has to be written
|
|
229
|
+
`${custom.compose}` in `format` — hence `Section.ref`. It also runs a shell command on **every**
|
|
230
|
+
prompt, so it carries a `when` guard, and anything needing the network is disqualified.
|
|
231
|
+
- Symbols for new sections come from `starship print-config --default` — the module's own shipped
|
|
232
|
+
glyph — rather than being picked from a Nerd Font chart that can't be verified without the font.
|
|
233
|
+
- The sample project must never gain a `bun.lock`: starship's `nodejs` module lists it as a
|
|
234
|
+
*negative* detector, so it silently switches the Node section off in previews.
|
|
235
|
+
- The live preview runs `starship prompt` with `STARSHIP_SHELL=nu`, not `bash`: for bash, starship
|
|
236
|
+
wraps escapes in readline's `\[`/`\]` markers, which are invisible inside a `PS1` and print
|
|
237
|
+
literally anywhere else. It also overrides `PWD` (starship prefers it over the real cwd) and
|
|
238
|
+
makes a second `--right` call, since `right_format` is not part of the left prompt.
|
|
239
|
+
- Every preview failure path returns `None` and degrades to the offline renderer. A preview must
|
|
240
|
+
never be able to end the wizard.
|
|
241
|
+
- The Nerd Font gate (`configure/starship/fonts.py`) is allowed to answer "don't know": without
|
|
242
|
+
fontconfig there is nothing to enumerate, and `None` means *stay silent* rather than warn. It
|
|
243
|
+
also refuses to install over SSH — the glyphs are drawn by the client's terminal — and always
|
|
244
|
+
says that installing a font does not repoint the terminal at it. The install itself goes through
|
|
245
|
+
the ordinary catalog path (`nerd-font` in `tools.yaml` → `install_cmd.install_by_key`), never a
|
|
246
|
+
private download (SD-10).
|
|
247
|
+
|
|
248
|
+
**Within the commitizen configurator, the object being configured is a list of commit types, not
|
|
249
|
+
a settings sheet.** `TYPES` in `model.py` is ordered (declaration order *is* prompt order, changelog
|
|
250
|
+
order and regex-alternation order), and `render.py` derives all nine `cz_customize` settings from
|
|
251
|
+
it — so adding a type is one `ChangeType` record and it reaches `bump_pattern`, `bump_map`,
|
|
252
|
+
`schema_pattern`, `change_type_map`, `change_type_order`, `commit_parser` and `questions` with no
|
|
253
|
+
other edit. Full reasoning in `docs/specs/commitizen-config/`.
|
|
254
|
+
|
|
255
|
+
**Things learned from the real binary — don't "simplify" these away:**
|
|
256
|
+
- `bump_map` is an **ordered** map and commitizen `break`s at the first key that `re.match`es, so
|
|
257
|
+
the two breaking-change rules (`^.+!$`, `^BREAKING[\-\ ]CHANGE`) must be emitted first. Reorder
|
|
258
|
+
them and `feat(api)!:` silently ships as a MINOR.
|
|
259
|
+
- What `bump_map`'s keys are matched against is **group 1 of `bump_pattern`** (`feat(api)!`), not
|
|
260
|
+
the commit message. That is why `^.+!$` works at all, and why every selected type belongs in the
|
|
261
|
+
pattern even when it has no map entry.
|
|
262
|
+
- `schema_pattern` must always accept the `bump:` prefix (`ALWAYS_ACCEPTED` in `model.py`):
|
|
263
|
+
`cz bump` writes its own commit with that prefix, and `cz check --rev-range` over a release
|
|
264
|
+
otherwise rejects commitizen's own commit. `cz_conventional_commits` accepts `bump` for exactly
|
|
265
|
+
this reason without ever offering it in the picker.
|
|
266
|
+
- `commit_parser`'s trailing `|\w+!` alternative is load-bearing: it is what keeps `docs!: …` (a
|
|
267
|
+
breaking change on a type with no changelog section) in the release notes at all. Verified — it
|
|
268
|
+
lands in an unlabelled group rather than vanishing.
|
|
269
|
+
- The `BREAKING CHANGE` changelog heading only collects commits with a **footer**. A `feat!:` still
|
|
270
|
+
bumps the major but is written up under Features, because that is the type it declared.
|
|
271
|
+
- Regexes are emitted as TOML **literal** strings (`'…'`) so no backslash needs doubling;
|
|
272
|
+
`message_template` and `schema` are the exceptions (they carry real newlines, so they are basic
|
|
273
|
+
strings). A user-supplied value containing a quote falls back to a basic string automatically.
|
|
274
|
+
- `config_path()` mirrors `commitizen.config.read_cfg`: search order *and* the rule that a file
|
|
275
|
+
without a `commitizen` section doesn't count — otherwise every Python project on disk looks
|
|
276
|
+
already-configured because it has a `pyproject.toml`.
|
|
277
|
+
- The `pyproject.toml` splice is line-based, so it verifies itself by parsing the result back and
|
|
278
|
+
comparing the settings; a mismatch returns `None` and the caller writes `.cz.toml` instead. Don't
|
|
279
|
+
replace that check with reasoning about which files it can handle.
|
|
280
|
+
- `validate.py` is the "measured, not assumed" half: it replays commits through the real
|
|
281
|
+
`cz bump --dry-run` in a throwaway repo. It runs on an explicit menu action plus once at save
|
|
282
|
+
time — not on every redraw (~3s, unlike starship's millisecond preview) — and a disagreement
|
|
283
|
+
*warns*, it never vetoes a save. Keep that distinction in the comments.
|
|
284
|
+
|
|
285
|
+
Not yet built: configurators for anything other than starship and commitizen, and round-tripping an
|
|
286
|
+
existing hand-edited config back into wizard state (the timestamped backup is the safety net
|
|
287
|
+
instead).
|
|
288
|
+
|
|
170
289
|
## Specs (`docs/specs/`)
|
|
171
290
|
|
|
172
291
|
Design documents live in `docs/specs/<feature>/` — `specifications.md` (numbered, testable
|
|
@@ -258,6 +377,12 @@ Not yet built: an `add` wizard for agent tools, and `catalog import`/`export` fo
|
|
|
258
377
|
- **No new runtime dependencies for the agent.** The Ollama transport is stdlib `urllib` against
|
|
259
378
|
`/api/chat`; the REPL uses `prompt_toolkit`, already vendored via questionary. devstuff is a
|
|
260
379
|
globally installed CLI, so every dependency is a cost paid by users who never run `agent`.
|
|
380
|
+
- **Configuration is Python, installation is YAML.** The no-per-tool-code rule covers *install
|
|
381
|
+
mechanisms*, which generalise; per-tool config formats don't. `configure/` is a registry of
|
|
382
|
+
Python wizards on purpose — see the section above before trying to fold it into `tools.yaml`.
|
|
383
|
+
- **A config wizard previews with the real binary, not an approximation.** `starship prompt`
|
|
384
|
+
against a temp config in a throwaway project is the source of truth; the offline renderer is a
|
|
385
|
+
labelled fallback for when the tool isn't installed (and is what unit tests exercise).
|
|
261
386
|
- **Functions get a parallel catalog/registry instead of extending `GenericTool`.** The
|
|
262
387
|
schemas diverge enough (no `requires` inference, a `params` list, no install/remove
|
|
263
388
|
lifecycle) that folding them into the tool catalog would be lossy; some duplication with
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devstuff
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.18.0
|
|
4
4
|
Summary: Development environment setup CLI for Linux
|
|
5
5
|
Project-URL: Repository, https://github.com/thesawdawg/dev-setup-py
|
|
6
6
|
Author-email: Sawyer <sawyerksu@gmail.com>
|
|
@@ -188,6 +188,201 @@ for confirmation before doing this.
|
|
|
188
188
|
|
|
189
189
|
---
|
|
190
190
|
|
|
191
|
+
### `configure`
|
|
192
|
+
|
|
193
|
+
Set up an installed tool through a guided wizard, previewing the result before anything is
|
|
194
|
+
written. Installing a tool that has a wizard also offers to run it there and then.
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
devstuff configure # pick from the tools that have a wizard
|
|
198
|
+
devstuff configure starship # run starship's prompt wizard
|
|
199
|
+
devstuff configure --list # which tools have a wizard
|
|
200
|
+
devstuff configure starship --path # print the config file path
|
|
201
|
+
devstuff configure starship --output /tmp/try.toml # write elsewhere, leave the live config alone
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Tool | What it configures |
|
|
205
|
+
|------|-------------------|
|
|
206
|
+
| `commitizen` | Commit types, what each one bumps, git tags, and changelog sections |
|
|
207
|
+
| `starship` | Prompt style, colour palette, which sections appear, and layout |
|
|
208
|
+
|
|
209
|
+
#### Commitizen wizard
|
|
210
|
+
|
|
211
|
+
Commitizen needs a config file before it does anything, and everything past its built-in
|
|
212
|
+
Conventional Commits rules means `cz_customize` — nine coupled regexes where `bump_map`'s keys
|
|
213
|
+
are matched against **group 1** of `bump_pattern`, the two breaking-change rules have to come
|
|
214
|
+
*first* because commitizen stops at the first key that matches, and `schema_pattern` has to
|
|
215
|
+
accept whatever `message_template` produces. Get the order wrong and `feat(api)!:` quietly ships
|
|
216
|
+
as a minor release.
|
|
217
|
+
|
|
218
|
+
The wizard asks about commit types and version rules, and derives all nine settings from the
|
|
219
|
+
answers:
|
|
220
|
+
|
|
221
|
+
| Step | Options |
|
|
222
|
+
|------|---------|
|
|
223
|
+
| **Convention** | `cz_conventional_commits` (commitizen's fixed rules — nothing to configure) · `cz_customize` (your types, your bump rules) |
|
|
224
|
+
| **Commit types** | Checkbox over `feat`, `fix`, `refactor`, `perf`, `docs`, `style`, `test`, `build`, `ci` (all on, matching Conventional Commits) plus `chore`, `revert`, `deps`, `security` — and you can add your own |
|
|
225
|
+
| **Per type** | What it bumps (`MAJOR` / `MINOR` / `PATCH` / no release), whether it appears in the changelog, under which heading, and its hotkey in `cz commit` |
|
|
226
|
+
| **Versioning** | Where the version lives (`commitizen`, `scm`, `pep621`, `uv`, `poetry`, `cargo`, `npm`, `composer`) · scheme (`semver`, `semver2`, `pep440`) · tag format · other files carrying the version |
|
|
227
|
+
| **Release** | Changelog on bump · `0.x` mode · annotated tags · GPG signing · incremental changelog · prerelease merging · `allow_abort` · hotkeys · changelog file · bump commit message |
|
|
228
|
+
| **Prompt** | Which questions `cz commit` asks — scope, body, footer |
|
|
229
|
+
| **Destination** | `pyproject.toml` (spliced in place) or a standalone `.cz.toml` |
|
|
230
|
+
|
|
231
|
+
The custom branch **starts as an exact copy of Conventional Commits** — the built-in type table
|
|
232
|
+
reproduces `commitizen.defaults.BUMP_MAP` and its picker, read out of the installed package and
|
|
233
|
+
pinned by a test. Switching to custom to add one type does not cost you the convention.
|
|
234
|
+
|
|
235
|
+
Before it asks anything, the wizard reads the project: git root, any existing commitizen config
|
|
236
|
+
(in commitizen's own search order, ignoring files without a `commitizen` section), the version
|
|
237
|
+
provider and current version from `pyproject.toml`/`package.json`/`Cargo.toml`/`composer.json`,
|
|
238
|
+
the latest git tag, and an existing changelog.
|
|
239
|
+
|
|
240
|
+
The review screen shows a sample `cz commit` message, the bump table, and the changelog sections:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
what each type does to 1.4.2
|
|
244
|
+
|
|
245
|
+
commit increment new version
|
|
246
|
+
feat: … MINOR 1.5.0
|
|
247
|
+
fix: … PATCH 1.4.3
|
|
248
|
+
docs: … — 1.4.2
|
|
249
|
+
feat!: … MAJOR 2.0.0
|
|
250
|
+
BREAKING CHANGE: … (footer) MAJOR 2.0.0
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**That table is checked against the real thing.** "Check these rules against the real cz" builds
|
|
254
|
+
a throwaway git repo tagged at 1.4.2, replays one commit per bump level plus both breaking forms
|
|
255
|
+
through `cz bump --dry-run`, and reports whether commitizen agrees rule by rule. The same check
|
|
256
|
+
runs automatically before saving — a disagreement is reported and asks for confirmation, but
|
|
257
|
+
never blocks the save. "Preview a generated changelog" runs the real `cz changelog --dry-run`
|
|
258
|
+
over one sample commit per type. Without `cz` installed the wizard still works; the checks say so
|
|
259
|
+
rather than failing.
|
|
260
|
+
|
|
261
|
+
On save:
|
|
262
|
+
|
|
263
|
+
- Into `pyproject.toml`, every `[tool.commitizen…]` table is replaced and **the rest of the file
|
|
264
|
+
is left byte for byte**. The result is parsed back and compared to what was meant; if it does
|
|
265
|
+
not match, the write falls back to a standalone `.cz.toml` and the original is untouched.
|
|
266
|
+
- Any existing file is copied to `<name>.bak.<timestamp>` first, and a config that wasn't written
|
|
267
|
+
by this wizard asks before being replaced.
|
|
268
|
+
- If more than one commitizen config now exists, you're told which one commitizen will actually
|
|
269
|
+
read — `.cz.toml` beats `pyproject.toml`, so a new dotfile can silently shadow settings you
|
|
270
|
+
forgot about.
|
|
271
|
+
- In a git repo with no `commit-msg` hook, you're offered one running `cz check`. An existing
|
|
272
|
+
hook is never replaced.
|
|
273
|
+
|
|
274
|
+
The output is meant to be hand-edited afterwards: commented, ordered, and with regexes written as
|
|
275
|
+
TOML literal strings so `^((BREAKING[\-\ ]CHANGE|feat)(\(.+\))?!?):` reads as itself instead of
|
|
276
|
+
with every backslash doubled.
|
|
277
|
+
|
|
278
|
+
```toml
|
|
279
|
+
# Commitizen configuration
|
|
280
|
+
# Generated by `devstuff configure commitizen` — edit freely, or re-run the wizard.
|
|
281
|
+
# Convention: Custom types and bump rules · Types: feat, fix, docs, deps
|
|
282
|
+
# Option reference: https://commitizen-tools.github.io/commitizen/config/
|
|
283
|
+
[tool.commitizen]
|
|
284
|
+
name = 'cz_customize'
|
|
285
|
+
version_provider = 'pep621'
|
|
286
|
+
version_scheme = 'pep440'
|
|
287
|
+
tag_format = 'v$version'
|
|
288
|
+
update_changelog_on_bump = true
|
|
289
|
+
# …
|
|
290
|
+
|
|
291
|
+
# Prefix -> version increment. Order matters: commitizen stops at the first
|
|
292
|
+
# key that matches, so the two breaking-change rules have to lead.
|
|
293
|
+
[tool.commitizen.customize.bump_map]
|
|
294
|
+
'^.+!$' = 'MAJOR'
|
|
295
|
+
'^BREAKING[\-\ ]CHANGE' = 'MAJOR'
|
|
296
|
+
'^feat' = 'MINOR'
|
|
297
|
+
'^fix' = 'PATCH'
|
|
298
|
+
'^deps' = 'PATCH'
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Design notes, including why this one isn't catalog-driven and why the checks warn rather than
|
|
302
|
+
veto: [`docs/specs/commitizen-config/`](docs/specs/commitizen-config/).
|
|
303
|
+
|
|
304
|
+
#### Starship prompt wizard
|
|
305
|
+
|
|
306
|
+
Four questions, with the prompt re-rendered after each one:
|
|
307
|
+
|
|
308
|
+
| Step | Options |
|
|
309
|
+
|------|---------|
|
|
310
|
+
| **Style** | `Plain text` · `Bracketed segments` (both ASCII, any font) · `Icons` · `Icons, bracketed` (Nerd Font glyphs) · `Powerline`, `Powerline, rounded`, `Powerline, slanted` (solid colour bars) |
|
|
311
|
+
| **Palette** | `Terminal colours` (inherits your terminal theme) · Catppuccin Mocha · Nord · Gruvbox Dark · Tokyo Night · Dracula · Rosé Pine · Catppuccin Latte (light) |
|
|
312
|
+
| **Sections** | Grouped checkbox over ~35 modules — see the table below |
|
|
313
|
+
| **Layout** | Single line · Two lines · Two lines with shell info right-aligned (needs zsh/fish/nushell — bash has no right prompt) |
|
|
314
|
+
|
|
315
|
+
| Group | Sections |
|
|
316
|
+
|-------|----------|
|
|
317
|
+
| **Context** | username, hostname (over SSH), container (Docker/toolbox/distrobox) |
|
|
318
|
+
| **Location** | current directory |
|
|
319
|
+
| **Git** | branch, commit hash (when detached), status (dirty/ahead/behind), operation in progress |
|
|
320
|
+
| **Languages** | Node.js, Deno, Bun, Python, Rust, Go, Java, PHP, Ruby, Elixir, .NET, package version |
|
|
321
|
+
| **Infrastructure** | Docker context, **Docker Compose project**, Kubernetes context, AWS profile, Google Cloud project, Azure subscription, Terraform workspace, Nix shell |
|
|
322
|
+
| **Shell** | command duration, exit code of the last command, background jobs, nested shell depth, clock |
|
|
323
|
+
|
|
324
|
+
The review menu adds two content toggles: the blank line between prompts, and whether language
|
|
325
|
+
sections show **version numbers** or just the runtime's symbol.
|
|
326
|
+
|
|
327
|
+
If you pick a style that needs a Nerd Font and there isn't one on the machine, the wizard says
|
|
328
|
+
so in the style list itself (`Needs a Nerd Font — none installed here.`) and offers to install
|
|
329
|
+
`nerd-font` right there — once per run, whether you say yes or no. Two cases it handles rather
|
|
330
|
+
than pretending otherwise: over SSH it points you at [nerdfonts.com](https://www.nerdfonts.com/)
|
|
331
|
+
instead, because the glyphs are drawn by the terminal on *your* machine, not the one you're
|
|
332
|
+
configuring; and after installing it reminds you to actually select the font in your terminal's
|
|
333
|
+
settings, which is a preference no shell can change for you. Without `fontconfig` there is no way
|
|
334
|
+
to enumerate fonts, so the wizard says nothing rather than guessing.
|
|
335
|
+
|
|
336
|
+
The Compose section is a starship [custom module](https://starship.rs/config/#custom-commands)
|
|
337
|
+
rather than a built-in one — it reports the project name `docker compose` in that directory would
|
|
338
|
+
actually use (`$COMPOSE_PROJECT_NAME`, else a top-level `name:` in the compose file, else the
|
|
339
|
+
lowercased directory name), and it only runs at all when there is a compose file next to you.
|
|
340
|
+
|
|
341
|
+
The preview is the real thing: the candidate config is written to a temp file and rendered by
|
|
342
|
+
your installed `starship` binary inside a throwaway sample project (a git repo with language
|
|
343
|
+
marker files), so what you see is the bytes your prompt will produce. Without starship installed
|
|
344
|
+
the wizard still works and falls back to a labelled approximation.
|
|
345
|
+
|
|
346
|
+
A review menu then lets you revisit any answer, dump the generated TOML, or save. On save:
|
|
347
|
+
|
|
348
|
+
- Written to `$STARSHIP_CONFIG`, or `~/.config/starship.toml`.
|
|
349
|
+
- Any existing file is copied to `starship.toml.bak.<timestamp>` first — and if it wasn't written
|
|
350
|
+
by this wizard, you're asked before it's replaced.
|
|
351
|
+
- If `~/.bashrc` has no starship hook, you're offered one (using the same marker
|
|
352
|
+
`devstuff install starship` uses, so `devstuff remove starship` still cleans up).
|
|
353
|
+
|
|
354
|
+
The output is meant to be hand-edited afterwards: it's commented, ordered, and colours are
|
|
355
|
+
referenced through nine semantic palette roles (`dir`, `git`, `lang`, `infra`, `shell`, `ok`,
|
|
356
|
+
`err`, `muted`, `bar_text`), so retheming everything is nine edits in one table.
|
|
357
|
+
|
|
358
|
+
```toml
|
|
359
|
+
# Starship prompt configuration
|
|
360
|
+
# Generated by `devstuff configure starship` — edit freely, or re-run the wizard.
|
|
361
|
+
# Style: Powerline · Palette: Nord · Layout: Two lines
|
|
362
|
+
# Module reference: https://starship.rs/config/
|
|
363
|
+
"$schema" = 'https://starship.rs/config-schema.json'
|
|
364
|
+
|
|
365
|
+
add_newline = true
|
|
366
|
+
palette = 'nord'
|
|
367
|
+
|
|
368
|
+
format = """
|
|
369
|
+
[](fg:dir)\
|
|
370
|
+
$directory\
|
|
371
|
+
[](fg:dir bg:git)\
|
|
372
|
+
$git_branch\
|
|
373
|
+
[](fg:git)\
|
|
374
|
+
$line_break\
|
|
375
|
+
$character"""
|
|
376
|
+
|
|
377
|
+
# Semantic colour roles — swap these to retheme every section at once.
|
|
378
|
+
[palettes.nord]
|
|
379
|
+
dir = '#81a1c1'
|
|
380
|
+
git = '#a3be8c'
|
|
381
|
+
# …
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
191
386
|
### `add`
|
|
192
387
|
|
|
193
388
|
Guided wizard to register a new custom package. Supports six install types:
|
|
@@ -586,16 +781,18 @@ Optional utilities you may want on some machines.
|
|
|
586
781
|
| Key | Name | Description | Help |
|
|
587
782
|
|-----|------|-------------|------|
|
|
588
783
|
| `aws` | AWS CLI | Amazon Web Services CLI v2 | `aws help` |
|
|
784
|
+
| `commitizen` | Commitizen | Conventional-commit prompt, semantic version bumping, and changelog generation (`devstuff configure commitizen`) | `cz --help` |
|
|
589
785
|
| `eza` | eza | Modern ls replacement with git status, icons, and tree view | `eza --help` |
|
|
590
786
|
| `gh` | GitHub CLI | GitHub's official CLI | `gh --help` |
|
|
591
787
|
| `htop` | htop | Interactive process and resource monitor | `man htop` |
|
|
592
788
|
| `mkcert` | mkcert | Zero-config local HTTPS certificates | `mkcert --help` |
|
|
789
|
+
| `nerd-font` | JetBrainsMono Nerd Font | Patched font supplying the icons Starship and other CLI tools draw | `fc-list \| grep -i "nerd font"` |
|
|
593
790
|
| `ollama` | Ollama | Run large language models locally | `ollama --help` |
|
|
594
791
|
| `php` | PHP 8.4 | PHP 8.4 + common extensions via ondrej/php PPA | `php --help` |
|
|
595
792
|
| `pi` | Pi Coding Agent | AI coding agent npm package | `pi --help` |
|
|
596
793
|
| `pre-commit` | pre-commit | Git hook manager for automated code quality checks | `pre-commit --help` |
|
|
597
794
|
| `saml2aws` | saml2aws | SAML → AWS STS credentials CLI (Versent) | `saml2aws --help` |
|
|
598
|
-
| `starship` | Starship | Fast, cross-shell customizable prompt | `starship --help` |
|
|
795
|
+
| `starship` | Starship | Fast, cross-shell customizable prompt (`devstuff configure starship`) | `starship --help` |
|
|
599
796
|
| `yq` | yq | Portable command-line YAML/JSON/XML processor | `yq --help` |
|
|
600
797
|
|
|
601
798
|
### Languages
|
|
@@ -740,6 +937,13 @@ dev-setup-py/
|
|
|
740
937
|
├── functions_registry.py # Loads bundled + user YAML into the live function registry
|
|
741
938
|
├── function_runner.py # Param resolution + script/eval/bashrc rendering & execution
|
|
742
939
|
├── functions.yaml # Bundled built-in function catalog
|
|
940
|
+
├── configure/ # Per-tool setup wizards (see "configure" above)
|
|
941
|
+
│ ├── __init__.py # CONFIGURATORS registry: tool key -> wizard module
|
|
942
|
+
│ └── starship/
|
|
943
|
+
│ ├── model.py # presets, palettes, sections, StarshipConfig
|
|
944
|
+
│ ├── render.py # starship.toml emitter + offline preview renderer
|
|
945
|
+
│ ├── preview.py # live preview via `starship prompt` in a sample project
|
|
946
|
+
│ └── wizard.py # the interactive flow, backup + save
|
|
743
947
|
├── agent_tools.yaml # Bundled agent tool catalog
|
|
744
948
|
├── agent/ # Local-model agent (see "Agent" above)
|
|
745
949
|
│ ├── config.py # agent.yaml load/validate/save
|