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.

Updated 2026-09-20

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.