Developers · · 11 min read

A Developer's Guide to Reclaiming Disk Space

Reclaim disk space as a developer: safely clear node_modules, Docker images and volumes, package caches for npm, pip, gradle, cargo, go, plus Xcode and .venv.

If you write code, your disk fills up faster than anyone’s. Every project spawns a node_modules folder the size of a small OS, every docker build layers gigabytes of images, and every package manager keeps its own ever-growing cache. The good news: almost all of it is regenerable — build artifacts and caches rebuild from your source and lockfiles, so a developer can usually reclaim disk space in the tens of gigabytes without touching a single real file. This guide is the safe, comprehensive playbook, tool by tool.

First rule: source is sacred, artifacts are disposable

The mental model that keeps you safe is a hard line between two things:

  • Sources of truth — your source code, package.json, lockfiles (package-lock.json, Cargo.lock, poetry.lock), Dockerfiles, config. Never delete these.
  • Derived artifactsnode_modules, dist/, build/, target/, .gradle, DerivedData, Docker images, package caches. These are reproducible from the sources above. Safe to delete; you pay only rebuild time.

Everything below is about deleting the second category confidently while never risking the first.

node_modules — the classic offender

A single node_modules can be hundreds of MB; a machine with dozens of old projects can have 20+ GB tied up in them. They regenerate with npm install (or yarn/pnpm) from your lockfile.

Find and size them across your projects:

# List every node_modules under ~/code with its size
find ~/code -type d -name node_modules -prune -print0 |
  xargs -0 du -sh 2>/dev/null | sort -rh | head -20

Delete the ones in projects you’re not actively working on:

# Safe: regenerates with `npm install`. Confirm the path first!
rm -rf ~/code/old-project/node_modules

Safety caveat: rm -rf has no undo. Only ever target a path ending in /node_modules, never a bare project or home directory, and confirm the project has its lockfile committed so you can reinstall. If you want the deeper story on why this is safe and the edge cases, we cover it in the dedicated node_modules post on the blog.

Docker — usually the single biggest win

Docker quietly hoards images, stopped containers, unused volumes, and build cache. Start by measuring:

docker system df        # summary of images, containers, volumes, build cache
docker system df -v     # per-item detail

Then reclaim in increasing order of aggressiveness:

# Remove stopped containers, unused networks, dangling images, build cache
docker system prune

# Also remove ALL images not used by a running container
docker system prune -a

# Volumes are never auto-removed — this clears unused ones
docker volume prune

Safety caveat — this matters: system prune -a costs only re-pull/rebuild time. But docker volume prune deletes data — databases, uploads, anything persisted in a volume. A volume “unused” right now may hold your local dev database. Prune volumes only when you’re certain, and back up any you care about first. Build cache (docker builder prune) is always safe to clear.

Package-manager caches

Every language ecosystem caches downloaded packages so it doesn’t re-fetch them. These are pure caches — safe to clear, re-downloaded on next install. The only cost is bandwidth and time next time.

EcosystemCache location (typical)Clear command
npm~/.npmnpm cache clean --force
Yarn~/.cache/yarn (or yarn cache dir)yarn cache clean
pnpmpnpm store pathpnpm store prune
pip~/.cache/pippip cache purge
Gradle~/.gradle/cachesdelete subfolder / --refresh-dependencies
Maven~/.m2/repositorydelete stale artifacts (see caveat)
Cargo~/.cargo/registry, ~/.cargo/gitcargo cache tool, or clear registry cache
Go~/go/pkg/mod (module cache)go clean -modcache
Homebrew$(brew --cache)brew cleanup -s

Caveats:

  • Gradle and Maven caches also serve as your local artifact store. Clearing them forces a full re-download on the next build, which can be large. Safe, but not instant. For Gradle you can also clear old daemon logs and unused wrapper distributions under ~/.gradle.
  • Go module cache is read-only by default; go clean -modcache is the correct way to clear it (a plain rm -rf can hit permission errors).
  • Cargo registry cache regenerates, but the ~/.cargo/bin folder holds installed binaries — don’t delete that.

Build outputs in your projects

Beyond node_modules, each project leaves compiled output:

