npkill alternatives: beyond the supervised sweep
npkill is good at what it does. What to reach for when you need more than node_modules, a pass that runs itself, or a check stronger than last-modified.
If npkill is working for you, keep it. For a one-off, supervised sweep
of node_modules it is hard to beat: run npx npkill, watch it find
every install tree under the current directory, sort by size, check the last-modified
column, and delete with a keypress. Nothing below improves on that workflow for that job.
People search for an alternative when the job changes. It usually changes in one of three ways, and each one points at a different tool.
"My disk is not just node_modules"
npkill is built around one directory name. There is a flag to point it at another
(--target), but the workflow stays one name at a time, and a Python
.venv, a Go vendor/, a Composer vendor/ and an
Elixir deps/ are four more scans you will not run.
Two tools cover the multi-ecosystem case. kondo keeps npkill's interactive shape: it recognises twenty-odd project types in one binary, shows what each costs, and deletes what you confirm. dev-prune covers thirty-five package managers, but changes the shape instead: it is built to run without you, which is the next section.
"I want this to stop being a chore"
npkill is interactive by design, which means it runs exactly as often as you remember to run it. If the real problem is that the machine fills up again every couple of months, the fix is not a better interactive tool, it is a pass that runs on a schedule and can be trusted to run unattended.
Unattended is the case dev-prune was written for, and it is why the safety model is
different: a background pass cannot ask you to eyeball a row, so every deletion is
preceded by the package manager's own check. devp setup registers the pass
with Task Scheduler, launchd or systemd; devp run only considers repositories
with no commit or working-tree change past your idle threshold; and every directory is
verified against its lockfile before it goes.
"Last week I deleted something that did not come back"
npkill's safety signal is the last-modified date, and the honest thing to say about
last-modified is that it measures when a file changed, not whether the directory can be
rebuilt. A node_modules holding a package that was installed without being
recorded in the lockfile looks identical to one that reinstalls cleanly, right up until
you delete it.
dev-prune runs npm ci --dry-run --ignore-scripts (or the pnpm, yarn or bun
equivalent) before touching anything, keeps the directory when that exits non-zero, and
records what it removed so devp restore --last-run can put the whole pass
back. Stress-testing dev-prune shows the
round-trip on real installs, byte for byte.
Trying it takes one dry run
curl -fsSL https://devprune.vkrishna04.me/install.sh | sh
devp init ~/Code
devp run --dry-run
The dry run deletes nothing and prints every candidate with the lockfile that proves it
rebuildable. The fuller comparison, including cargo-sweep,
rimraf and a cron job, is at
dev-prune vs the alternatives.
Common questions
What is the best alternative to npkill?
It depends which limit you hit. For interactive cleanup across more ecosystems than Node, kondo. For an unattended, scheduled pass that verifies each directory against its lockfile before deleting and can restore what it removed, dev-prune. For one directory in front of you, rm -rf remains faster than any tool.
Can npkill run automatically on a schedule?
Not usefully: it is an interactive terminal UI by design, and that is a strength for the supervised case rather than a flaw. If you want scheduled cleanup, use a tool built for it. dev-prune registers a pass with Task Scheduler, launchd or systemd, gates on repository idleness, and verifies lockfiles before every deletion.
Does npkill handle Python virtualenvs or Rust target directories?
Its scan is built around node_modules, with a --target flag that can point it at one other directory name at a time. For .venv, vendor/, deps/ and Pods/ in one pass you want kondo (interactive) or dev-prune (unattended), both of which recognise those project types natively.