My disk filled up last week. Not from anything I was actively working on — from the graveyard of projects in ~/code. Forty-odd repos, each carrying a node_modules I haven't touched in months, a target/ from that Rust experiment, a .venv here, a .next there. Tens of gigabytes of stuff that a single command would regenerate, just… sitting there.
The annoying part isn't deleting it. It's finding it. du -sh */node_modules only catches Node. Then you do it again for .venv, again for target, again for __pycache__. Different command, different ecosystem, every time.
So I built diskreap — one zero-dependency command that finds reclaimable build artifacts and dependency caches across every language at once, shows you what's eating your disk, and deletes only what's safely regenerable.
npx diskreap # scan the current directory
# or
pip install diskreap
Why not just npkill / kondo?
They're good — I used both. But each covers one corner:
-
npkill is
node_modules-only. - kondo is great and multi-language, but it's a Rust binary you have to install first.
diskreap runs instantly with npx (or pipx run diskreap), needs nothing installed, and reaches every ecosystem in a single scan: node_modules, .venv/venv, __pycache__, .pytest_cache, .mypy_cache, .ruff_cache, .next, .nuxt, .svelte-kit, .turbo, .parcel-cache, target, .gradle, vendor, dist/build, .terraform, Pods.
Using it
Scan first — it never deletes without being asked:
$ diskreap scan ~/code
/Users/you/code
1.2 GB Rust/Maven build scanner/target · 5d ago
412 MB Node deps webapp/node_modules · 3w ago
88 MB Python venv ml-notes/.venv · 2mo ago
────────────────────────────────────────────────
total reclaimable: 1.7 GB across 12 dir(s)
Then reclaim, with filters to scope the sweep:
diskreap clean ~/code --dry-run # preview exactly what would go
diskreap clean ~/code --older 60d # only long-idle projects
diskreap clean ~/code --min 100MB # skip the small fry
diskreap clean ~/code --yes # no prompt (CI / scripts)
--json is there too, if you want to pipe the scan somewhere.
The one design decision that mattered: safety
The scary names are the generic ones. node_modules is unambiguous — but target, dist, build, vendor could just as easily be your folders.
So diskreap only treats a generic name as reclaimable when a sibling project file proves its origin: target/ counts next to a Cargo.toml or pom.xml; dist/ and build/ count next to a package.json/pyproject.toml/setup.py; vendor/ next to a composer.json/go.mod. A bare build/ of your own files is never touched. Symlinks are never followed, and clean always confirms unless you pass --yes.
It's also genuinely zero-dependency — pure Node stdlib and pure Python stdlib, same logic in both, byte-for-byte aligned output. No supply chain, nothing to audit.
Try it
npx diskreap # Node
pipx run diskreap # Python
- npm: https://www.npmjs.com/package/diskreap
- PyPI: https://pypi.org/project/diskreap/
- GitHub: https://github.com/jjdoor/diskreap
What's the most disk you've ever clawed back from a single ~/code sweep? And which artifact dir surprised you the most — for me it's always .gradle. 👇
Top comments (0)