Repository navigation
Releases
v1.23.1
Fixed
-
A Windows short-name alias can no longer reach
.git. On NTFS volumes that keep
8.3 short names,GIT~1\objectsis the same directory as.git\objects, and the
.gitboundary only compared names. dev-prune now resolves every deletion target to its
real location first and refuses any that lands inside.git, outside the repository, or
anywhere other than the path that was named. Nothing was known to be hit by this; it was
found in a security review and closed before anyone could be. -
A symlinked or junctioned parent directory can no longer stand in for a prunable
one. The link check only looked at the last path component. It now looks at where the
whole path really leads, for built-in adapters and forprunable.directoriesalike. -
A committed
prunabledeclaration can no longer mark un-ignored files as disposable.
A cloned repository could carry"rebuild": "echo not needed"for a directory holding
your own untracked data. Declared directories now have to be ignored by Git and not
tracked, or they are refused with the reason. If you declare one, add it to
.gitignorefirst. -
devp caches clearrefuses cache paths it cannot vouch for. Cache locations come
from environment variables such asCCACHE_DIRandGOMODCACHE. A value that points at
a filesystem root, at your home directory (or a folder containing it), or at a link is
now left alone and reported. -
devp containers clearwill not act on a remote daemon. An inherited
DOCKER_HOST=ssh://...ortcp://...(orCONTAINER_HOST) used to make "free space on
this machine" prune someone else's engine. The command now stops and says why. Unset the
variable for that command to clear the local engine. -
On Windows, a planted
node.cmdin a repository is no longer picked up.cmd.exe
looks in the current directory beforePATH, and thepnpmandyarnshims call
nodeby bare name. dev-prune now setsNoDefaultCurrentDirectoryInExePathfor the
commands it starts. -
The bundled TLS stack is updated (rustls 0.23.46, rustls-webpki 0.103.16 and
webpki-roots 1.0.11). That closes four rustls advisories and two certificate-trust
advisories (RUSTSEC-2026-0381 and RUSTSEC-2026-0382) in the connection code behind
devp update.
For contributors
- The VS Code extension's icon-font tooling now resolves
glob14 andminimatch11, so
npm auditis clean foreditors/vscode. docs/SAFETY_INVARIANTS.mdnow says plainly that verification runs the package manager
in the repository, and that only npm and bun are passed--ignore-scripts.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.23.1 / pipx install dev-prune==1.23.1 |
| Rust, no compile | cargo binstall dev-prune@1.23.1 |
| Rust, from source | cargo install dev-prune --version 1.23.1 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.23.1-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.23.1-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.23.1-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.23.1-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.23.1-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.23.1-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.23.1-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.23.1-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither does building from source.
The troubleshooting guide
covers what your options actually are.
Every archive ships a .sha256 sidecar. Check it before you trust it:
sha256sum -c dev-prune-v1.23.1-linux-x64.tar.gz.sha256(Get-FileHash dev-prune-v1.23.1-windows-x64.zip).Hash -eq (Get-Content dev-prune-v1.23.1-windows-x64.zip.sha256).Split(' ')[0].ToUpper()An archive's hash stops meaning anything the moment you unpack it, and the
unpacked files are the only ones your antivirus ever looks at. So each Windows
zip also ships a .zip.contents.sha256 listing the digest of every file inside
it — run this in the folder you extracted to, from Git Bash (sha256sum ships
with Git for Windows, and is what reads this format):
sha256sum -c dev-prune-v1.23.1-windows-x64.zip.contents.sha256dev-prune.exe and devp.exe are one file under two names and share a digest
on purpose, so a scanner builds one reputation record instead of two.
devpw.exe — the console-free build the scheduled task runs — is compiled
separately and legitimately has a different one. devp trust prints the same
three digests for the copies already installed on your machine, so you can
compare them against this file without downloading anything again.
That sidecar proves the file was not altered in transit. It does not prove
where it came from — the same hand that swaps an archive swaps its sidecar.
Every archive on this page is also signed by GitHub's build provenance, which
binds it to this repository, this workflow and the commit it was built from:
gh attestation verify dev-prune-v1.23.1-linux-x64.tar.gz --repo Life-Experimentalist/dev-prunegh attestation verify dev-prune-v1.23.1-windows-x64.zip --repo Life-Experimentalist/dev-pruneFull Changelog: v1.23.0...v1.23.1
v1.23.0
Added
-
pycache joins the Python group as a regular adapter (on by default): it deletes
__pycache__by name alone, since CPython owns that name unconditionally, and deletes
.pytest_cache,.mypy_cacheand.ruff_cacheonly when aCACHEDIR.TAGfile inside
proves the tool wrote it, per the cache directory tagging
spec. It never touches.hypothesis(holds regression
examples pytest cannot regenerate on its own), and never.toxor.nox(environments,
not caches). Verification requires at least one.pyfile anywhere in the repository,
so there is always something to regenerate the bytecode and tool caches from. That
makes thirty-six adapters. -
devp statusreports a Tools line for the output graphify and understand-anything
leave behind (graphify-out/and.understand-anything/), because both can grow
into gigabytes and neither has a lockfile to prove it is safe to delete: rebuilding
either means re-running the tool's own extraction passes, LLM calls included. The
interactive dashboard's header and the plain-table view both show the size next to
everything else, and--jsoncarries it as atoolsarray on each repository entry.
It is report-only: never counted in the reclaimable total, and never a candidate for
devp run. -
devp statusopens an inspector pane beside the table on terminals at least 110
columns wide: the selected repository's per-directory sizes, root-commit identity,
idle window, last prune, lifetime space saved and detected adapters, all in one
place instead of behinddevp doctor <path>. It also draws a sparkline of the
repository's commits over the last 26 weeks and lists the five largest entries inside
its bloat directories, both read in the background so moving the selection never waits
on a largenode_modules. A narrower terminal with at least 34 rows puts the pane
below the table instead, andTabhides and shows it. -
devp scores(the same report asdevp history --scores) ranks your all-time
largest single-repository cleanups and largest whole passes, read from the same pass
logdevp historyprints, with medals on the top three of each.--jsonemits it
as a document with"command": "history --scores". -
The registry heals itself.
devp status,devp runanddevp doctornow
resolve registry entries whose directory is gone instead of warning about them
forever. A repository
that moved into a siblingArchive/-style directory, or anywhere else its root-commit
identity proves it is the same repository, keeps its lifetime statistics under the new
path. An entry for a deleted AI-agent worktree (.claude/worktrees/,
.cursor/worktrees/and kin) is dropped outright, because the session that creates
one deletes it when it ends. Nothing is merged on a shared directory name alone, so
an entry whose drive is merely unplugged stays put until the drive returns. -
devp skill --prompt workspace(or--prompt agent) prints just that onboarding
prompt, with no header or code fence around it, so you can pipe it or paste it
without trimming. Add--copyand it goes straight to the clipboard instead.
devp skill --rules-file <path>writes the same marked rules block--agent
uses into any file you name inside the repository, for an editor--agentdoes not
list or one that reads a renamed file; a re-run replaces the block and leaves the
rest of the file alone. Seedevp skillin the CLI
reference.
Changed
-
iindevp statusasks before it changes anything. A small dialog names the
repository and what will happen;yorEnterconfirms and any other key backs out.
A stray keypress used to rewrite.devprune.jsonon whichever row was highlighted. -
devp update --installand the auto-update also replace the copies cargo put on
PATH. The scheduled pass runs the managed copy, and a copy only ever replaced itself
and the managed one, sodevptyped from~/.cargo/binkept answering with the
release thatcargo binstallinstalled, however many scheduled passes had updated
since. Thedev-pruneanddevpfiles in cargo'sbindirectory now move forward with
the managed copy, unless they are already the same release or newer (acargo install --path .development build is never downgraded). Cargo's own record of the installed
version is not touched, and the update says which command brings it forward. -
devp doctornames the upgrade command for a stale copy, not only the uninstall
one. A copy on an older release is usually one you still want, on the current
release, and "remove withcargo uninstall dev-prune" pointed at deleting the binary
you type. The line now reads, for example, "upgrade withcargo binstall dev-prune --forceor remove withcargo uninstall dev-prune". -
Windows binaries no longer need the Visual C++ runtime. They link the C runtime
statically, so the release zip, the install script, Scoop, npm, PyPI and WinGet all
run on a clean Windows install instead of failing to start with a missing
VCRUNTIME140.dll.cargo install
from crates.io still compiles against the dynamic runtime, which any machine with the
MSVC toolchain already has.
Fixed
-
A pass that found nothing eligible to prune, or stopped early on a lockfile
verification failure, skipped the auto-update check entirely, so an unattended
machine whose repositories were all clean or all active could stay on an old release
indefinitely. The check now runs at the end of every pass regardless of what the
pass found, with one deliberate exception: a--jsonpass stays out of it, because
that mode's stdout is a single machine-readable document and nothing else. -
The windowless
devpw.exetwin the Windows scheduled task runs is now refreshed
when it is stale against the running binary, so an upgrade no longer leaves the
scheduled task executing the previous version. And when the twin is missing and the
console binary runs the task instead, it detaches from its console immediately,
shortening the window flash. -
DEV_PRUNE_NO_TUInow keeps every full-screen view closed, as documented. Only the
config wizard read it, sodevp statusand thedevp runselector still opened
whenever both ends looked like a terminal, and an AI agent holding a pseudo-terminal
landed in a keypress loop it had no way to leave. Set the variable and both print
their plain output instead. -
-yondevp trust --fix-ownershipworks in either position.devp -y trust --fix-ownershipparsed the flag and then asked anyway, anddevp trust --fix-ownership -ywas a usage error. -
devp restore --last-runputs a Govendor/directory back. Restore chose between
go mod vendorandgo mod downloadby checking whethervendor/existed, but the
prune had just deleted it, so a vendored repository always gotgo mod download,
which exits successfully without recreating anything, and the pass reported
"restored" over a directory that was still gone. It now rebuilds what the prune
recorded, and reports a failure unlessvendor/exists afterwards. -
Pressing
ion a repository ignored through the olderignore.devprune.jsonmarker
took two presses to un-ignore it. The first wrote"ignore": trueand deleted the
marker, so the repository stayed ignored; it is now offered "stop ignoring" straight
away, and confirming clears both. -
In
devp status, after sorting, filtering or searching, the highlighted row's path
could keep the colour meant for an unhighlighted one while a different row got the
white text meant for the highlight, which is unreadable on a light terminal theme.
The highlight is now matched by its position on screen. -
devp run --helplistsdenoanddotnet_buildamong the--onlyand--skip
names,devp caches --helpcovers every manager the report sizes, and the sample
output throughout the docs says MiB and GiB, which is what dev-prune prints. -
When a
.devprune.jsoncannot be read,devp run,devp doctoranddevp config
now suggestdevp config project <PATH> --updateto reset it. The hint used to say
devp config <PATH> --update, which is a usage error, so following the advice printed
only clap's complaint.
For contributors
devp uninstallanddevp updatenow recognise a development build anywhere under
target/, includingtarget/<triple>/releaseand cargo-llvm-cov's
target/llvm-cov-target/debug. Before, an uninstall run from one of those deleted the
binary it was running from, socargo llvm-covfailed the uninstall tests.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.23.0 / pipx install dev-prune==1.23.0 |
| Rust, no compile | cargo binstall dev-prune@1.23.0 |
| Rust, from source | cargo install dev-prune --version 1.23.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev...
v1.22.0
Added
-
Ten new adapters bring the total to thirty-five. pixi joins the regular set (on by
default): a.pixi/directory besidepixi.toml,pixi.lockor apyproject.toml
with a[tool.pixi]table is verified againstpixi.lockread-only, because
pixi lock --checkcan re-solve over the network and a verification must never do
that. The other nine are opt-in like every build tree: Zig (.zig-cache/,
zig-cache/andzig-out/beside abuild.zig), Haskell Stack (.stack-work/),
Haskell Cabal (dist-newstyle/; a lone.cabalfile is never claimed), sbt
(target/andproject/target/besidebuild.sbt), and the imported-resource
caches of Godot, Unity, Unreal, Defold and Cocos Creator.devp config set enable_zig trueand friends switch them on, and every one is in the recommended
set the config wizard offers. That makes thirty-five adapters, eighteen opt-in
switches and forty-one settings; the whole opt-in class is walked through in
docs/OPT_IN_BUILD_ADAPTERS.md. -
devp caches clear docker --include-volumes(podman too): after the narrow
reclaim, it lists the engine's unused volumes by name and takes one line of picks
(numbers, ranges,all, or Enter for none), then runs one unforcedvolume rm <name>per pick. It is consent-gated end to end: it refuses--yes,--jsonand a
piped stdin, and the pick list only arms within ten minutes of a completed volume
dry run for that engine. Typed cold, the command becomes that dry run, and
--include-volumes --dry-runends by naming the command to type next. dev-prune
still never runsvolume pruneorsystem prune --volumesanywhere, and the unit
tests fail the build if any argv it assembles containsprune,--volumesor a
force flag. nerdctl, finch and Apple'scontainerget a usage error naming
<engine> volume lsinstead, because their volume listings cannot be sized safely. -
A "Detected, but switched off" section at the end of a bulk dry run. When a
dormant opt-in adapter would find bloat,devp run --dry-runnow says so: how many
repositories, and the exactdevp config set enable_<name> truethat would include
them. The--jsondocument carries the same facts under an additive
recommendationskey, anddevp config set recommendations falsesilences the
section once you have read it. -
devp skill --detectedand an editor detection report. Plaindevp skillnow
ends by naming every editor and agent whose traces are on the machine or committed
in the repository (home-directory footprints, VS Code-family extensions, rules
files), and whether each one's rules are current, stale or missing.devp skill --detectedthen writes the right rules file for everything detected in one pass.
Detection is pure existence checks; nothing is executed or fetched. -
Exported rules files now carry three guardrails for the agents that read them: never
delete a bloat directory by hand (usedevp run, anddevp restoreto put back
anything devp removed), never clear container volumes through a bulk engine prune,
and never empty~/.m2/repositoryuninvited.
docs/IDE_INTEGRATION.md adds a copy-paste PreToolUse hook
that turns the volume rule into a hard confirmation prompt in Claude Code.
Changed
-
The windowless Windows twin (
devpw.exe) can no longer fall behind silently. The
release publishes it as its own asset with a SHA-256 sidecar;devp update --installreconciles every twin alongside the main binary;devp doctorcompares
each twin's build stamp against the running version, namesdevp update --install
as the fix, and exits 1 when the scheduled task is actually running a stale twin
(a warning otherwise);devp doctor --fixperforms the reconcile itself. The setup
pass also self-heals once per version at an attended terminal. All of it stands
down underDEV_PRUNE_OFFLINE,version_lock, and in development builds. -
A worktree nested inside its own repository (the shape agent harnesses create under
.claude/worktrees/) is no longer self-registered by the quiet Git hook or by
status adoption. An explicitdevp linkstill registers one when you mean it. -
The no-longer-a-repository report now names both ways out in place (
devp unlink <path>to drop the row,git initif the directory should be one again), and the
nested-repository refusal explains why it exists (no lockfile of yours can vouch
for someone else's git history) and points at the cache-relocation config for the
common cause.
Fixed
-
devp restorein a Go repository rebuilds the recordedvendor/directory again.
It used to consult the directory the prune had already deleted to decide between
go mod vendorandgo mod download, so a pruned vendor tree came back as a
module-cache download instead of thevendor/the build was using. -
devp trust --fix-ownership -yis honoured with the flag on either side of
--fix-ownership. Previously one order asked anyway, which is what a script cannot
answer. -
DEV_PRUNE_NO_TUI=1is honoured at every full-screen entry point, including the
ones reached from inside another command, so agents driving a terminal never get a
dashboard they cannot read. -
The scheduled task's windowless twin, and a stray managed-binary alias, could be
left running a stale release. Both are refreshed by comparing the new copy against
the one already in place, and that comparison trusted two files with the same size
and the same modified-time to also hold the same bytes, which is not guaranteed and
occasionally false. A refresh that hit the coincidence quietly kept the old binary
in place instead of replacing it. The comparison now always reads both files once
their lengths match.
For contributors
-
crates.io publishing now uses Trusted Publishing: the release workflow exchanges a
GitHub OIDC token for a 30-minute crates.io token at publish time, so the
long-livedCARGO_REGISTRY_TOKENsecret is no longer read by the workflow. -
Test fixtures create their repositories through
git_in(an explicit-Con every
invocation), so a test run started from inside a Git hook can never act on the
repository that hosts the checkout.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.22.0 / pipx install dev-prune==1.22.0 |
| Rust, no compile | cargo binstall dev-prune@1.22.0 |
| Rust, from source | cargo install dev-prune --version 1.22.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.22.0-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.22.0-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.22.0-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.22.0-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.22.0-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.22.0-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.22.0-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.22.0-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither...
v1.21.0
Added
devp caches clear npm,uv,pipempties exactly the caches you name. The target
now takes a comma-separated list, a one-time whitelist with no configuration
involved. The mirror image isdevp caches clear all --except npm,uv: everything
goes except the names given, for the day one cache is the only one worth keeping
warm.--exceptonly pairs withall(a list already says exactly what to clear),
and a container engine never appears in either form: naming an engine alone remains
the consent to touch it. Flags, exit codes and the maven rule are in
the CLI reference.
Changed
-
A
prunabledeclaration is now checked against the manifest itsrebuildcommand
would read, not just against yourPATH."rebuild": "npm run build"used to pass
the moment npm was installed — even in a project whosepackage.jsonhas nobuild
script. dev-prune would call the directory recoverable, delete it, and the command
meant to put it back would fail. It now reads the manifest and refuses instead:! `site/dist` is declared prunable, rebuilt by `npm run build`, but `package.json` defines no `build` script — refusing to delete something that command cannot put back. Add a `build` script to `package.json`, or fix the command.Covered where a manifest in the tree can answer:
npm/pnpm/yarnrun <script>
and the barepnpm <script>/yarn <script>forms, honouring--prefix,-C,
--dirand--cwdsonpm --prefix docs run buildreadsdocs/package.json;
make <target>against theMakefile, honouring-Cand-f;uv run <script>
against[project.scripts]inpyproject.toml; andcargo <subcommand>for names
that are neither cargo's own nor any installedcargo-<name>plugin.Two things this deliberately does not do. It never runs the rebuild command, or any
part of it — every check is a read of a file already in the tree. And a command shape
it cannot resolve is allowed through rather than guessed at: a shell pipeline, a
target held in a variable, a tool with no manifest behind it, or a manifest that is
absent or unparseable all fall back to the tool check alone, because a false refusal
blocks a prune that was safe.One gotcha worth naming:
[tool.uv.scripts]is not a table uv reads. A script
declared only there does nothing, souv run <that script>is refused, and the
message says to move it to[project.scripts]. -
devp caches clearnow ends with the reinstall command for browser bundles.
Playwright, Puppeteer and Cypress binaries do not come back with the next
npm install; they only return when their own installer runs. Clearing one of those
caches now prints the command that brings it back (npx playwright install,
npx puppeteer browsers install,npx cypress install) right where you cleared it,
instead of leaving the next broken test run to say it later.
Fixed
- A read-only file no longer stops the whole delete on Windows.
go modwrites
module directories read-only on purpose, and the odd npm package ships a read-only
file too; a single one used to fail the prune with Access Denied partway through.
dev-prune now clears the attribute the way rimraf does and retries. A delete that
still fails after that is reported honestly, as before. - Dropping an
ignore.devprune.jsonmarker no longer resets the idle clock.
Creating the marker is bookkeeping, not work, but its timestamp used to count as
project activity: un-ignore a repository later and it looked freshly touched, waiting
outidle_daysall over again. The marker now sits beside.devprune.jsonand
project.devprune.jsonin the activity walk's exclusion list.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.21.0 / pipx install dev-prune==1.21.0 |
| Rust, no compile | cargo binstall dev-prune@1.21.0 |
| Rust, from source | cargo install dev-prune --version 1.21.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.21.0-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.21.0-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.21.0-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.21.0-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.21.0-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.21.0-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.21.0-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.21.0-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither does building from source.
The troubleshooting guide
covers what your options actually are.
Every archive ships a .sha256 sidecar. Check it before you trust it:
sha256sum -c dev-prune-v1.21.0-linux-x64.tar.gz.sha256(Get-FileHash dev-prune-v1.21.0-windows-x64.zip).Hash -eq (Get-Content dev-prune-v1.21.0-windows-x64.zip.sha256).Split(' ')[0].ToUpper()An archive's hash stops meaning anything the moment you unpack it, and the
unpacked files are the only ones your antivirus ever looks at. So each Windows
zip also ships a .zip.contents.sha256 listing the digest of every file inside
it — run this in the folder you extracted to, from Git Bash (sha256sum ships
with Git for Windows, and is what reads this format):
sha256sum -c dev-prune-v1.21.0-windows-x64.zip.contents.sha256dev-prune.exe and devp.exe are one file under two names and share a digest
on purpose, so a scanner builds one reputation record instead of two.
devpw.exe — the console-free build the scheduled task runs — is compiled
separately and legitimately has a different one. devp trust prints the same
three digests for the copies already installed on your machine, so you can
compare them against this file without downloading anything again.
That sidecar proves the file was not altered in transit. It does not prove
where it came from — the same hand that swaps an archive swaps its sidecar.
Every archive on this page is also signed by GitHub's build provenance, which
binds it to this repository, this workflow and the commit it was built from:
gh attestation verify dev-prune-v1.21.0-linux-x64.tar.gz --repo Life-Experimentalist/dev-prunegh attestation verify dev-prune-v1.21.0-windows-x64.zip --repo Life-Experimentalist/dev-pruneFull Changelog: v1.20.0...v1.21.0
v1.20.0
Added
- Adapter idle windows now show up in the report. A repository idle past
idle_dayswhosetarget/still waits onbuild_idle_days(or an
adapter_idle_daysentry) used to hold that adapter in silence — thenode_modules
row appeared, thetarget/row simply didn't, and nothing said why. Nowdevp run
prints oneNot examined (adapter idle window: N days)line per held adapter,
devp run --explainanddevp doctor <repo>name the window and the
devp --ignore-idle runoverride, and--jsoncarries it as a new
skipped_adapter_windowstatus. One reading note for scripts: in
devp status --json, a repository held only by such windows now reports the lowest
unmet window as itsidle_days— the threshold it is actually held to — rather
than the configured setting.
Changed
- A registered folder that lost its
.gitno longer fails every scheduled pass.
Delete and re-clone a repository by hand, orgit worktree prunea registered
worktree, and the leftover entry used to count as a blocking error — exit1on
everydevp rununtil you went looking for why. It is now reported as what it is, a
stale registry entry: the pass names the path, hintsdevp unlink <path>, exits
0, and--jsontags the rownot_a_repo. If your automation alerts ondevp run's
exit code, note the change: this situation was exit1before 1.20.0 and is exit0
now. (devp unlink --missingdeliberately does not clear these — the directory still
exists; only its.gitis gone.) - The scheduled prune no longer skips laptops on battery. The Windows task is now
registered to start on battery power, keep running if the charger is pulled, and
fire as soon as the machine wakes if it slept through the scheduled time
(StartWhenAvailable). Existing installations are repaired in place: the next run
of anydevpcommand that checks the daemon rewrites the task's power settings
without moving its schedule. A task dev-prune cannot rewrite is reported by
devp doctorinstead of silently left strict. - A failed update check retries the next day, not next week. When the release
check cannot reach GitHub — captive portal, proxy, flaky hotel Wi-Fi — the failure
used to consume the wholeupdate_check_interval, so one bad morning meant a week
of not hearing about a new release. A failed check is now retried after a day.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.20.0 / pipx install dev-prune==1.20.0 |
| Rust, no compile | cargo binstall dev-prune@1.20.0 |
| Rust, from source | cargo install dev-prune --version 1.20.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.20.0-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.20.0-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.20.0-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.20.0-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.20.0-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.20.0-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.20.0-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.20.0-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither does building from source.
The troubleshooting guide
covers what your options actually are.
Every archive ships a .sha256 sidecar. Check it before you trust it:
sha256sum -c dev-prune-v1.20.0-linux-x64.tar.gz.sha256(Get-FileHash dev-prune-v1.20.0-windows-x64.zip).Hash -eq (Get-Content dev-prune-v1.20.0-windows-x64.zip.sha256).Split(' ')[0].ToUpper()An archive's hash stops meaning anything the moment you unpack it, and the
unpacked files are the only ones your antivirus ever looks at. So each Windows
zip also ships a .zip.contents.sha256 listing the digest of every file inside
it — run this in the folder you extracted to, from Git Bash (sha256sum ships
with Git for Windows, and is what reads this format):
sha256sum -c dev-prune-v1.20.0-windows-x64.zip.contents.sha256dev-prune.exe and devp.exe are one file under two names and share a digest
on purpose, so a scanner builds one reputation record instead of two.
devpw.exe — the console-free build the scheduled task runs — is compiled
separately and legitimately has a different one. devp trust prints the same
three digests for the copies already installed on your machine, so you can
compare them against this file without downloading anything again.
That sidecar proves the file was not altered in transit. It does not prove
where it came from — the same hand that swaps an archive swaps its sidecar.
Every archive on this page is also signed by GitHub's build provenance, which
binds it to this repository, this workflow and the commit it was built from:
gh attestation verify dev-prune-v1.20.0-linux-x64.tar.gz --repo Life-Experimentalist/dev-prunegh attestation verify dev-prune-v1.20.0-windows-x64.zip --repo Life-Experimentalist/dev-pruneFull Changelog: v1.19.0...v1.20.0
v1.19.0
Added
devp updatenow asks before installing. When a newer release exists and you are
at a terminal, the report ends withInstall vX.Y.Z now? [y/N]— Enter leaves the
binary alone,yruns the same download-verify-replace that--installalways did.
The global-yflag answers yes up front, anddevp update --installstill skips
the report entirely. Run from a script or a pipe, nothing changes: the check never
asks and never installs.
Fixed
- The release check no longer reads
api.github.com, whose sixty-requests-an-hour
limit per unauthenticated address could turndevp update(and the passive
update check) into a403that surfaced as "Could not reach the release API".
The version now comes from the redirectLocationof the release page at
github.com/Life-Experimentalist/dev-prune/releases/latest, which has no such
quota — and when the check does fail, the error now prints its full cause chain
instead of a one-line summary. - The install pages taught commands that quietly did nothing on a machine that already
had dev-prune —uv tool install dev-prunereports "already installed" and exits
successfully having changed nothing, and npm, bun, pnpm and yarn share the trap. The
README, the site and the docs now quote the spelling that both installs and updates:
@latestwhere the manager re-resolves it,--forcefor pipx,--upgradefor pip.
For contributors
scripts/bump-version.shnow rewrites the three version strings inSECURITY.md
(the supported-series table row and the twogh attestation verifyexample
filenames), so a version bump no longer failscheck-version.shuntil SECURITY.md
is edited by hand.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.19.0 / pipx install dev-prune==1.19.0 |
| Rust, no compile | cargo binstall dev-prune@1.19.0 |
| Rust, from source | cargo install dev-prune --version 1.19.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.19.0-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.19.0-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.19.0-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.19.0-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.19.0-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.19.0-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.19.0-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.19.0-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither does building from source.
The troubleshooting guide
covers what your options actually are.
Every archive ships a .sha256 sidecar. Check it before you trust it:
sha256sum -c dev-prune-v1.19.0-linux-x64.tar.gz.sha256(Get-FileHash dev-prune-v1.19.0-windows-x64.zip).Hash -eq (Get-Content dev-prune-v1.19.0-windows-x64.zip.sha256).Split(' ')[0].ToUpper()An archive's hash stops meaning anything the moment you unpack it, and the
unpacked files are the only ones your antivirus ever looks at. So each Windows
zip also ships a .zip.contents.sha256 listing the digest of every file inside
it — run this in the folder you extracted to, from Git Bash (sha256sum ships
with Git for Windows, and is what reads this format):
sha256sum -c dev-prune-v1.19.0-windows-x64.zip.contents.sha256dev-prune.exe and devp.exe are one file under two names and share a digest
on purpose, so a scanner builds one reputation record instead of two.
devpw.exe — the console-free build the scheduled task runs — is compiled
separately and legitimately has a different one. devp trust prints the same
three digests for the copies already installed on your machine, so you can
compare them against this file without downloading anything again.
That sidecar proves the file was not altered in transit. It does not prove
where it came from — the same hand that swaps an archive swaps its sidecar.
Every archive on this page is also signed by GitHub's build provenance, which
binds it to this repository, this workflow and the commit it was built from:
gh attestation verify dev-prune-v1.19.0-linux-x64.tar.gz --repo Life-Experimentalist/dev-prunegh attestation verify dev-prune-v1.19.0-windows-x64.zip --repo Life-Experimentalist/dev-pruneWhat's Changed
- ci: bump softprops/action-gh-release from 3.0.2 to 3.0.3 in the actions-minor-and-patch group by @dependabot[bot] in #29
- deps(site): bump @types/react-dom from 19.2.4 to 19.2.5 in /site in the site-minor-and-patch group by @dependabot[bot] in #28
New Contributors
- @dependabot[bot] made their first contribution in #29
Full Changelog: v1.18.0...v1.19.0
v1.18.0
Added
-
devp config set enable_dotnet_build trueadds a twenty-fifth adapter: the .NET
build output MSBuild writes.bin/andobj/are the most generic directory names a
repository can hold, so the adapter demands proof before claiming either — NuGet's
restore writesobj/project.assets.jsonrecording exactly which project it restored,
and only when that record names a project file in the same directory isobj/
claimed, withbin/going along only when it holds nothing butDebug/Release
build output. Abin/full of committed tools, or anobj/someone made by hand, is
never touched. Opt-in like every build-tree adapter and idle-gated by
build_idle_days; the nextdotnet buildwrites both directories again. -
devp cachesnow sizes ccache and sccache, the compiler caches behind most C,
C++ and Rust CI recipes — routinely several gigabytes that no row accounted for
before. ccache is asked where its cache is (ccache --get-config cache_dir) and
cleared with its ownccache --clear; sccache ships neither a path query nor a clear
command, so its row uses the documented locations (SCCACHE_DIRrespected) and
devp caches clear sccachedeletes the directory — aftersccache --stop-server
if the daemon is holding it open, which the report says on the row.
Changed
- The first run now asks before installing anything. dev-prune used to put its
integrations in place on the first command — a managed copy of the binary on
PATH, Git hooks, and a scheduled task runningdevp run --yes— and open the
settings walkthrough afterwards. Installing first and asking second is, from the
outside, the exact shape of malware establishing persistence, and anti-virus
classifiers flagged the 1.17.0 release executable for that behaviour. Now the
walkthrough opens first, its opening screen lists exactly what finishing it will
install, and nothing is installed until you finish it: accepting the recommended
setup is still one key (a), everything it enables can still be switched off
individually on the settings list, and quitting (q) installs nothing — durably,
so no later upgrade installs it either.devp setupremains the standing way to say
yes later,devp uninstallnow clears the answer so a reinstall asks again, and
machines upgrading from 1.17.0 or earlier are not re-asked — keeping the
integrations the old flow installed already answered the question.
Fixed
-
devp config project <PATH> --teamnow writes the public schema URL into the
committedproject.devprune.json. It used to inherit the personal file's preference
for the locally installed schema copy, which put afile:///C:/Users/<name>/...path
— username included — into a file whose whole purpose is to be committed, and broke
IntelliSense on every clone but the author's. If you created one before this release,
replace its$schemavalue with
https://devprune.vkrishna04.me/schemas/v1/devprune.schema.json. -
A declared
rebuildthat starts with a shell builtin now says what to write
instead."rebuild": "cd docs && npm run build"was refused with "Installcd
first" — advice that cannot be followed, becausecdis not a program. The refusal
now names the actual fix: put the tool first, as innpm --prefix docs run build.
The check is also the same on every platform now; macOS ships a/usr/bin/cdshim
that used to let such a declaration through there while Windows refused it.
For contributors
- The release build now fails if a shipping binary contains dropper-bait strings —
the PowerShell obfuscation flags, Defender-exclusion cmdlets and injection API names
that the 1.15.0 hardening removed by hand.scripts/check-binary-hygiene.shholds
the list and runs over every staged executable (the Windows zips unpacked,
devpw.exeincluded) before anything is published, so a dependency that smuggles
one back in fails in CI instead of in front of seventy antivirus engines.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.18.0 / pipx install dev-prune==1.18.0 |
| Rust, no compile | cargo binstall dev-prune@1.18.0 |
| Rust, from source | cargo install dev-prune --version 1.18.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.18.0-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.18.0-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.18.0-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.18.0-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.18.0-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.18.0-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.18.0-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.18.0-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither does building from source.
The troubleshooting guide
covers what your options actually are.
Every archive ships a .sha256 sidecar. Check it before you trust it:
sha256sum -c dev-prune-v1.18.0-linux-x64.tar.gz.sha256(Get-FileHash dev-prune-v1.18.0-windows-x64.zip).Hash -eq (Get-Content dev-prune-v1.18.0-windows-x64.zip.sha256).Split(' ')[0].ToUpper()An archive's hash stops meaning anything the moment you unpack it, and the
unpacked files are the only ones your antivirus ever looks at. So each Windows
zip also ships a .zip.contents.sha256 listing the digest of every file inside
it — run this in the folder you extracted to, from Git Bash (sha256sum ships
with Git for Windows, and is what reads this format):
sha256sum -c dev-prune-v1.18.0-windows-x64.zip.contents.sha256dev-prune.exe and devp.exe are one file under two names and share a digest
on purpose, so a scanner builds one reputation record instead of two.
devpw.exe — the console-free build the scheduled task runs — is compiled
separately and legitimately has a different one. devp trust prints the same
three digests for the copies already installed on your machine, so you can
compare them against this file without downloading anything again.
That sidecar proves the file was not altered in transit. It does not prove
where it came from — the same hand that swaps an archive swaps its sidecar.
Every archive on this page is also signed by GitHub's build provenance, which
binds it to this repository, this workflow and the commit it was built from:
gh attestation verify dev-prune-v1.18.0-linux-x64.tar.gz --repo Life-Experimentalist/dev-prunegh attestation verify dev-prune-v1.18.0-windows-x64.zip --repo Life-Experimentalist/dev-pruneWhat's Changed
- The VirusTotal job slept through most of its own runtime by @VKrishna04 in #24
- Dogfooding polish: public schema URL in the team file, and a followable refusal for cd by @VKrishna04 in #25
- A generic bin/ is guilty until the assets file vouches for it by @VKrishna04 in https://github.com/Life-Experimentalis...
dev-prune VS Code extension v0.5.0
- A stale “devp not found” now heals itself. The verdict was computed once,
when the window opened — install the CLI a minute later (or have an antivirus
quarantine give it back) and the warning stayed for the life of the window,
and clicking it sent you to the install page for a CLI you already had. The
extension now re-checks whenever the window regains focus while that warning
is up, and a click re-probes first: the install page only opens when devp is
still really missing. - A slow
devp statusno longer looks like a missing one. The status call
walks every registered repository, and on a machine mid antivirus-scan it
could outlive the old 15-second limit — the extension then hid its status bar
item without a word. The limit is now 60 seconds, and reaching it shows
“devp: not responding” with Refresh one click away, instead of nothing. - Prune This Repository is now a palette command. Pruning was reachable
only through the status-bar QuickPick, and only while it showed a candidate;
everything else the QuickPick offers already had a Command Palette twin. The
new command runsdevp run .in a visible terminal, same as the QuickPick
entry — the CLI still decides whether this repository is safely prunable and
says so in that terminal if not.
Install it from your editor rather than from this page: VKrishna04.dev-prune
on the VS Code Marketplace
and on Open VSX, which
is where VSCodium, Cursor, Windsurf and the other forks look.
The .vsix below is the same file both marketplaces are published from. Take
it if your editor cannot reach either registry:
code --install-extension dev-prune-vscode-0.5.0.vsix(codium, cursor and windsurf accept the same flag.)
gh attestation verify dev-prune-vscode-0.5.0.vsix --repo Life-Experimentalist/dev-pruneThe extension needs the devp CLI for everything except schema validation.
It is released separately — the latest release
is always the CLI, never this.
v1.17.0
Added
-
devp caches clear docker(alsopodman,nerdctl,finchand Apple's
container) runs the container prune commands the report has been printing since
1.13.0, instead of asking you to go and type one in another window. Build cache, unused
images, stopped containers — printed first, after a prompt, and counted on its own line
indevp stats, so the 20 GiB you reclaimed on dev-prune's advice is space dev-prune
can actually account for.--dry-runshows the commands and the estimate and touches
nothing.It will not touch a volume, and there is no flag that makes it. No argument anywhere
in its table contains the word, and a unit test fails the build if one appears. An image
can be pulled again and a build cache rebuilt; what is inside a named volume is the only
copy.docker volume prunestays a command it prints and you type — and the estimate
has the engine's unused-volume figure taken out of it and named separately, rather than
promising back space these commands cannot give.Nothing on a schedule reaches any of this: no daemon, no Git hook, no
devp run, and
notdevp caches clear alleither. Naming the engine is the consent.
Reference -
How a repository gets registered
is every way a repository can land on a machine, and which of the three mechanisms
catches it. A repository you unzipped, copied from another machine, restored from a
backup or received over Dropbox never runsgit, so no hook can ever fire for it —
discovery is what covers those, and the table says so instead of leaving you to work it
out. It also names the one case that still needs a hand, and what is skipped on purpose. -
devp historyanswers the questiondevp statsraises. That report says ten passes
freed 27.66 GiB; this one says pass #2 ran at 09:14 asdevp run --daemon, took
4.02 GiB out of two repositories, and names all three directories it deleted. Bare, it
is one line per pass.devp history --pass 1opens one in full: the exact command line,
the version that ran it, and every directory removed with its package manager and size,
grouped by repository.It records what started each pass, which nothing did before —
manualif you typed
devp run,scheduledif it was the background pass,dashboardif it was the[p]
key indevp status. There are three ways to start a prune and those are all three, so
"was that me or the daemon?" now has an answer rather than an inference.Long output has three exits rather than a truncation: detail is per-pass and opt-in, the
directory list is capped at 200 entries only when it is going to a terminal (redirect
or pipe it and nothing is elided), anddevp history --exportwrites the whole document
to your documents folder — or to exactly the path you name.Passes from before this release still appear, marked
(totals only): their four numbers
were always in the registry, and a history that started empty next to adevp stats
reading "10 prune passes" would look like a bug rather than a gap.devp history --json
carriesdetail: falseon those, so a script can tell "deleted nothing" from "nobody
wrote it down".
Reference -
devp cachesnow finds the stores that were quietly the largest things on the disk.
Playwright and Puppeteer keep a whole browser build per version, Cypress an unpacked
Electron application per version, and none of them ever removes the old one when the
dependency moves — on the machine this was written on that was 2.9 GiB nothing had ever
reported. The HuggingFace hub cache, the Electron download cache and electron-builder's
own store are in the report for the same reason. Each gets the row every other cache
gets: a size, the path,devp caches clear <name>, and the command that clears it.huggingfacecarries a warning the others do not, because it is the one row where
"re-download it" is not a promise. A gated or now-private repository will not hand the
weights back to the token that fetched them last month, a checkpoint from a deleted
revision is gone, and the re-download is tens of gigabytes rather than tens of
megabytes. It is cleared like anything else when you type it — with the path printed
first, so you can look inside before you do.
Reference -
Six adapters that pruned projects with nothing to show for it now have a cache row.
devp runhas always cleaned a Bundler, pub, SwiftPM, Terraform, Poetry or PDM project;
devp cachescould not see the machine-wide store those projects were reinstalling
from, so the report answered "where did my disk go" with a gap exactly where the answer
was. Each is asked where its cache is rather than assumed —gem env gemdir,
poetry config cache-dir,pdm config cache_dir— and each row names the one
subdirectory that is genuinely a download cache. That last part is the whole care taken
here:dart pub cache cleanwould also delete your globally activated executables and
yourgit/checkouts, and Poetry's cache directory holdsvirtualenvs/beside
artifacts/. dev-prune clears the archives and nothing else.
Reference -
A Deno adapter, the twenty-fourth. It detects on
deno.lockand takes the
node_modulesa Deno project with npm dependencies materialises, sized the way bun's is
because Deno hardlinks it out ofDENO_DIRtoo.deno installputs it back, and
devp caches clear denoempties the shared cache behind it.It takes
vendor/only when the Deno config asked for one. Go and Composer both use
that name at a project root for something else entirely, and a repository carrying a
deno.lockalongside either would otherwise have had its Composer dependencies deleted
withdeno installoffered to put them back. The config is parsed rather than searched,
so a"vendor": truesomebody commented out in adeno.jsoncreads as what it is.
Reference -
finch and Apple's
containerjoin the container report anddevp caches clear.
finch is nerdctl inside a Lima VM and forwardssystemto it verbatim, so it reads and
clears exactly as nerdctl does. Apple's engine is the odd one: itssystem dfanswers
with a single object rather than a row per resource, it has nosystem prune, and its
prune subcommands neither ask a question nor define a-f— so those steps run the
moment they are typed, anddevp caches containers containersays so in as many words
before it lists them. The confirmation is dev-prune's own, and it is still there.
Reference -
devp config set cache_max_gb default=10caps every download cache at once,
without you first having to learn which twenty-nine of them exist. Until now a ceiling
had to name a manager, which meant the setting only ever covered the caches you had
already thought about — and the one that has quietly passed 10 GiB is rarely one of
those. A manager named outright still wins:default=10,npm=4holds npm to four and
everything else to ten. Setting a ceiling still deletes nothing; it decides what
devp cachescalls too big, anddevp caches clear --over-cap allis still typed by
hand.The first run now suggests it, alongside the adapters, and
devp config recommendedsets it. It is the first suggestion that is not a yes-or-no, so it is
the first one that can already be satisfied by a different answer: any ceiling at all
counts as taken. A machine withnpm=4set by hand is listed as Already set,
never as outstanding, anddevp config recommendedleaves the number alone rather
than replacing the map with its own.
Reference -
devp statsnow says which package manager the space came from. The tool has
twenty-four adapters and, until now, never told you which of them was earning its keep
— the lifetime total was one number with nothing behind it. By package manager
ranks them by what each has given back, with the directory count beside it, so "npm is
the one costing me" stops being a hunch. It covers pruning only, and says so under
itself: emptying a cache is not a prune pass, so these figures are not meant to add up
to the lifetime total above them. -
devp statsalso shows how many passes you typed and how many ran unattended.
How passes start splits the same reclaims acrossmanual,scheduledand
dashboard, each with its share. All three print even at zero, because ascheduled
line reading zero passes is how you find out the daemon has never actually run — and
when it does read zero, the report points you atdevp status daemon. Both sections
are summed from the prune log, so both are bounded by 1.17.0 and both say how many
earlier passes they could not account for rather than quietly under-reporting.
devp stats --jsoncarries them asby_managerandby_trigger.
Reference
Changed
- Every binary in
devp trustnow shows the version it was built as, so the list
answers the question people open it with. Three of those files are called some spelling
of the same word, and until now the only thing telling them apart was a path and a
digest — which meant "which of these is the old one" could only be answered by
uninstalling something and seeing what broke. The newest is marked(latest release)
when a releas...
v1.16.0
Added
-
devp caches --volume V:reports only the caches sitting on one drive, and the
unfiltered report now ends with aBy driveline splitting the total the same way.
On a machine whose projects live on a second disk, "22 GiB of caches" is not the
figure that decides anything — the two gigabytes on the drive that is full is, and
until now you had to read twelve absolute paths to find it.--driveis the same
flag; both take a drive (V:,V:\, or the bare letterV), a mount point
(/mnt/data,/Volumes/Work), or any path on the one you mean, so--volume .is
the drive you are standing on. In--json, every cache row gains avolumekey so a
consumer can group by drive without deriving a mount table frompath.The narrowing happens last, after every verdict, so it changes what you see and never
what a figure means: acache_max_gbcap still weighs a manager's whole footprint
wherever it is, and a cache no registered repository uses does not become unused just
because the repositories that use it live on another drive. Container engines are left
out of a filtered report entirely — an engine reports its disk from inside a VM image
that has no path on this filesystem, so there is no honest drive to file it under, and
the JSON document omitscontainersrather than emitting an empty list that would
claim none are installed.devp caches dockerstill has that number.--volumewithclear,dockerorcontainersis a usage error rather than a flag
that looks accepted and does nothing: the clear commands empty a manager wherever it
is, and aclearthat had silently ignored the drive you handed it would be the worst
possible way to find that out. -
afinishes the configurator in one keystroke.devp config wizardtakes every
remaining safe recommendation and jumps straight to the summary, which still needs its
ownEnterbefore anything is written. It applies exactly what holdingEnterdown
would have applied —allow_manifest_rewriteis left off by both, because it can edit
a file Git tracks and that stays a deliberateSpace.Shift+Enterdoes the same
thing on terminals that report the modifier;ais the spelling that works
everywhere, soais the one the footer names. The first screen now says so too:
holdEnterand the whole setup configures itself. -
devp trustnow ends with every binary it owns and the SHA-256 of each, the one
you are running marked and listed first, each with a VirusTotal lookup URL for that
exact digest. When a scanner objects to dev-prune, the file it objected to is the one
on your disk — not the asset on a release page — and until now there was no way to ask
the tool which bytes those were. The digests are computed locally and the URLs are
printed rather than fetched: nothing is uploaded anywhere, and a digest the service has
never seen returnsnot found, which means unscanned rather than clean. On Windows
dev-prune.exeanddevp.exeshare a digest on purpose — one file under two names, so
a scanner builds one reputation record instead of two — anddevpw.exe, the
console-free build the scheduled task runs, is a separate build target that legitimately
differs.devp trust --jsoncarries the same facts under a newbinariesarray with
sha256as a field of its own, so a check can compare it against a published checksum
without parsing a sentence. -
Every Windows release now ships a
.zip.contents.sha256listing the digest of each
file inside the archive, insha256sumformat —sha256sum -cin the folder you
extracted to verifies all three at once. An archive's hash stops meaning anything the
moment you unpack it, and the unpacked files are the only ones an antivirus ever looks
at, so there was previously no published answer to "is thedevpw.exeon my disk the
one you built?". The same digests come out ofdevp trust, which is the side of the
comparison you actually control.
Changed
- The banner now says what the tool is. Under the art, two lines: every dependency
directory on the machine in one command, and the promise that only what a lockfile can
rebuild is ever deleted — withdevp undobehind that. The screen every interactive
command opens with said the name, the version and nothing else, so the first thing a
new user saw answered neither "what does this do beyondnode_modules" nor "what
stops it deleting my work". The version now sits at the right edge under the art
instead of trailing it, andPRUNEcarries the weightDEVdoes not.
Fixed
-
The configurator no longer skips the settings above the cursor. After an upgrade
added a setting,devp config wizardopened on that setting — halfway down the
list. But the walk only moves downwards and leaves through the finish line at the
bottom, so holdingEnterfrom there never offered a single row above it. Anyone
configuring the tool the way its own footer suggests was configuring a suffix of it.
The cursor now starts at the top and the walk reaches everything; the new setting is
still markedNEWwhen it comes around. -
The AI skill now stays current on machines that turned auto-setup off. dev-prune
exportsSKILL.md— the file Claude Code and the other agents read to learn its flags
— and rewrites it after every upgrade. That refresh rode along with the automatic
setup pass, so turning setup off (devp config set auto_setup false, or
DEV_PRUNE_NO_AUTO_SETUP) also froze the skill at whichever version installed it: the
agent went on describing flags that had been removed two releases ago, confidently,
because nothing told it otherwise. An upgrade now refreshes the copies that are
already on disk regardless of that setting, and creates none that were not — a machine
that never wanted an exported skill still does not get one.devp doctorcontinues to
report a stale copy, anddevp skillstill rewrites it on demand.
Which download do I want?
Most people want none of them. The installers below verify the SHA-256
sidecar, put the binary somewhere already on PATH, and create the devp
alias — three things unzipping an archive does not do.
| You are on | Run this |
|---|---|
| Windows (PowerShell) | iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex |
| Windows (Command Prompt) | powershell -NoProfile -ExecutionPolicy Bypass -Command "iwr -useb https://devprune.vkrishna04.me/install.ps1 | iex" |
| macOS / Linux | curl -fsSL https://devprune.vkrishna04.me/install.sh | sh |
| Python tooling | uv tool install dev-prune==1.16.0 / pipx install dev-prune==1.16.0 |
| Rust, no compile | cargo binstall dev-prune@1.16.0 |
| Rust, from source | cargo install dev-prune --version 1.16.0 (needs Rust 1.88+) |
The PyPI packages contain these same binaries rather than downloading one
afterwards, so they work behind a registry mirror and offline. cargo install
is the only channel that compiles on your machine; cargo binstall reaches
for the archives on this page instead.
Full instructions: https://devprune.vkrishna04.me/#install
The assets, then
Take one only if you are packaging dev-prune yourself, air-gapping it, or
pinning it into a container image.
| Asset | For |
|---|---|
dev-prune-v1.16.0-windows-x64.zip |
Windows on Intel/AMD — almost every Windows PC |
dev-prune-v1.16.0-windows-arm64.zip |
Windows on ARM — Surface Pro X, Snapdragon laptops, Windows in a Mac VM |
dev-prune-v1.16.0-windows-x86.zip |
32-bit Windows — locked-down corporate images, older industrial machines |
dev-prune-v1.16.0-darwin-arm64.tar.gz |
Apple Silicon Macs — M1 and later |
dev-prune-v1.16.0-darwin-x64.tar.gz |
Intel Macs — 2020 and earlier |
dev-prune-v1.16.0-linux-x64.tar.gz |
Linux on Intel/AMD |
dev-prune-v1.16.0-linux-arm64.tar.gz |
Linux on ARM — Raspberry Pi 4/5, Graviton, ARM CI runners |
Both Linux builds are statically linked against musl, so they run on any
distribution including Alpine, with no glibc floor.
32-bit is published for Windows only. There is no 32-bit Linux, no 32-bit
macOS and no 32-bit ARM build on any platform; the install scripts refuse
rather than guess when they meet one.
There is no .vsix on this page. The VS Code extension has its own
version and its own release cadence, so it ships from its own tags:
the extension's releases.
Install it by name instead — VKrishna04.dev-prune, on the
VS Code Marketplace
and on Open VSX.
Windows: the binaries are not code-signed, and two separate features react
to that.
Windows protected your PC is SmartScreen, and it only challenges files
carrying a Mark of the Web — which your browser attaches to the download and
File Explorer copies onto everything it extracts. Clear the mark on the archive
before extracting and nothing inside it is ever marked:
Unblock-File .\dev-prune-v1.16.0-windows-x64.zipThe installers above already do this for you, on the archive and on both
installed copies.
A refusal with no dialog and no "run anyway" is something else: Smart App
Control, which blocks unsigned executables outright and never looks at the mark.
It is on by default on clean installs of Windows 11 22H2+ and always off on
upgraded ones, which is why the same release runs on one machine and not the
next. Unblock-File does not help, and neither does building from source.
The troubleshooting guide
covers what your options actually are.
Every archive ships a .sha256 sidecar. Check it before you trust it:
sha256sum -c dev-prune-v1.16.0-linux-x64.tar.gz.sha256...