devstuff 1.13.1__py3-none-any.whl

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,617 @@
1
+ Metadata-Version: 2.4
2
+ Name: devstuff
3
+ Version: 1.13.1
4
+ Summary: Development environment setup CLI for Linux
5
+ Project-URL: Repository, https://github.com/thesawdawg/dev-setup-py
6
+ Author-email: Sawyer <sawyerksu@gmail.com>
7
+ License: MIT
8
+ Keywords: cli,developer,devtools,linux,setup
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: System :: Installation/Setup
20
+ Classifier: Topic :: Utilities
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: click>=8.1
23
+ Requires-Dist: pyyaml>=6.0
24
+ Requires-Dist: questionary>=2.0
25
+ Requires-Dist: rich>=13.0
26
+ Description-Content-Type: text/markdown
27
+
28
+ # devstuff
29
+
30
+ A Python-based CLI for managing your Linux development environment. Install, remove, and track developer tools from a single command — with an interactive picker, a guided wizard for adding custom packages, and a consistent Rich terminal UI.
31
+
32
+ ---
33
+
34
+ ## Prerequisites
35
+
36
+ | Requirement | Notes |
37
+ |-------------|-------|
38
+ | **OS** | Ubuntu 20.04+ or Debian 11+ (amd64) |
39
+ | **Python** | 3.11 or later |
40
+ | **curl** | Used by script-based installers (Docker, NVM, uv, etc.) |
41
+ | **sudo** | Required for tools that write to system paths (`/usr/local/bin`, apt packages) |
42
+ | **ca-certificates** | For HTTPS downloads — present on most systems by default |
43
+
44
+ These are available on any standard Ubuntu/Debian install. On a fresh minimal image, run:
45
+
46
+ ```bash
47
+ sudo apt-get install -y python3 python3-pip curl ca-certificates sudo
48
+ ```
49
+
50
+ **Optional** — only needed when using specific install types:
51
+
52
+ | Requirement | When |
53
+ |-------------|------|
54
+ | `git` | `git`-type custom packages (`devstuff add` → git) |
55
+ | `node` / `npm` | `npm`-type custom packages |
56
+ | `uv` | Running from source via `./dev-setup` (auto-installed if missing) |
57
+
58
+ ---
59
+
60
+ ## Installation
61
+
62
+ ### From PyPI (recommended)
63
+
64
+ The simplest install — no git clone required, Python 3.11+ is the only prerequisite:
65
+
66
+ ```bash
67
+ # pipx gives the tool its own isolated environment (preferred)
68
+ pipx install devstuff
69
+
70
+ # or plain pip
71
+ pip install devstuff
72
+ ```
73
+
74
+ After install, `devstuff` is the primary command. Run `devstuff --help` to verify. The former
75
+ `dev-setup` command remains available as a compatibility alias.
76
+
77
+ ### From source (development)
78
+
79
+ ```bash
80
+ git clone <repo-url> ~/dev-setup-py
81
+ cd ~/dev-setup-py
82
+ bash install.sh # installs from PyPI via pipx or pip
83
+ ```
84
+
85
+ Or to run directly from the cloned repo without installing:
86
+
87
+ ```bash
88
+ ./dev-setup list # creates a .venv on first run, then stays fast
89
+ ```
90
+
91
+ The `./dev-setup` bash script requires Python 3.11+ and creates a local `.venv` automatically. On Debian/Ubuntu, if `python3-venv` is not installed, it falls back to `uv venv` if uv is available.
92
+
93
+ For editable development installs:
94
+
95
+ ```bash
96
+ pip install -e .
97
+ devstuff list
98
+ ```
99
+
100
+ ---
101
+
102
+ ## How it works
103
+
104
+ When installed from PyPI (via `pip` or `pipx`), `devstuff` is a standard Python entry point — Python is the only runtime dependency. The `[project.scripts]` entries in `pyproject.toml` map both `devstuff` and the compatibility alias `dev-setup` directly to `dev_setup.__main__:main`.
105
+
106
+ The bash `./dev-setup` script in the repo is a convenience runner for the git-clone workflow. It creates a `.venv` using `python3 -m venv` (falling back to `uv venv` on systems where `python3-venv` is a separate package) and installs the project in editable mode on first run.
107
+
108
+ ---
109
+
110
+ ## Commands
111
+
112
+ ### `list`
113
+
114
+ Show all available packages with their install status, type, version, and help command.
115
+
116
+ ```bash
117
+ devstuff list # all packages
118
+ devstuff list core # core category only
119
+ devstuff list tools # tools category only
120
+ devstuff list custom # custom/user-added packages only
121
+ devstuff list --installed # only installed packages
122
+ devstuff list --available # only packages not yet installed
123
+ ```
124
+
125
+ Output columns: status (✔/✘), package key, description, install type, version (if installed), help command.
126
+
127
+ ---
128
+
129
+ ### `install`
130
+
131
+ Install one or more packages by key, or launch an interactive multi-select picker.
132
+
133
+ ```bash
134
+ devstuff install docker nvm # install specific packages
135
+ devstuff install # interactive picker (Space to toggle, Enter to confirm)
136
+ ```
137
+
138
+ The interactive picker shows all available packages with their current install status and lets you select multiple at once before confirming.
139
+
140
+ ---
141
+
142
+ ### `remove`
143
+
144
+ Uninstall an installed package. Always asks for confirmation before proceeding.
145
+
146
+ ```bash
147
+ devstuff remove htop
148
+ devstuff uninstall htop # alias
149
+ ```
150
+
151
+ ---
152
+
153
+ ### `update`
154
+
155
+ Update one or more already-installed packages to the latest version, or pin a single package to
156
+ a specific version with `--version`. With no arguments, launches an interactive multi-select
157
+ picker over installed packages, similar to `install`.
158
+
159
+ ```bash
160
+ devstuff update nvm # update to latest
161
+ devstuff update pi --version 1.2.3 # pin a single package to a specific version
162
+ devstuff update # interactive picker
163
+ ```
164
+
165
+ Packages that aren't installed are skipped with a warning rather than treated as an error.
166
+ `--version` can only be combined with a single package (and is not available in the interactive
167
+ picker).
168
+
169
+ The interactive picker probes every installed package for a newer version (`npm view`, `uv tool
170
+ list --outdated`, `apt-cache policy`, or comparing local vs. remote git HEAD) and pre-checks the
171
+ ones with a known update available. `script`/`bash` packages have no reliable way to check for
172
+ a newer version ahead of time, so they're listed as "unknown" and left unchecked — selecting one
173
+ still works, it just can't be pre-recommended.
174
+
175
+ How "update" is performed depends on the package's install `type`:
176
+
177
+ | Type | Latest | Specific version |
178
+ |------|--------|-------------------|
179
+ | `npm` | `npm install -g <pkg>@latest` | `npm install -g <pkg>@<version>` |
180
+ | `pip` / `uvx` | `uv tool upgrade <pkg>` | `uv tool upgrade <pkg>==<version>` |
181
+ | `apt` | `apt-get install --only-upgrade` | `apt-get install <pkg>=<version>` (single package only) |
182
+ | `git` | `git pull` (+ re-run `git_install_cmd`) | not supported — repos are cloned shallow (`--depth=1`) |
183
+ | `script` / `bash` | Re-runs the install script | not supported — no version parameter to inject |
184
+
185
+ For `script`/`bash` packages, "update" is a full reinstall (the same script that may have used
186
+ `sudo` runs again), since there's no narrower update mechanism available. `devstuff update` asks
187
+ for confirmation before doing this.
188
+
189
+ ---
190
+
191
+ ### `add`
192
+
193
+ Guided wizard to register a new custom package. Supports six install types:
194
+
195
+ | Type | What it does |
196
+ |------|-------------|
197
+ | `npm` | `npm install -g <package>` |
198
+ | `uvx` | `uv tool install <package>` |
199
+ | `apt` | `sudo apt-get install -y <packages>` |
200
+ | `git` | `git clone --depth=1 <url>` with optional post-clone and pre-remove commands |
201
+ | `script` | `curl -fsSL <url> \| sh` — single-URL convenience script |
202
+ | `bash` | Arbitrary multi-step bash — opens `$EDITOR` for install and remove scripts |
203
+
204
+ ```bash
205
+ devstuff add
206
+ ```
207
+
208
+ The wizard collects type-specific fields, then prompts for a help command (e.g. `tool --help`). Packages are saved into `~/.config/dev-setup/tools.yaml`.
209
+
210
+ #### `bash` type
211
+
212
+ For tools like AWS CLI or saml2aws that require multiple download/extract/install steps, choose the `bash` type. The wizard opens `$EDITOR` twice — once for the install script and once for the optional remove script — with a `#!/usr/bin/env bash / set -euo pipefail` template pre-filled.
213
+
214
+ Example YAML for a `bash`-type custom package:
215
+
216
+ ```yaml
217
+ version: 1
218
+ tools:
219
+ batcat:
220
+ name: batcat
221
+ description: Modern cat with syntax highlighting
222
+ category: custom
223
+ type: bash
224
+ check_cmd: bat
225
+ help_cmd: bat --help
226
+ install_script: |
227
+ set -euo pipefail
228
+ VER=$(curl -s https://api.github.com/repos/sharkdp/bat/releases/latest | grep tag_name | cut -d'"' -f4 | sed 's/v//')
229
+ curl -fsSL "https://github.com/sharkdp/bat/releases/download/v${VER}/bat_${VER}_amd64.deb" -o /tmp/bat.deb
230
+ sudo dpkg -i /tmp/bat.deb
231
+ rm /tmp/bat.deb
232
+ remove_script: |
233
+ sudo dpkg -r bat
234
+ ```
235
+
236
+ ---
237
+
238
+ ### `delete`
239
+
240
+ Remove a user catalog entry from the registry. Built-in-only packages cannot be deleted, but a user override of a built-in package can be deleted to restore the bundled definition.
241
+
242
+ ```bash
243
+ devstuff delete my-tool
244
+ devstuff rm my-tool # alias
245
+ ```
246
+
247
+ Asks for confirmation, then removes the entry from `~/.config/dev-setup/tools.yaml`.
248
+
249
+ ---
250
+
251
+ ### `catalog`
252
+
253
+ Manage the user YAML catalog.
254
+
255
+ ```bash
256
+ devstuff catalog path # print ~/.config/dev-setup/tools.yaml
257
+ devstuff catalog export # write ./dev-setup-tools.yaml
258
+ devstuff catalog export tools.yaml # write effective catalog to a path
259
+ devstuff catalog import tools.yaml # validate and merge into user catalog
260
+ ```
261
+
262
+ The effective catalog is loaded in this order:
263
+
264
+ 1. Bundled tools from `src/dev_setup/tools.yaml`
265
+ 2. Legacy JSON migration from `~/.config/dev-setup/packages/*.json`
266
+ 3. User overrides and additions from `~/.config/dev-setup/tools.yaml`
267
+
268
+ When a user key matches a bundled key, the user definition overrides the bundled definition in place. New user keys are appended after bundled tools.
269
+
270
+ ---
271
+
272
+ ## Functions/Scripts
273
+
274
+ Reusable shell functions/snippets, tracked in a separate catalog from installable tools
275
+ (`~/.config/dev-setup/functions.yaml`, same bundled+user precedence merge as `tools.yaml`).
276
+ Unlike tools, functions aren't installed/removed — they're invoked.
277
+
278
+ There are two function `type`s, because a `devstuff` command runs as its own child process
279
+ and can't mutate the shell that invoked it:
280
+
281
+ | Type | What it does | How you invoke it |
282
+ |------|---------------|--------------------|
283
+ | `script` | Runs as a subprocess (like a tool's `install_script`) — for anything that just calls other binaries/apps and doesn't need to change your shell's state. | `devstuff run <key> [args...]` — prompts for any missing required param. |
284
+ | `shell-eval` | For things that must mutate the *calling* shell — env vars, `cd`, aliases, agents. Has two `register` modes (see below). | Depends on `register`. |
285
+
286
+ `shell-eval` functions declare `register`:
287
+
288
+ - **`register: bashrc`** (default) — `devstuff functions enable <key>` patches a real shell
289
+ function into `~/.bashrc` (idempotent, using the same patch/remove mechanism as tool
290
+ bashrc blocks). After enabling, open a new shell (or `source ~/.bashrc`) and call the
291
+ function directly by name — `devstuff` itself never runs it, since a child process
292
+ can't export environment changes back to your interactive shell.
293
+ ```bash
294
+ devstuff functions enable ssh-agent-key
295
+ source ~/.bashrc
296
+ ssh-agent-key ~/.ssh/id_ed25519
297
+ ```
298
+ `devstuff functions disable <key>` removes it from `~/.bashrc`.
299
+ - **`register: eval`** — `devstuff run <key> [args]` resolves params and prints shell code
300
+ to stdout only (no prompts, no formatting — anything else on stdout would corrupt the
301
+ `eval` capture); missing required params are reported on stderr and exit non-zero instead.
302
+ ```bash
303
+ eval "$(devstuff run some-eval-function arg1)"
304
+ ```
305
+
306
+ Other commands:
307
+
308
+ ```bash
309
+ devstuff functions list # show all functions, their type, and declared params
310
+ devstuff functions path # print ~/.config/dev-setup/functions.yaml
311
+ ```
312
+
313
+ ### functions.yaml schema
314
+
315
+ A JSON Schema documenting every field (`src/dev_setup/functions.schema.json`) mirrors the
316
+ validation in `functions_catalog.py` — point your editor's YAML language server at it for
317
+ inline docs/autocomplete/validation while hand-editing a functions catalog (in VS Code with
318
+ the YAML extension, add a `yaml.schemas` mapping to the file's path, or add a
319
+ `# yaml-language-server: $schema=<path>` comment at the top of the file, as the bundled
320
+ catalog does).
321
+
322
+ ```yaml
323
+ version: 1
324
+ functions:
325
+ ssh-agent-key:
326
+ name: SSH Agent + Add Key
327
+ description: Start ssh-agent in the current shell and add a key to it
328
+ type: shell-eval
329
+ register: bashrc
330
+ params:
331
+ - name: key_path
332
+ description: Path to the SSH private key
333
+ required: true
334
+ script: |
335
+ eval "$(ssh-agent -s)"
336
+ ssh-add "$key_path"
337
+ docs_url: https://www.ssh.com/academy/ssh/agent
338
+ ```
339
+
340
+ Each `params` entry becomes a named shell variable in the script body (`$key_path`, not
341
+ positional `$1`) — the runner injects a prelude mapping real argv positions to those names
342
+ for `script`/bashrc-registered functions, or bakes the already-resolved, shell-quoted values
343
+ directly for `register: eval` (which has no argv channel of its own once `eval`'d).
344
+
345
+ #### Function fields
346
+
347
+ | Field | Required | Description |
348
+ |-------|----------|-------------|
349
+ | `name` | no | Display name shown in `functions list`. Defaults to the catalog key. |
350
+ | `description` | no | Short description shown in `functions list`. Defaults to `""`. |
351
+ | `category` | no | Group shown in `functions list` (grouped/sorted like tools). Freeform string, defaults to `custom`. |
352
+ | `type` | yes | `script` or `shell-eval` — see the type table above. |
353
+ | `register` | shell-eval only | `bashrc` (default) or `eval`. Rejected for `type: script`. |
354
+ | `params` | no | List of param objects (see below), resolved positionally in the order declared. |
355
+ | `script` | yes | The bash script body. References params by name (`"$key_path"`), not by position (`$1`). |
356
+ | `help_cmd` | no | Help command shown alongside the function in `functions list`. |
357
+ | `docs_url` | no | Documentation URL for this function. |
358
+
359
+ #### Param fields
360
+
361
+ | Field | Required | Description |
362
+ |-------|----------|-------------|
363
+ | `name` | yes | Shell variable name the param is bound to. Must be a valid shell identifier (letters/digits/underscore, not starting with a digit) and unique within the function. |
364
+ | `description` | no | Defaults to `""`. Shown as the prompt label when this param is missing and interactively promptable (`type: script` only — `shell-eval` never prompts). |
365
+ | `required` | no | Defaults to `true`. Whether the param must resolve to a non-empty value. An explicitly empty value (`devstuff run key ""`) counts as missing, same as not passing it at all. |
366
+ | `default` | no | Defaults to `""`. Fallback value used when nothing else resolves it. A required param *with* a default is always satisfied by it, so it never triggers a resolution error or (for `register: bashrc`) the runtime bash guard described below. |
367
+
368
+ Unknown fields fail validation, same as tools. A required param without a default behaves
369
+ differently per invocation path:
370
+ - `type: script` — prompts for it interactively (unless stdin isn't a terminal, in which case
371
+ it's reported and the command exits non-zero rather than hitting an unreadable prompt).
372
+ - `register: eval` — reported on stderr and exits non-zero; never prompts, to keep stdout
373
+ clean for `eval` capture.
374
+ - `register: bashrc` — `devstuff` is never involved when the enabled function is called
375
+ directly, so enforcement happens inside the generated function itself: it fails loudly
376
+ (message to stderr, `return 1`) if the argument is left blank at call time.
377
+
378
+ Not yet built: an `add` wizard and `catalog import`/`export` for functions, analogous to the
379
+ ones tools already have — for now, custom functions are hand-edited YAML at
380
+ `~/.config/dev-setup/functions.yaml`.
381
+
382
+ ### Built-in functions
383
+
384
+ | Key | Category | Type | Description | Args |
385
+ |-----|----------|------|--------------|------|
386
+ | `ssh-agent-key` | auth | shell-eval (bashrc) | Start ssh-agent in the current shell and add a key to it | `key_path` |
387
+ | `validate-docker-compose` | validation | script | Validate a docker-compose.yml file in the current directory | — |
388
+ | `validate-yaml` | validation | script | Validate a YAML file's syntax using `yq` | `file` |
389
+ | `acc-check` | web-dev | script | Run the pi coding agent's `/dogfood` skill against a web URL | `url`, `instruction` (optional) |
390
+ | `aws-saml-reauth` | web-dev | script | Reauthorize the AWS CLI via `saml2aws login --force` | `profile` (optional) |
391
+
392
+ ---
393
+
394
+ ## Built-in packages
395
+
396
+ ### Core
397
+
398
+ These are the foundation tools — install them on every machine.
399
+
400
+ | Key | Name | Description | Help |
401
+ |-----|------|-------------|------|
402
+ | `docker` | Docker | Container runtime + docker compose plugin | `docker --help` |
403
+ | `nvm` | NVM + Node LTS | Node Version Manager + latest Node LTS | `nvm help` |
404
+ | `uv` | uv | Astral Python package and project manager | `uv --help` |
405
+
406
+ ### Tools
407
+
408
+ Optional utilities you may want on some machines.
409
+
410
+ | Key | Name | Description | Help |
411
+ |-----|------|-------------|------|
412
+ | `aws` | AWS CLI | Amazon Web Services CLI v2 | `aws help` |
413
+ | `eza` | eza | Modern ls replacement with git status, icons, and tree view | `eza --help` |
414
+ | `gh` | GitHub CLI | GitHub's official CLI | `gh --help` |
415
+ | `htop` | htop | Interactive process and resource monitor | `man htop` |
416
+ | `mkcert` | mkcert | Zero-config local HTTPS certificates | `mkcert --help` |
417
+ | `ollama` | Ollama | Run large language models locally | `ollama --help` |
418
+ | `php` | PHP 8.4 | PHP 8.4 + common extensions via ondrej/php PPA | `php --help` |
419
+ | `pi` | Pi Coding Agent | AI coding agent npm package | `pi --help` |
420
+ | `saml2aws` | saml2aws | SAML → AWS STS credentials CLI (Versent) | `saml2aws --help` |
421
+ | `starship` | Starship | Fast, cross-shell customizable prompt | `starship --help` |
422
+ | `yq` | yq | Portable command-line YAML/JSON/XML processor | `yq --help` |
423
+
424
+ ### Languages
425
+
426
+ | Key | Name | Description | Help |
427
+ |-----|------|-------------|------|
428
+ | `go` | Go | Go programming language toolchain | `go help` |
429
+ | `java` | Java 21 (OpenJDK) | OpenJDK 21 LTS - JDK and JRE | `java --help` |
430
+ | `ruby` | Ruby (rbenv) | Ruby via rbenv version manager + ruby-build | `ruby --version` |
431
+
432
+ ---
433
+
434
+ ## Custom packages
435
+
436
+ Custom packages live in `~/.config/dev-setup/tools.yaml`. You can create them via `devstuff add`, import them with `devstuff catalog import`, or edit the YAML by hand.
437
+
438
+ ### YAML schema
439
+
440
+ ```yaml
441
+ version: 1
442
+ tools:
443
+ my-tool:
444
+ name: My Tool
445
+ description: Does something useful
446
+ category: custom
447
+ type: bash
448
+ check_cmd: my-tool
449
+ help_cmd: my-tool --help
450
+ docs_url: https://example.com/docs
451
+ requires: []
452
+ install_script: |
453
+ set -euo pipefail
454
+ curl -fsSL https://example.com/install.sh | sh
455
+ remove_script: |
456
+ rm -f "$HOME/.local/bin/my-tool"
457
+ ```
458
+
459
+ ### YAML fields
460
+
461
+ | Field | Required | Description |
462
+ |-------|----------|-------------|
463
+ | `name` | yes | Display name shown in `list` |
464
+ | `description` | no | Short description shown in `list` |
465
+ | `category` | no | `custom` (default), `core`, `tools`, or `languages` |
466
+ | `type` | yes | `npm`, `pip`, `uvx`, `apt`, `git`, `script`, or `bash` |
467
+ | `check_cmd` | no | Binary name or shell check used to detect install status |
468
+ | `help_cmd` | no | Command shown in `list` under the package entry |
469
+ | `docs_url` | no | URL opened by `devstuff docs <key>` |
470
+ | `requires` | no | List of package keys that must already be installed |
471
+ | `npm_name` | npm | npm package name |
472
+ | `pip_name` | pip | PyPI package name |
473
+ | `apt_packages` | apt | Space-separated list of apt packages |
474
+ | `git_url` | git | Repository URL to clone |
475
+ | `git_install_cmd` | git | Bash command run inside the cloned repo after clone |
476
+ | `git_remove_cmd` | git | Bash command run inside the repo before deletion |
477
+ | `script_url` | script | URL passed to `curl -fsSL … \| sh` |
478
+ | `install_script` | bash | Full bash script to run on install |
479
+ | `remove_script` | bash | Full bash script to run on remove |
480
+
481
+ Unknown fields fail validation. `requires` defaults to `["nvm"]` for `npm` tools and `["uv"]` for `pip`/`uvx` tools unless explicitly set.
482
+
483
+ ### Examples
484
+
485
+ **npm package:**
486
+ ```yaml
487
+ version: 1
488
+ tools:
489
+ prettier:
490
+ name: Prettier
491
+ description: Opinionated code formatter
492
+ type: npm
493
+ npm_name: prettier
494
+ check_cmd: prettier
495
+ help_cmd: prettier --help
496
+ ```
497
+
498
+ **uvx/PyPI package:**
499
+ ```yaml
500
+ version: 1
501
+ tools:
502
+ httpie:
503
+ name: httpie
504
+ description: Human-friendly HTTP client
505
+ type: uvx
506
+ pip_name: httpie
507
+ check_cmd: http
508
+ help_cmd: http --help
509
+ ```
510
+
511
+ **apt package:**
512
+ ```yaml
513
+ version: 1
514
+ tools:
515
+ ripgrep:
516
+ name: ripgrep
517
+ description: Fast recursive search tool
518
+ type: apt
519
+ apt_packages: ripgrep
520
+ check_cmd: rg
521
+ help_cmd: rg --help
522
+ ```
523
+
524
+ **Multi-step bash install:**
525
+ ```yaml
526
+ version: 1
527
+ tools:
528
+ saml2aws-custom:
529
+ name: saml2aws (custom)
530
+ description: SAML-to-AWS credential helper
531
+ type: bash
532
+ check_cmd: saml2aws
533
+ help_cmd: saml2aws --help
534
+ install_script: |
535
+ set -euo pipefail
536
+ VER=$(curl -s https://api.github.com/repos/Versent/saml2aws/releases/latest | grep tag_name | cut -d'v' -f2 | cut -d'"' -f1)
537
+ curl -fsSL "https://github.com/Versent/saml2aws/releases/download/v${VER}/saml2aws_${VER}_linux_amd64.tar.gz" | tar -xz -C /tmp
538
+ sudo mv /tmp/saml2aws /usr/local/bin/saml2aws
539
+ sudo chmod +x /usr/local/bin/saml2aws
540
+ remove_script: |
541
+ sudo rm -f /usr/local/bin/saml2aws
542
+ ```
543
+
544
+ ---
545
+
546
+ ## Architecture
547
+
548
+ ```
549
+ dev-setup-py/
550
+ ├── dev-setup # Bash entry point — bootstraps uv, then exec's Python
551
+ ├── install.sh # Installs devstuff and exposes the devstuff command
552
+ ├── pyproject.toml # Python project (hatchling, requires-python >=3.11)
553
+ └── src/
554
+ └── dev_setup/
555
+ ├── __main__.py # python -m dev_setup entry point
556
+ ├── cli.py # Click group, command registration
557
+ ├── base.py # Tool ABC, patch_bashrc / remove_bashrc_block utilities
558
+ ├── catalog.py # YAML catalog loading, validation, migration, import/export
559
+ ├── registry.py # Loads bundled + user YAML into the live tool registry
560
+ ├── generic.py # GenericTool - handles all catalog install types
561
+ ├── tools.yaml # Bundled built-in tool catalog
562
+ ├── functions_catalog.py # YAML catalog loading/validation for functions.yaml
563
+ ├── functions_registry.py # Loads bundled + user YAML into the live function registry
564
+ ├── function_runner.py # Param resolution + script/eval/bashrc rendering & execution
565
+ ├── functions.yaml # Bundled built-in function catalog
566
+ ├── ui.py # Rich console helpers, questionary wrappers, styled prompts
567
+ ├── commands/
568
+ │ ├── list_cmd.py
569
+ │ ├── install_cmd.py
570
+ │ ├── remove_cmd.py
571
+ │ ├── update_cmd.py
572
+ │ ├── add_cmd.py
573
+ │ ├── delete_cmd.py
574
+ │ ├── catalog_cmd.py
575
+ │ ├── run_cmd.py
576
+ │ └── functions_cmd.py
577
+ ```
578
+
579
+ ### Adding a new built-in tool
580
+
581
+ Add an entry to `src/dev_setup/tools.yaml`. Built-ins use the same schema as user tools, with `category` set to `core`, `tools`, or `languages`.
582
+
583
+ ```yaml
584
+ mytool:
585
+ name: My Tool
586
+ description: Does something useful
587
+ category: tools
588
+ type: bash
589
+ check_cmd: mytool
590
+ help_cmd: mytool --help
591
+ docs_url: https://example.com/docs
592
+ install_script: |
593
+ set -euo pipefail
594
+ curl -fsSL https://example.com/install.sh | sh
595
+ remove_script: |
596
+ sudo rm -f /usr/local/bin/mytool
597
+ ```
598
+
599
+ ### Key design decisions
600
+
601
+ - **uv owns Python provisioning.** The bash wrapper only guarantees uv is present; Python version and virtualenv management is delegated entirely to `uv run`.
602
+ - **Catalogs are the source of truth.** Bundled YAML loads first, then user YAML overrides matching keys and appends new tools.
603
+ - **Tool execution is generic.** The Python engine handles npm, uvx/pip, apt, git, script URLs, and bash scripts from catalog metadata.
604
+ - **Custom packages are plain YAML.** Scripts are stored as strings and written to a temp file at install time, giving bash full parsing fidelity.
605
+ - **`install()` raises on failure.** Tools raise `RuntimeError` or `subprocess.CalledProcessError`; command handlers catch and report them. No `InstallResult` enum to check.
606
+ - **Invalid catalogs fail visibly.** Malformed YAML, unsupported versions, bad keys, unknown fields, and invalid `requires` values raise clear load errors.
607
+
608
+ ---
609
+
610
+ ## Dependencies
611
+
612
+ | Package | Version | Purpose |
613
+ |---------|---------|---------|
614
+ | `click` | ≥ 8.1 | CLI command dispatch, `--help` generation, editor integration |
615
+ | `PyYAML` | ≥ 6.0 | Tool catalog parsing and writing |
616
+ | `rich` | ≥ 13.0 | Terminal UI — panels, tables, spinners, styled text |
617
+ | `questionary` | ≥ 2.0 | Interactive prompts — multi-select, confirm, text input |
@@ -0,0 +1,30 @@
1
+ dev_setup/__init__.py,sha256=BfTc-iAf16B_sxLK1PM3P7QlMGy7k33ColMK0o6KkdA,158
2
+ dev_setup/__main__.py,sha256=w-Vnqe3bgAw_UNlPywPkbOqoFKcEk2H2S79wrQjXvU4,102
3
+ dev_setup/base.py,sha256=j2EQ5gzeGgtveWQN_BgbLcZianMENJ7PQy8EQ9J9MPE,1946
4
+ dev_setup/catalog.py,sha256=nwsere81V_XN3FOjm-KkoFeDZQNDFHncn2qXU2KvVfA,5515
5
+ dev_setup/cli.py,sha256=oyPXtcwUV6byuR-rrgexZozGcRc1YILugCglzbdYTuY,1579
6
+ dev_setup/function_runner.py,sha256=2Jk4FjdHuj4olRnLNc_WqMen-KBz0aTS6t82XBu8IaM,5179
7
+ dev_setup/functions.schema.json,sha256=GgvBR7_mPE7u_L7hotWg1hlG8HuqzlFBCBXw5hYKANE,6221
8
+ dev_setup/functions.yaml,sha256=q3JE8g-iG64tbJ4dgvEq7o5SbNbJ8Fh__mVVR3GJIWc,3425
9
+ dev_setup/functions_catalog.py,sha256=YgR2hY9HM1iol1AZcF-_j02EXCP9U4P3e_5eWes9KH0,7116
10
+ dev_setup/functions_registry.py,sha256=YSl-VgNXPf0hj4WgReg-pZUj4fAjFlwvC165dgon_BE,3682
11
+ dev_setup/generic.py,sha256=zhJrC33mXy7stDaHlOBD0euTVojW-xs9yp1iFSENpVY,24021
12
+ dev_setup/registry.py,sha256=8lrk6EXCCWk1WNeNnCGLTJ-v8rpCs7-TLYtVXgiuxnA,2243
13
+ dev_setup/tools.yaml,sha256=U2k6FV4n3fYkH5iS7tZYZO_j5DG3TFQ7QzjSJZ8Z_mo,23691
14
+ dev_setup/ui.py,sha256=baW9D_0VvGIhWt0K9OIORg0l9q5CiDmdzjyqWuFk5AI,2975
15
+ dev_setup/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ dev_setup/commands/add_cmd.py,sha256=rBdPoY6DiMLz26MewXE-lobepOYhe-55bA8GP4hrx9w,11666
17
+ dev_setup/commands/catalog_cmd.py,sha256=s-2TYhe8LOunSF56EhoTDx7X_1vJPfqqI0Dy1jUkzjY,1003
18
+ dev_setup/commands/delete_cmd.py,sha256=j_-fr2RMaeX3sMhH-7wJP5KC9Yvpgbb9KIeEEyG9ODQ,995
19
+ dev_setup/commands/docs_cmd.py,sha256=1PtpwdFO3LrAxG3HyCLFn5SXVnnwqcJ8K_c9cVd8Phc,940
20
+ dev_setup/commands/functions_cmd.py,sha256=D9JRYMRavXbROz0XRGjHRHeFvZY-GKyvRCctJODQDBE,2856
21
+ dev_setup/commands/help_cmd.py,sha256=TYfYe5qMA99-9Zm6dTnBTQ_aB3WmOuHvX25kTPG-l0w,2663
22
+ dev_setup/commands/install_cmd.py,sha256=6bfEJz1ySeAJpHKxkmMcBNhlw_HncZEvMCFD_iW_kJk,4167
23
+ dev_setup/commands/list_cmd.py,sha256=-BAywXxpSm4-VAlysLzlDwIqvmk_zBKhmzEObM8jigo,2847
24
+ dev_setup/commands/remove_cmd.py,sha256=5xCCN6zlaP5KCfOl6GKbSbWC08QD9zkQ1MN1X4AKaLw,1414
25
+ dev_setup/commands/run_cmd.py,sha256=1m4ktiPNm6joZ3xFkSFve6-LppcyRybOLrwtANeqW10,2467
26
+ dev_setup/commands/update_cmd.py,sha256=TcO0CFjaL9sardwpJ83OkBAs-E1is8yfVMLN80ylqCI,5045
27
+ devstuff-1.13.1.dist-info/METADATA,sha256=w2OaI7hieVFpE3B1Ipxy-Al3QO5Y3QqZNqEd0_9Q0Vw,24936
28
+ devstuff-1.13.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
29
+ devstuff-1.13.1.dist-info/entry_points.txt,sha256=qrFaFztiik3a3VhItpmbcJhWdoNKFKe1c2JSSU99iMk,89
30
+ devstuff-1.13.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ dev-setup = dev_setup.__main__:main
3
+ devstuff = dev_setup.__main__:main