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:
| Folder | What it is | Getting it back |
|---|---|---|
node_modules | JavaScript dependencies | expensive a re-download (npm ci, pnpm install) |
.venv, venv | Python virtual environments | expensive a re-install (uv sync, pip install -r) |
Pods | CocoaPods dependencies | expensive pod install |
target | Rust (and Maven) build output, often several GB per project | regenerable the next build |
.next, .nuxt, .svelte-kit, .turbo, .parcel-cache, .expo | Framework build caches | regenerable the next dev server or build |
dist, build, .build, .gradle, .dart_tool, coverage | Build output and tool state | regenerable 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
- Only delete ignored folders. If
git check-ignoreprints nothing, the folder is tracked or unknown to git. Leave it. - Don't reach for
git clean -fdX. It deletes every ignored file, including.envfiles, local databases and editor settings. If you use it at all, preview first withgit clean -ndX. - Prefer projects you aren't using. Deleting dependencies in an active project only costs you a re-install; in an old one it costs nothing until you return.
- Use the Trash when unsure. Dragging a folder to the Trash in Finder keeps it recoverable until you empty it.
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.