dev-prune-darwin-arm64 1.20.0 → 1.22.0
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.
- package/README.md +138 -165
- package/bin/dev-prune +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,13 +52,15 @@ gigabytes hostage for a build you are not running.
|
|
|
52
52
|
|
|
53
53
|
`dev-prune` finds those directories across every Git repository you register, and deletes
|
|
54
54
|
them — but only after proving the exact command that puts them back would succeed. It
|
|
55
|
-
knows
|
|
56
|
-
CocoaPods and Terraform are as first-class as npm and pip. It is
|
|
57
|
-
installs its own background schedule, and answers to two names
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
knows thirty-five package managers, not just the obvious four: Composer, Bundler, Mix,
|
|
56
|
+
CocoaPods and Terraform are as first-class as npm and pip. It is one Rust program,
|
|
57
|
+
installs its own background schedule, and answers to two names you type — `dev-prune` and
|
|
58
|
+
`devp` — alongside a third, windowless build, `devpw`, that exists only so the Windows
|
|
59
|
+
scheduled task runs without flashing up a console.
|
|
60
|
+
|
|
61
|
+
Deleting is only half of it. The same binary puts everything back (`devp restore
|
|
62
|
+
--last-run`), sizes and clears the caches those package managers keep *outside* your
|
|
63
|
+
projects (`devp caches`), reports what Docker is holding (`devp caches docker`), and shows
|
|
62
64
|
where the disk actually went, drive by drive (`devp status`, `devp stats`). One tool for
|
|
63
65
|
every dependency directory on the machine, instead of one command per ecosystem and a
|
|
64
66
|
mental note about which ones are safe.
|
|
@@ -322,7 +324,7 @@ so they are worth copying rather than typing.
|
|
|
322
324
|
| Where | Published as | What you get |
|
|
323
325
|
|---|---|---|
|
|
324
326
|
| [crates.io](https://crates.io/crates/dev-prune) | **`dev-prune`** | Source. `cargo install` compiles it; `cargo binstall` fetches the release archive instead. |
|
|
325
|
-
| [PyPI](https://pypi.org/project/dev-prune/) | **`dev-prune`** |
|
|
327
|
+
| [PyPI](https://pypi.org/project/dev-prune/) | **`dev-prune`** | Seven wheels, each containing the binary. `pip`, `pipx`, `uv tool`. |
|
|
326
328
|
| [npm](https://www.npmjs.com/package/dev-prune) | **`dev-prune`** | A dispatcher plus seven platform packages; npm installs the one matching your machine. |
|
|
327
329
|
| [GitHub Releases](https://github.com/Life-Experimentalist/dev-prune/releases) | `dev-prune-v<ver>-<platform>` | Seven checksummed, provenance-attested archives. What the install scripts fetch. |
|
|
328
330
|
| [Homebrew](https://github.com/Life-Experimentalist/homebrew-tap) | **`Life-Experimentalist/tap`** | A one-formula tap, so `brew upgrade` keeps finding new versions. |
|
|
@@ -367,7 +369,7 @@ devp history # which pass reclaimed it, and what started that pas
|
|
|
367
369
|
devp history --pass 1 # the exact command line, and every directory it took
|
|
368
370
|
devp caches # every package manager cache, sized. The report deletes nothing
|
|
369
371
|
devp caches docker # what Docker holds, and the prune commands
|
|
370
|
-
devp caches clear docker # run the narrow ones —
|
|
372
|
+
devp caches clear docker # run the narrow ones — no volume unless you name it, never on a schedule
|
|
371
373
|
devp status --drift # anything installed that the lockfiles don't record?
|
|
372
374
|
devp doctor . # why is this repository not being pruned?
|
|
373
375
|
devp doctor --fix # repair a broken integration — never a first-time install
|
|
@@ -381,93 +383,53 @@ devp -V # version, OS, architecture, config path, PATH audit
|
|
|
381
383
|
<details open>
|
|
382
384
|
<summary><b><code>devp run --dry-run</code></b> — the plan, before anything is touched</summary>
|
|
383
385
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
386
|
+
`--dry-run` scans every registered repository and prints the pass it *would* make, then
|
|
387
|
+
stops without touching anything. Each candidate is one line: the repository, the
|
|
388
|
+
directory as a path relative to that repository's root, the directory's size, and in
|
|
389
|
+
brackets the adapter that claimed it — `[pnpm]`, `[uv]`, `[cargo]`, `[go]`. A repository
|
|
390
|
+
that is being skipped says so on its own line, with the reason it was skipped.
|
|
391
|
+
The summary at the end is the total those lines add up to and the number of directories
|
|
392
|
+
behind it.
|
|
389
393
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
→ • ~/Code/render-farm → target (2.14 GiB) [cargo]
|
|
394
|
-
→ • ~/Code/edge-proxy → vendor (96.4 MiB) [go]
|
|
395
|
-
|
|
396
|
-
Summary (Dry Run)
|
|
397
|
-
→ Would free 2.82 GiB across 4 bloat directories.
|
|
398
|
-
```
|
|
394
|
+
There is no figure this README can put in that summary for you. It is the size of *your*
|
|
395
|
+
`node_modules`, and this repository holds no measurement that would make a number here
|
|
396
|
+
mean anything about your disk — so run it and read your own.
|
|
399
397
|
|
|
400
398
|
</details>
|
|
401
399
|
|
|
402
400
|
<details>
|
|
403
401
|
<summary><b><code>devp status</code></b> — the dashboard, or a plain table with no TTY</summary>
|
|
404
402
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
dev-prune status
|
|
416
|
-
|
|
417
|
-
# Repository Status / Reason Adapters Bloat Last Activity Last Pruned
|
|
418
|
-
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
419
|
-
1 acme-api Candidate pnpm+uv 600.9 MiB 2026-04-02 Never
|
|
420
|
-
2 render-farm Candidate cargo 2.14 GiB 2026-03-11 2026-01-08
|
|
421
|
-
3 edge-proxy Candidate go 96.4 MiB 2026-05-19 Never
|
|
422
|
-
4 dashboard Active (not idle) npm 314.0 MiB 2026-08-12 2026-06-30
|
|
423
|
-
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
424
|
-
→ Total: 4 repos | 3 candidates | 3.13 GiB reclaimable
|
|
425
|
-
```
|
|
403
|
+
The header states the facts about the installation itself: where the registry file lives,
|
|
404
|
+
whether the OS daemon and the Git hooks are installed, the global command timeout, how
|
|
405
|
+
many repositories are tracked, and the lifetime total already reclaimed together with the
|
|
406
|
+
number of prune passes that produced it.
|
|
407
|
+
|
|
408
|
+
Below it, one row per repository — an index, its name, its status and, when it is being
|
|
409
|
+
skipped, the reason for that; the adapters that detected
|
|
410
|
+
it; the size of the bloat it is holding; the date of its last activity; and when it was
|
|
411
|
+
last pruned. The footer totals the repositories, how many of them are candidates, and how
|
|
412
|
+
much is reclaimable right now.
|
|
426
413
|
|
|
427
|
-
|
|
428
|
-
keeping, `Enter` prunes the rest, `i` toggles ignore for
|
|
414
|
+
With a TTY the table is interactive: `↑`/`↓` move, `p` pre-selects every candidate,
|
|
415
|
+
`Space` deselects the one you are keeping, `Enter` prunes the rest, `i` toggles ignore for
|
|
416
|
+
a repository, `q` exits. Without one, the same table is printed and the command exits.
|
|
429
417
|
|
|
430
418
|
</details>
|
|
431
419
|
|
|
432
420
|
<details>
|
|
433
421
|
<summary><b><code>devp caches</code></b> — where the rest of the disk went</summary>
|
|
434
422
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
npm cache 9.98 GiB ~/.npm
|
|
441
|
-
clear: npm cache clean --force
|
|
442
|
-
npm is used by 18 of 46 registered repositories · 567.75 MiB each
|
|
443
|
-
|
|
444
|
-
uv cache 6.22 GiB ~/.cache/uv
|
|
445
|
-
clear: uv cache prune
|
|
446
|
-
uv is used by 7 of 46 registered repositories · 909.77 MiB each
|
|
447
|
-
|
|
448
|
-
pnpm store 2.07 GiB /mnt/data/.pnpm-store
|
|
449
|
-
clear: pnpm store prune --store-dir /mnt/data/.pnpm-store
|
|
450
|
-
one store per filesystem, because a hardlink into node_modules cannot cross one
|
|
451
|
-
pnpm is used by 1 of 46 registered repositories · 2.09 GiB each
|
|
452
|
-
|
|
453
|
-
nuget global packages 1.44 GiB ~/.nuget/packages
|
|
454
|
-
clear: dotnet nuget locals global-packages --clear
|
|
455
|
-
every .NET project on the machine restores from here; re-downloaded on the next restore
|
|
456
|
-
|
|
457
|
-
… (pip, bun, both go caches, gradle wrapper distributions, both cargo
|
|
458
|
-
registry caches, and the pnpm store beside your home directory)
|
|
459
|
-
|
|
460
|
-
Total 21.99 GiB across 12 caches
|
|
461
|
-
|
|
462
|
-
→ Nothing above was deleted, and dev-prune never deletes any of it.
|
|
463
|
-
|
|
464
|
-
Container engines
|
|
423
|
+
One row per package-manager cache and store found on the machine, largest first. Each
|
|
424
|
+
carries the manager's name, the size, the path it was found at, the exact command that
|
|
425
|
+
clears it, and — for the managers that are also adapter names — how many of your
|
|
426
|
+
registered repositories use it and what the cache works out to per repository. A total
|
|
427
|
+
closes the table, and the report ends by saying out loud that nothing in it was deleted.
|
|
465
428
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
```
|
|
429
|
+
Container engines are listed after that total rather than inside it, each on one line with
|
|
430
|
+
what the engine itself calls reclaimable and the `devp caches docker` that breaks it down.
|
|
431
|
+
They are kept out of the package-manager total deliberately: images, volumes and build
|
|
432
|
+
cache are a different kind of thing, and dev-prune never deletes any of them.
|
|
471
433
|
|
|
472
434
|
A cache lives outside every repository and is shared by all of them, so no single
|
|
473
435
|
lockfile can prove it recoverable — and it is what makes `devp restore` fast. `devp
|
|
@@ -486,62 +448,64 @@ a registered repository, and each such row names its store in the command it pri
|
|
|
486
448
|
<details>
|
|
487
449
|
<summary><b><code>devp caches docker</code></b> — the engine that is usually bigger than all of them</summary>
|
|
488
450
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
An image has no lockfile to prove it can be rebuilt, and a named volume is the one thing
|
|
512
|
-
here that cannot be rebuilt at all — so this command measures, prints the commands, and
|
|
513
|
-
leaves the decision with you.
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
Clearing 6 GiB of npm cache while a Docker install nobody has looked at in a year sits on
|
|
517
|
-
40 GiB is the mistake this exists to prevent. `devp caches podman`, `devp caches
|
|
518
|
-
nerdctl`, `devp caches finch` and `devp caches containers container` — Apple's engine, on
|
|
519
|
-
Apple silicon — are the same report for those engines, and `devp caches containers` runs
|
|
520
|
-
every one it finds and lists any local Kubernetes clusters (kind, k3d, minikube) by name.
|
|
451
|
+
Four rows — Images, Containers, Local Volumes, Build Cache — each with its size, how much
|
|
452
|
+
of that size the engine itself calls reclaimable, and how many items it holds against how
|
|
453
|
+
many are in use. A total closes them.
|
|
454
|
+
|
|
455
|
+
Under the table, the prune commands, narrowest first, each paired with what it takes with
|
|
456
|
+
it: `docker builder prune` (the build cache; costs a slower next build), `docker image
|
|
457
|
+
prune` (dangling images no tag points at any more), `docker container prune` (stopped
|
|
458
|
+
containers and each writable layer), `docker system prune` (the three at once, volumes
|
|
459
|
+
untouched) and `docker system prune --volumes`, the one that deletes data.
|
|
460
|
+
|
|
461
|
+
Nothing in that report is deleted, and nothing dev-prune runs on a schedule ever will. An
|
|
462
|
+
image has no lockfile to prove it can be rebuilt, and a named volume is the one thing here
|
|
463
|
+
that cannot be rebuilt at all — so this command measures, prints the commands, and leaves
|
|
464
|
+
the decision with you.
|
|
465
|
+
|
|
466
|
+
Clearing the npm cache while a Docker install nobody has looked at in a year sits on many
|
|
467
|
+
times more is the mistake this exists to prevent. `devp caches podman` is the same report
|
|
468
|
+
for Podman; `devp caches containers nerdctl`, `devp caches containers finch` and `devp
|
|
469
|
+
caches containers container` — Apple's engine, on Apple silicon — are the same report for
|
|
470
|
+
those, the engine being an argument to `containers` rather than a subcommand of its own;
|
|
471
|
+
and `devp caches containers` on its own runs every engine it finds and lists any local
|
|
472
|
+
Kubernetes clusters (kind, k3d, minikube) by name.
|
|
521
473
|
|
|
522
474
|
**The report deletes nothing, and nothing on a schedule ever will** — no daemon, no Git
|
|
523
475
|
hook and no `devp run` path reaches container disk, with or without `--yes`. What used to
|
|
524
476
|
end there now has a second half: `devp caches clear docker` runs the narrow commands for
|
|
525
477
|
you — `builder prune -a -f`, `image prune -a -f`, `container prune -f` — after printing
|
|
526
478
|
them and asking, and counts what came back on its own line in `devp stats`. Printing four
|
|
527
|
-
commands and asking you to go and type one in another window meant
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
a
|
|
536
|
-
|
|
537
|
-
|
|
479
|
+
commands and asking you to go and type one in another window meant whatever you reclaimed
|
|
480
|
+
on its advice was yours to have remembered, and dev-prune could not account for it.
|
|
481
|
+
|
|
482
|
+
**It will not bulk-delete volumes, and no flag makes it.** No argument in the reclaim
|
|
483
|
+
table contains the word volume, a unit test fails the build if one appears, and dev-prune
|
|
484
|
+
never runs `volume prune` or `system prune --volumes`. That is a different promise from
|
|
485
|
+
the lockfile rule: an image can be pulled again and a build cache rebuilt, so those are a
|
|
486
|
+
question of consent and the prompt is the consent. What is inside a volume is the only
|
|
487
|
+
copy, so a volume goes only when someone names it. That naming has a spelling now:
|
|
488
|
+
`devp caches clear docker --include-volumes` (docker and podman) lists the unused
|
|
489
|
+
volumes by name after the narrow steps run and you type the numbers of the ones to
|
|
490
|
+
delete, each pick one unforced `volume rm`. It refuses `--yes`, `--json` and a piped
|
|
491
|
+
stdin, so no script or scheduler can reach it. The one unattended spelling is
|
|
492
|
+
`--include-volumes --dry-run`, which deletes nothing: it lists the unused volumes by
|
|
493
|
+
name with the command to paste, so an agent can prepare everything and a person runs
|
|
494
|
+
the final command at a terminal, and what the picks free is then counted on
|
|
495
|
+
`devp stats`, which a `volume rm` typed straight at the engine would not be. The pick
|
|
496
|
+
list arms only within ten minutes of a completed dry run for that engine: typed cold,
|
|
497
|
+
the real command runs the dry run instead and says so, and the same line typed again
|
|
498
|
+
within ten minutes reaches the picking. Without
|
|
499
|
+
the flag, the estimate still
|
|
500
|
+
says how much unused-volume space is being left alone rather than folding it into a
|
|
501
|
+
number these commands cannot deliver.
|
|
538
502
|
|
|
539
503
|
The figures come from the engine's own `system df`, not a walk of the disk. On Docker
|
|
540
504
|
Desktop and Podman the store lives inside a VM disk image the host filesystem cannot see,
|
|
541
505
|
so a size taken off the disk would be wrong by orders of magnitude in the reassuring
|
|
542
506
|
direction — and asking is the only way to learn what is *reclaimable*, which is the
|
|
543
|
-
figure that decides anything.
|
|
544
|
-
situation from
|
|
507
|
+
figure that decides anything. A store that is almost entirely dangling images is a
|
|
508
|
+
different situation from one the same size with almost nothing reclaimable in it.
|
|
545
509
|
|
|
546
510
|
An engine that is installed with its daemon stopped is reported as exactly that, quoting
|
|
547
511
|
the engine's own first line, and contributes no figures: a blank, not a zero. An engine
|
|
@@ -555,30 +519,18 @@ the same gigabytes counted twice.
|
|
|
555
519
|
<details>
|
|
556
520
|
<summary><b><code>devp doctor .</code></b> — the one reason a repository is being skipped</summary>
|
|
557
521
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
522
|
+
Three sections and a verdict. **Repository** answers whether the path is a Git repository,
|
|
523
|
+
whether it is registered and since when, whether a `.devprune.json` was found and what it
|
|
524
|
+
sets, whether an opt-out applies, the last activity date against the idle threshold in
|
|
525
|
+
force, the size floor, and the scan depth.
|
|
562
526
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
.devprune.json parses; idle_days 20
|
|
567
|
-
Opt-out none
|
|
568
|
-
Activity 2026-08-12 (0 days ago), threshold 20 — active
|
|
569
|
-
Size floor none — every recognised directory counts
|
|
570
|
-
Scan depth 6 levels below the root
|
|
527
|
+
**Projects** lists every project found below the root by its repository-relative path with
|
|
528
|
+
the adapter that claimed it, and under each one whether the lockfile is present and which
|
|
529
|
+
bloat directories that adapter owns, sized.
|
|
571
530
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
Lockfile ✓ package-lock.json present
|
|
576
|
-
Bloat ✓ node_modules (314.0 MiB)
|
|
577
|
-
|
|
578
|
-
Verdict
|
|
579
|
-
✗ Would `devp run` prune this? No — active within the last 20 days.
|
|
580
|
-
`devp --ignore-idle run ~/Code/dashboard` overrides exactly that check and nothing else.
|
|
581
|
-
```
|
|
531
|
+
**Verdict** is a single line — would `devp run` prune this, yes or no — and when the answer
|
|
532
|
+
is no, the one check that said so and the exact command that overrides that check and
|
|
533
|
+
nothing else.
|
|
582
534
|
|
|
583
535
|
It runs no package manager and repairs nothing, so it is safe to run twice — once to see
|
|
584
536
|
the problem, once to confirm the fix. Without a path it audits the installation instead:
|
|
@@ -625,12 +577,12 @@ process that leaves a dirty working tree is a surprise.
|
|
|
625
577
|
| 🧩 **Any number of ecosystems per repository** | uv, npm and cargo in one root, or spread across `frontend/`, `services/api/` and `tools/cli/` — each discovered, verified and pruned on its own terms |
|
|
626
578
|
| ↩️ **One-command restore** | `devp restore .` reinstalls a tree; `devp restore --last-run` puts back exactly what the most recent pass deleted, across every repository it touched |
|
|
627
579
|
| 🕒 **Activity-aware** | Combines `git log` timestamps with source-file `mtime`, so uncommitted work protects a repository just as a commit does |
|
|
628
|
-
| 🐳 **Container report** | `devp caches docker` (also `podman`, `nerdctl`, `finch
|
|
580
|
+
| 🐳 **Container report** | `devp caches docker` (also `devp caches podman`, and `devp caches containers <engine>` for `nerdctl`, `finch` or Apple's `container` — the engine name is an argument to `containers`, never a subcommand of its own — or `devp caches containers` on its own for every engine it finds plus local Kubernetes clusters) breaks a container engine's disk into images, containers, local volumes and build cache, each with what the engine itself calls reclaimable, and prints the prune commands narrowest first with what each takes with it. `devp caches clear docker` then runs the narrow ones for you, after asking, and counts them in `devp stats` — **no volume unless you pick it by name** (`--include-volumes`, a terminal-only list you choose from, one unforced `volume rm` per pick, never `volume prune`), and never from a scheduler or a hook. `devp caches` carries a one-line summary per engine, outside its own total |
|
|
629
581
|
| 📊 **Cache report** | `devp caches` sizes every package manager cache and store on the machine — npm to cargo to conda, Maven, Gradle, NuGet, vcpkg, Conan, Composer, CocoaPods, Hex, Bundler, pub, SwiftPM, Terraform, Poetry, PDM and Deno — and prints the command that clears each. It also finds the stores that belong to no package manager at all and are routinely the largest things in the list: the Playwright and Puppeteer browser bundles, the Cypress binary cache, the Electron and electron-builder download caches, and the HuggingFace hub — a whole browser or model per version, and nothing ever removes the old one. The report is read-only; `devp caches clear <manager>` runs that command for you, after asking. `devp config set cache_max_gb default=10` says how big is too big — for every manager at once, or per manager with `default=10,npm=4` — and marks the ones past it — `devp caches clear --over-cap all` then empties exactly those, still only when you type it. Each manager also says how many of your registered repositories use it and what that works out to per repository, and `devp caches clear --unused all` empties the ones nothing uses at all. pnpm is reported once per filesystem, because a store it hardlinks into `node_modules` cannot cross one and projects kept off the system disk get a store of their own. Nothing on a schedule ever touches a cache, and Maven's `~/.m2/repository` is never cleared at all — it holds artifacts `mvn install:install-file` put there that no remote can hand back |
|
|
630
582
|
| 🩺 **`devp doctor`** | One read-only pass that ends by naming the *single* reason a repository would or would not be pruned. Runs no package manager, repairs nothing, safe to run twice. `devp doctor --fix` then mends what it found — installed-but-broken only |
|
|
631
583
|
| 🤖 **Self-installing automation** | OS-native scheduler (Task Scheduler, LaunchAgent, systemd user timer) and non-blocking Git hooks, installed once the first run’s walkthrough is accepted (quitting it installs nothing) and restored after an upgrade. `auto_setup`, `auto_hooks`, `auto_daemon` or `DEV_PRUNE_NO_AUTO_SETUP=1` turn it off |
|
|
632
584
|
| ⚡ **0ms opt-out** | An `ignore.devprune.json` in a repository root is honoured by file presence alone — no read, no parse. It applies at registration as well: a bulk scan (`devp init`, and the scheduled pass's own discovery) will not register a repository that holds it, so a repository can decline before it ever reaches `devp status`. `devp link <path>` still registers one, because naming a single repository is not a bulk scan |
|
|
633
|
-
| 🔌 **`--json` on every reporting command** | `run`, `status`, `stats`, `trust` and `caches` each emit one versioned document on stdout, diagnostics on stderr. Built for scripts and agents |
|
|
585
|
+
| 🔌 **`--json` on every reporting command** | `run`, `status`, `stats`, `history`, `trust` and `caches` each emit one versioned document on stdout, diagnostics on stderr. Built for scripts and agents |
|
|
634
586
|
| 🧠 **AI agent skill** | A token-lean `SKILL.md` embedded in the binary; `devp skill` exports it and prints onboarding prompts for Claude Code, Gemini Antigravity, Cursor, Windsurf, Copilot and OpenClaw, and the repository doubles as a Claude Code plugin marketplace |
|
|
635
587
|
| 🧰 **Editor extension** | Validates `.devprune.json` as you type and shows the workspace's reclaimable size in the status bar. `devp setup` offers to install it — once, only at a terminal — into VS Code, VSCodium, Cursor, Windsurf, Positron or Kiro, each from its own registry, falling back to the `.vsix` from the extension's own release. [docs/IDE_INTEGRATION.md](docs/IDE_INTEGRATION.md) |
|
|
636
588
|
| 🖼️ **File manager icons** | `devp icon` registers `*.devprune.json` with the OS file manager — a real `shared-mime-info` type plus hicolor icons on Linux, a folder icon on Windows. It never edits your editor settings, `PATH` or shell startup files |
|
|
@@ -653,7 +605,7 @@ process that leaves a dirty working tree is a surprise.
|
|
|
653
605
|
| `devp history` | `--pass N`, `--limit N`, `--all`, `--json`, `--export [PATH]` | Which pass deleted what, and what asked it to — one line per pass, then `--pass N` for the command line that ran it and every directory it removed. `--export` writes the lot to your documents folder |
|
|
654
606
|
| `devp completions` | `bash`, `zsh`, `fish`, `powershell`, `elvish` | Prints a shell completion script to stdout, generated from the same argument definitions the binary parses with |
|
|
655
607
|
| `devp caches` | `clear <manager\|all>`, `--json` | Sizes every package manager cache on the machine and prints the command that clears each. The report deletes nothing and nothing on a schedule ever will; `clear` empties one when you type it, after asking |
|
|
656
|
-
| `devp caches docker` | `podman`, `nerdctl`, `finch`, `container
|
|
608
|
+
| `devp caches docker` | `podman`, `containers [ENGINE]` (`nerdctl`, `finch`, `container`), `--json` | What a container engine holds — images, containers, volumes, build cache — each sized, with what the engine calls reclaimable, then the prune commands. The report deletes nothing; `devp caches clear <engine>` runs the narrow ones when you name it — a volume only through `--include-volumes`, picked by name at a terminal |
|
|
657
609
|
| `devp trust` | `--json` | What dev-prune may do on this machine: the guarantees the code enforces, then the scheduler, hooks and settings read live, then every copy of dev-prune on the machine with the manager that installed it and its SHA-256. Read-only |
|
|
658
610
|
| `devp restore [PATH]` | `--last-run` | Reinstalls dependencies for every project in a tree; `--last-run` undoes the last prune pass |
|
|
659
611
|
| `devp doctor [PATH]` | `--fix` | Diagnoses the installation, or one repository — ending with the single reason a pass would or would not touch it. `--fix` repairs what the checks found; it never performs a first-time install |
|
|
@@ -695,6 +647,7 @@ Adapters detect the project, verify the lockfile, and own the bloat directories:
|
|
|
695
647
|
| **PDM** (Python) | `pdm.lock`, `[tool.pdm]` or `pdm.backend` in `pyproject.toml` | `.venv`, `__pypackages__` | `pdm lock --check` | `pdm install` |
|
|
696
648
|
| **Pipenv** (Python) | `Pipfile` | `.venv` *(in-project installs only)* | `pipenv verify` | `pipenv install --deploy` |
|
|
697
649
|
| **venv** (Python) | `requirements.txt` + a directory containing `pyvenv.cfg` | every directory containing `pyvenv.cfg` | `requirements.txt` must exist and list at least one package | `python -m venv .venv && pip install -r requirements.txt` |
|
|
650
|
+
| **pixi** (Python/conda) | `pixi.toml`, `pixi.lock`, `[tool.pixi]` in `pyproject.toml` | `.pixi` | `pixi.lock` carries its `version:` and records at least one conda or PyPI package | `pixi install` |
|
|
698
651
|
| **Cargo** (Rust) *(opt-in)* | `Cargo.toml` | `target` | `cargo metadata --locked` | *(rebuilt by the next `cargo build`)* |
|
|
699
652
|
| **Go** | `go.mod` | `vendor` | `go mod download` | `go mod vendor` |
|
|
700
653
|
| **Composer** (PHP) | `composer.json` | `vendor` | `composer validate --no-check-publish --no-check-all` | `composer install` |
|
|
@@ -709,15 +662,23 @@ Adapters detect the project, verify the lockfile, and own the bloat directories:
|
|
|
709
662
|
| **Mix `_build/`** *(opt-in)* | `mix.exs` | `_build` | `mix.exs` and `mix.lock` both present — the rebuild-from-source proof | *(rebuilt by the next `mix compile`)* |
|
|
710
663
|
| **vcpkg** (C/C++) *(opt-in)* | `vcpkg.json` | `vcpkg_installed` | `vcpkg.json` declares a non-empty `dependencies` list | *(rebuilt by the next `vcpkg install`)* |
|
|
711
664
|
| **CMake** (C/C++) *(opt-in)* | `CMakeLists.txt` | any tree holding a `CMakeCache.txt` | the tree's own `CMakeCache.txt` names a source directory inside this repository | *(rebuilt by the next `cmake --build`)* |
|
|
665
|
+
| **.NET build** *(opt-in)* | `*.csproj`, `*.fsproj`, `*.vbproj` | `obj`, and `bin` beside it *(only while `bin` holds nothing but `Debug`/`Release`)* | `obj/project.assets.json` names a project file still sitting in this directory, and every project file here has a `<Project` root | *(rebuilt by the next `dotnet build`)* |
|
|
666
|
+
| **Zig** *(opt-in)* | `build.zig` | `.zig-cache`, `zig-cache`, `zig-out` | `build.zig` declares a `pub fn build` — the rebuild-from-source proof | *(rebuilt by the next `zig build`)* |
|
|
667
|
+
| **Stack** (Haskell) *(opt-in)* | `stack.yaml` | `.stack-work` | `stack.yaml` names its `resolver:` (or `snapshot:`) | *(rebuilt by the next `stack build`)* |
|
|
668
|
+
| **Cabal** (Haskell) *(opt-in)* | `cabal.project` | `dist-newstyle` | `cabal.project` declares its `packages` — a lone `*.cabal` file is never claimed | *(rebuilt by the next `cabal build`)* |
|
|
669
|
+
| **sbt** (Scala) *(opt-in)* | `build.sbt` | `target`, `project/target` | `build.sbt` carries a setting, or `project/build.properties` pins `sbt.version` | *(rebuilt by the next `sbt compile`)* |
|
|
712
670
|
|
|
713
671
|
A required binary that is missing is a reason to skip, never a reason to delete: if `npm`
|
|
714
672
|
is not on `PATH`, the `node_modules` it owns is left exactly where it is.
|
|
715
673
|
|
|
716
|
-
The
|
|
674
|
+
The eighteen build-tool adapters ship **disabled**, because a build tree is regenerated
|
|
717
675
|
by recompiling, not downloading — it costs more to get back. `devp config set
|
|
718
676
|
enable_cargo true` / `enable_gradle true` / `enable_maven true` / `enable_swift true` /
|
|
719
677
|
`enable_dart true` / `enable_mix_build true` / `enable_vcpkg true` /
|
|
720
|
-
`enable_cmake_build true` / `enable_dotnet_build true`
|
|
678
|
+
`enable_cmake_build true` / `enable_dotnet_build true` / `enable_godot true` /
|
|
679
|
+
`enable_unity true` / `enable_unreal true` / `enable_defold true` /
|
|
680
|
+
`enable_cocos true` / `enable_zig true` / `enable_stack true` /
|
|
681
|
+
`enable_cabal true` / `enable_sbt true` switches them on, and their candidates wait for
|
|
721
682
|
`build_idle_days` (45 by default), applied as the *maximum* of it and `idle_days` — the
|
|
722
683
|
build-tool gate only ever makes pruning later, never earlier.
|
|
723
684
|
|
|
@@ -744,10 +705,11 @@ column on the same checklist.
|
|
|
744
705
|
|
|
745
706
|
The report answers one more question the disk cannot: *who still needs this*. Beside each
|
|
746
707
|
manager it says how many of your registered repositories use it, and what its cache works
|
|
747
|
-
out to per repository — two repositories sharing a
|
|
748
|
-
look
|
|
749
|
-
manager **no** registered repository uses is the one case where a count
|
|
750
|
-
on: everything in it was downloaded for projects that are not on this
|
|
708
|
+
out to per repository — two repositories sharing a cache carry half of it each, which is
|
|
709
|
+
worth a look; forty sharing that same cache carry a fortieth each, and that is the cache
|
|
710
|
+
doing its job. A manager **no** registered repository uses is the one case where a count
|
|
711
|
+
is enough to act on: everything in it was downloaded for projects that are not on this
|
|
712
|
+
disk any more, so
|
|
751
713
|
`devp caches clear --unused all` costs no re-download for anything you still have. The
|
|
752
714
|
count ignores whether an adapter is switched on, because the question is which managers
|
|
753
715
|
your projects *use*, not which ones a prune pass would touch, and it is shown only for the
|
|
@@ -795,9 +757,9 @@ monorepo/ monorepo/ monorepo/
|
|
|
795
757
|
Results are reported by repository-relative path, so a monorepo reads unambiguously:
|
|
796
758
|
|
|
797
759
|
```
|
|
798
|
-
• MyMonorepo → frontend/node_modules
|
|
799
|
-
• MyMonorepo → services/api/.venv
|
|
800
|
-
• MyMonorepo → tools/cli/target
|
|
760
|
+
• MyMonorepo → frontend/node_modules [pnpm]
|
|
761
|
+
• MyMonorepo → services/api/.venv [uv]
|
|
762
|
+
• MyMonorepo → tools/cli/target [cargo]
|
|
801
763
|
```
|
|
802
764
|
|
|
803
765
|
The walk never descends into `node_modules`, `target`, `vendor`, virtual environments,
|
|
@@ -827,12 +789,12 @@ once on a first install — so the defaults are something you agreed to rather t
|
|
|
827
789
|
inherited — and again after an upgrade adds a setting you have never been shown.
|
|
828
790
|
|
|
829
791
|
If you already know what you want, `devp config recommended` is the one-command version:
|
|
830
|
-
it turns on the
|
|
792
|
+
it turns on the eighteen adapters and build trees that are off by default because they are
|
|
831
793
|
not universally wanted, and leaves `allow_manifest_rewrite` — the one recommendation
|
|
832
794
|
that edits files Git tracks — named, explained and off unless you add
|
|
833
795
|
`--with-cautious`. `devp config show` lists whatever you have not taken yet.
|
|
834
796
|
|
|
835
|
-
|
|
797
|
+
Forty-one settings, in the seven groups the configurator asks them in — the order the
|
|
836
798
|
decisions actually arrive in. Every key, with its full description and range, is in the
|
|
837
799
|
[CLI reference](docs/CLI_REFERENCE.md#8-devp-config-action).
|
|
838
800
|
|
|
@@ -865,7 +827,7 @@ rather than downloading. That is the whole reason each one is a switch.
|
|
|
865
827
|
|
|
866
828
|
| Key | Default | Meaning |
|
|
867
829
|
| :--- | :---: | :--- |
|
|
868
|
-
| `enable_cargo` … `
|
|
830
|
+
| `enable_cargo` … `enable_sbt` | `false` | Turn on an opt-in build-tool adapter; `build_idle_days` (`45`) gates all eighteen |
|
|
869
831
|
|
|
870
832
|
**Shared download caches** — one key, because the cap only ever marks.
|
|
871
833
|
|
|
@@ -971,7 +933,18 @@ scheduler with nobody watching. Before deleting one, dev-prune requires that:
|
|
|
971
933
|
- it resolves to somewhere inside the repository, even through a symlinked parent;
|
|
972
934
|
- Git is tracking nothing inside it — a lockfile cannot rebuild a file that is in the
|
|
973
935
|
repository itself;
|
|
974
|
-
- the first word of `rebuild` is a program this machine actually has
|
|
936
|
+
- the first word of `rebuild` is a program this machine actually has;
|
|
937
|
+
- and the target that program was given is one it could actually find, wherever a
|
|
938
|
+
manifest already in the tree can answer for it — an `npm`, `pnpm` or `yarn` script in
|
|
939
|
+
`package.json` (honouring `--prefix`), a `make` target, a `uv run` entry point in
|
|
940
|
+
`[project.scripts]`, a `cargo` subcommand. `npm run build` against a `package.json`
|
|
941
|
+
with no `build` script is refused, because installing node proves nothing about
|
|
942
|
+
whether that command would put the directory back.
|
|
943
|
+
|
|
944
|
+
Every one of those is a read of a file. The `rebuild` command is printed, never run —
|
|
945
|
+
not even a dry run of it. A command shape no manifest can resolve, such as a shell
|
|
946
|
+
pipeline or a target held in a variable, is allowed through on the checks above rather
|
|
947
|
+
than guessed at: a false refusal blocks a prune that was safe.
|
|
975
948
|
|
|
976
949
|
A claim that fails any of those is printed with the reason, and nothing is deleted.
|
|
977
950
|
|
|
@@ -1038,7 +1011,7 @@ Full decision flow: [docs/BACKGROUND_AUTOMATION.md](docs/BACKGROUND_AUTOMATION.m
|
|
|
1038
1011
|
|
|
1039
1012
|
| | `dev-prune` | `kondo` | `npkill` | `cargo-clean-all` | `pyclean` | `git clean` | `dust` / `ncdu` | BleachBit |
|
|
1040
1013
|
| :---------------------------------------- | :----------------------: | :---------------: | :------: | :---------------: | :-------: | :-------------: | :-------------: | :-------: |
|
|
1041
|
-
| Package managers | **
|
|
1014
|
+
| Package managers | **25** | ~20 project types | Node | Rust | Python | untracked files | — | OS caches |
|
|
1042
1015
|
| Many projects per repository | **✓** | ✓ | ✗ | ✗ | ✗ | n/a | n/a | ✗ |
|
|
1043
1016
|
| `.git` boundary enforced | **✓** | ✗ | ✗ | ✓ | ✗ | ✓ | ✗ | ✗ |
|
|
1044
1017
|
| Lockfile verified before deleting | **✓** | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
|
package/bin/dev-prune
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dev-prune-darwin-arm64",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"description": "Prebuilt dev-prune binary for darwin arm64. Installed automatically by the 'dev-prune' package; not meant to be depended on directly.",
|
|
5
5
|
"os": ["darwin"],
|
|
6
6
|
"cpu": ["arm64"],
|