# Rust
cargo clean                     # removes ./target

# Java/Gradle
./gradlew clean                 # removes build/ outputs

# .NET
dotnet clean                    # removes bin/ and obj/

# Generic JS build output
rm -rf dist build .next .nuxt   # confirm you're in the project root!

Prefer the tool’s own clean command over rm where one exists — it knows exactly which folders are outputs and won’t touch your source.

Xcode — the macOS space vacuum

If you build on macOS, Xcode is often the biggest consumer after Docker.

# DerivedData: build intermediates and indexes — safe, regenerates on build
rm -rf ~/Library/Developer/Xcode/DerivedData/*

# Old device support files pile up per iOS version
du -sh ~/Library/Developer/Xcode/iOS\ DeviceSupport/*

# Simulators: list and delete unavailable ones
xcrun simctl delete unavailable

xcrun simctl delete unavailable safely removes simulators for OS versions you no longer have installed — often several GB. Full simulator runtimes live under ~/Library/Developer/CoreSimulator. Caveat: deleting all DerivedData means your next build is a full clean build (slower, re-indexes). That’s a time cost, not data loss.

Python virtual environments (.venv)

A .venv (or venv, env) is a regenerable environment built from your requirements.txt/pyproject.toml. Old project venvs add up.

# Find virtualenvs by their marker file
find ~/code -type f -name pyvenv.cfg -exec dirname {} \; 2>/dev/null

# Recreate later with: python -m venv .venv && pip install -r requirements.txt
rm -rf ~/code/old-project/.venv

Caveat: .venv is opt-in territory — it’s safe only if you can recreate it, which means your dependency file is committed and complete. If a project installed things ad-hoc without recording them, deleting the venv loses that setup. Confirm before deleting.

A safe developer cleanup checklist

  • Scan and size first — find the biggest offenders before deleting.
  • Commit and push so nothing uncommitted is riding inside a build folder.
  • Prefer tool clean commands (cargo clean, dotnet clean, go clean -modcache) over raw rm.
  • Only rm -rf paths that end in a known artifact folder/node_modules, /target, /.venv, DerivedData. Never a project or home root.
  • Treat Docker volumes as data, not clutter. Prune images/build cache freely; prune volumes deliberately.
  • Keep lockfiles and dependency files — they’re what make the delete reversible.
  • Prefer a recoverable delete while you build the habit.

The recurring danger here is rm -rf: it’s fast, silent, and permanent, and a mistyped or word-split path (rm -rf ~ /project) can wipe your home directory. Read every path twice, and never automate a recursive delete across a directory you haven’t scoped precisely. Much of this overlaps with system-level Linux cleanup — package caches, Docker, journald — covered in How to Clean Up Disk Space on Ubuntu & Linux Safely.

How Declutter fits a developer workflow

Doing all this by hand means memorizing a dozen tools’ cache locations and hoping you don’t fat-finger an rm -rf. Declutter knows these categories natively. Its safety engine detects developer build artifacts (node_modules, .next, dist, build, target/, .gradle, __pycache__, DerivedData, .venv as opt-in) and package-manager caches across npm/yarn/pnpm/pip/gradle/maven/cargo/go/brew, tags each with why it’s safe and how it regenerates, and never includes your source or lockfiles.

Build artifacts are a review-tier category, so they’re never pre-selected — you see the exact paths and reclaimable size, approve per phase, and everything moves to a recoverable quarantine first. If a build breaks, undo restores it instantly. No rm -rf, no surprises.

The bottom line

As a developer you’re sitting on more reclaimable space than anyone — you just have to remember that artifacts and caches are disposable while source and lockfiles are sacred. Measure first, prune Docker (carefully with volumes), clear package caches, run each tool’s own clean, and sweep old node_modules, .venv, and Xcode DerivedData. Keep every rm -rf scoped to a known artifact path, and you’ll routinely reclaim 20–100 GB with nothing lost but a bit of rebuild time.


Want a copilot that knows every dev cache by heart? Try Declutter — it finds build artifacts and package caches and removes them quarantine-first with full undo. Subscribe to our newsletter for more developer-focused disk guides.