lysosome

Guide · build artifacts

Find and delete old node_modules, target and .venv folders safely

Updated · Scott Havird

short answer

Find the big ones with find ~/code -type d -name node_modules -prune -exec du -sh {} + | sort -h (swap in target, .venv and so on), confirm each is git-ignored with git check-ignore -v, and delete the ones in projects you aren't working on. They come back with the next npm install, cargo build or uv sync.

What takes the space

Every project you have ever installed or built keeps its dependencies and build output next to the source. They are rebuildable by design, which is why they are git-ignored, and they are often far larger than the code itself:

FolderWhat it isGetting it back
node_modulesJavaScript dependenciesexpensive a re-download (npm ci, pnpm install)
.venv, venvPython virtual environmentsexpensive a re-install (uv sync, pip install -r)
PodsCocoaPods dependenciesexpensive pod install
targetRust (and Maven) build output, often several GB per projectregenerable the next build
.next, .nuxt, .svelte-kit, .turbo, .parcel-cache, .expoFramework build cachesregenerable the next dev server or build
dist, build, .build, .gradle, .dart_tool, coverageBuild output and tool stateregenerable the next build or test run

Agent worktrees multiply this: each worktree gets its own install and build. See cleaning up dormant git worktrees.

Measure them by hand

The 20 largest node_modules folders under ~/code. -prune stops find from descending into each match, so nested node_modules aren't counted twice:

find ~/code -type d -name node_modules -prune -exec du -sh {} + 2>/dev/null | sort -h | tail -20

The same for Rust and Python:

find ~/code -type d -name target -prune -exec du -sh {} + 2>/dev/null | sort -h | tail -20
find ~/code -type d \( -name .venv -o -name venv \) -prune -exec du -sh {} + 2>/dev/null | sort -h | tail -20

A folder called build or target isn't always output: some projects keep source there. Before deleting, ask git whether the folder is ignored, and check when the project was last touched:

cd ~/code/old-project
git check-ignore -v node_modules target .venv   # prints the matching .gitignore rule, or nothing
git log -1 --format=%cr                         # e.g. "7 months ago"

Delete them safely by hand

rm -rf node_modules   # reinstall later with npm ci / pnpm install / yarn
cargo clean           # Rust: removes target/
rm -rf .venv          # recreate with uv sync, or python3 -m venv .venv && pip install -r requirements.txt

How lysosome does it

lysosome scan ~/code                       # read-only: idle projects' artifacts, largest first
lysosome scan ~/code --days 180            # only projects idle 180+ days
lysosome clean ~/code --artifacts          # dry run: build output only (cheap to rebuild)
lysosome clean ~/code --artifacts --tier regenerable_expensive --older-than 90d
                                           # also node_modules, .venv, Pods, idle 90+ days
lysosome clean -i                          # pick items in a checklist, then confirm

lysosome looks for node_modules, .venv, venv, target, .next, .nuxt, .svelte-kit, .turbo, dist, build, .gradle, Pods, .dart_tool, .build, coverage, .parcel-cache and .expo inside every repository under the folders you give it, and a folder only counts if git check-ignore confirms it. A project is idle when its last commit and its git index, HEAD and reflog are all older than --days (30 by default).

Dependencies (node_modules, .venv, venv, Pods) are tier regenerable_expensive, so a plain clean leaves them alone until you add --tier regenerable_expensive. Before moving anything, clean re-checks that the folder still exists, is still ignored, isn't a symlink and holds no .git, and that the project is still idle. Folders go to the Trash (--permanent deletes instead), and every action is logged.