JavaScript package manager caches and node_modules can consume 20-80GB on macOS. Here's how to find and clean them all.
Before cleaning anything, let's see the full picture of JavaScript-related disk usage on your Mac:
# npm cache
du -sh ~/.npm/
# Yarn Classic (v1) cache
du -sh ~/Library/Caches/Yarn/ 2>/dev/null
# Yarn Berry (v2+) global cache
du -sh ~/.yarn/berry/cache/ 2>/dev/null
# pnpm store
du -sh $(pnpm store path 2>/dev/null) 2>/dev/null
# All node_modules directories (this takes a moment)
find ~ -name "node_modules" -type d -maxdepth 5 -not -path "*/node_modules/*/node_modules" 2>/dev/null | \
xargs -I{} du -sh {} 2>/dev/null | sort -rh | head -20
# nvm Node.js versions
du -sh ~/.nvm/versions/node/*/ 2>/dev/null
# fnm Node.js versions
du -sh ~/Library/Application\ Support/fnm/node-versions/*/ 2>/dev/null
# Global npm packages
du -sh $(npm root -g) 2>/dev/null
# Total node_modules disk usage
echo "Total node_modules:"
find ~ -name "node_modules" -type d -maxdepth 5 -not -path "*/node_modules/*/node_modules" 2>/dev/null | \
xargs -I{} du -sk {} 2>/dev/null | awk '{s+=$1} END {printf "%.1f GB\n", s/1048576}'
| Cache Location | Typical Size | Safe to Delete? |
|---|---|---|
~/.npm/ | 1-10 GB | Yes (re-downloads on install) |
~/Library/Caches/Yarn/ | 1-10 GB | Yes (Yarn v1) |
~/.yarn/berry/cache/ | 500 MB-5 GB | Yes (Yarn Berry global) |
| pnpm store | 2-15 GB | Yes (re-downloads on install) |
| node_modules/ (all) | 5-50 GB | Yes (npm/yarn install recreates) |
| nvm versions | 1-5 GB | Old versions only |
# Size of npm cache
du -sh ~/.npm/
# Detailed cache info
npm cache ls 2>/dev/null | wc -l
npm cache verify
The npm cache lives at ~/.npm/_cacache/ and stores compressed tarballs of every package you've installed. It grows with every different package version you use across all projects.
# Verify cache integrity and remove corrupt entries
npm cache verify
# Nuclear option -- clear entire npm cache
npm cache clean --force
npm cache verify is usually sufficient -- it removes corrupt and unused entries while keeping valid cached packages. Only use --force if you want a completely fresh start.
# Check npm tmp directory
du -sh /tmp/npm-*/ 2>/dev/null
ls -la /tmp/npm-* 2>/dev/null
# Clean npm temp files
rm -rf /tmp/npm-*
# Check cache location and size
yarn cache dir
du -sh $(yarn cache dir)
# List cached packages
yarn cache list | head -20
# Clean entire Yarn v1 cache
yarn cache clean
Yarn Classic stores its cache at ~/Library/Caches/Yarn/ on macOS. This can grow to 5-10GB if you work on many projects.
# Yarn Berry uses per-project .yarn/cache by default (PnP mode)
# Check global cache
du -sh ~/.yarn/berry/cache/ 2>/dev/null
# Check project-local caches
find ~/Projects -name ".yarn" -type d -maxdepth 3 2>/dev/null | \
while read d; do echo "$(du -sh "$d/cache" 2>/dev/null)"; done
# Clean global Yarn Berry cache
rm -rf ~/.yarn/berry/cache/
.yarn/cache/ folder in your project IS your node_modules equivalent. Don't delete it for active projects without running yarn install after.
# Find pnpm store location
pnpm store path
# Check store size
du -sh $(pnpm store path)
# Check store status
pnpm store status
pnpm uses a content-addressable store (typically at ~/Library/pnpm/store/ on macOS) that hard-links packages into projects. This is more disk-efficient than npm/yarn, but the store still grows over time.
# Remove packages not referenced by any project on disk
pnpm store prune
# Full reset (re-downloads on next install)
rm -rf $(pnpm store path)
pnpm store prune is smart -- it only removes packages that aren't referenced by any project's node_modules on your disk. Run it periodically to keep the store lean.
node_modules directories are usually the biggest disk hog for JavaScript developers. A single project can have 200-500MB in node_modules, and if you have dozens of projects...
# Find and sort by size (largest first)
find ~ -name "node_modules" -type d -maxdepth 5 \
-not -path "*/node_modules/*/node_modules" 2>/dev/null | \
xargs -I{} du -sh {} 2>/dev/null | sort -rh
# Count total
find ~ -name "node_modules" -type d -maxdepth 5 \
-not -path "*/node_modules/*/node_modules" 2>/dev/null | wc -l
# Delete node_modules not accessed in 30+ days
find ~ -name "node_modules" -type d -maxdepth 5 \
-not -path "*/node_modules/*/node_modules" \
-not -newermt "30 days ago" 2>/dev/null -exec rm -rf {} +
# Or use npkill (interactive TUI)
npx npkill
npkill is an excellent interactive tool that lets you browse all node_modules and selectively delete them. Install with npx npkill.
# List globally installed npm packages
npm list -g --depth=0
# Size of global packages
du -sh $(npm root -g)
# Remove a specific global package
npm uninstall -g package-name
# Yarn global packages
yarn global list
du -sh $(yarn global dir)/node_modules/ 2>/dev/null
# pnpm global packages
pnpm list -g
Each installed Node.js version takes 80-200MB. If you have many versions installed via nvm or fnm, this adds up:
# List installed versions with sizes
du -sh ~/.nvm/versions/node/*/
# List all installed versions
nvm ls
# Remove a specific version
nvm uninstall v16.20.0
nvm uninstall v18.19.0
# Keep only your primary version
# Check current: nvm current
# Then uninstall others
# List installed versions
fnm ls
# Check sizes
du -sh ~/Library/Application\ Support/fnm/node-versions/*/
# Remove a specific version
fnm uninstall v16.20.0
# Check Volta tool cache
du -sh ~/.volta/
# List installed tools
volta list all
# Each tool version cached separately
du -sh ~/.volta/tools/*/
| Feature | npm | Yarn Classic | Yarn Berry | pnpm |
|---|---|---|---|---|
| Cache location | ~/.npm/ | ~/Library/Caches/Yarn/ | ~/.yarn/berry/cache/ | ~/Library/pnpm/store/ |
| Typical size | 1-10 GB | 1-10 GB | 500 MB-5 GB | 2-15 GB |
| Cleanup command | npm cache clean --force | yarn cache clean | Delete ~/.yarn/berry/cache/ | pnpm store prune |
| Auto-cleanup | No | No | No | No |
| Dedup strategy | Flat node_modules | Flat node_modules | PnP (no node_modules) | Content-addressed + hardlinks |
| node_modules size | Large | Large | None (PnP) | Small (hardlinks) |
# Add to crontab: crontab -e
# Run every Sunday at 3 AM
0 3 * * 0 ~/.scripts/js-cache-cleanup.sh >> /tmp/js-cleanup.log 2>&1
#!/bin/bash
# js-cache-cleanup.sh -- JavaScript cache maintenance
echo "=== JS Cache Cleanup $(date) ==="
# npm cache verify (safe -- keeps valid entries)
echo "npm cache verify..."
npm cache verify 2>/dev/null
# Yarn cache clean
if command -v yarn &>/dev/null; then
echo "Yarn cache clean..."
yarn cache clean 2>/dev/null
fi
# pnpm store prune
if command -v pnpm &>/dev/null; then
echo "pnpm store prune..."
pnpm store prune 2>/dev/null
fi
# Remove node_modules older than 30 days
echo "Removing old node_modules..."
find ~/Projects -name "node_modules" -type d -maxdepth 4 \
-not -path "*/node_modules/*/node_modules" \
-not -newermt "30 days ago" 2>/dev/null | while read d; do
echo " Removing: $d"
rm -rf "$d"
done
# npm temp files
rm -rf /tmp/npm-* 2>/dev/null
echo "=== Done ==="
# .git/hooks/post-checkout (mark for cleanup after switching branches)
# This removes stale node_modules when you switch to a branch
# that has different dependencies
#!/bin/bash
# Only run if package.json changed
if git diff --name-only "$1" "$2" | grep -q "package.json"; then
echo "package.json changed -- consider running npm install"
fi
npm, Yarn, pnpm, node_modules, Docker, Xcode, Homebrew, Rust, Go, Python, Gradle, CocoaPods -- all in one click.
Get ClearDisk (Free & Open Source)macOS native -- no dependencies, no tracking, no subscriptions
Yes. Package manager caches are just local copies of packages downloaded from the registry. Deleting them means the next npm install, yarn install, or pnpm install will re-download packages from the registry instead of using the local cache. Your projects and their lock files are unaffected.
No -- as long as you have a package.json and lock file (package-lock.json, yarn.lock, or pnpm-lock.yaml), running the install command will recreate node_modules identically. This is exactly what happens in CI/CD pipelines.
Typically 10-40GB for active JavaScript developers. The biggest savings come from deleting node_modules in projects you haven't worked on recently. A single project's node_modules can be 200MB-1GB+, and most devs have 10-50+ projects on their machine.
If disk space is a major concern, pnpm is the most disk-efficient option. Its content-addressable store means each package version is stored exactly once globally, and projects use hard links. This can reduce total disk usage by 50-70% compared to npm/Yarn with duplicate node_modules.
npm cache verify checks integrity and removes corrupt/unused entries -- it's safe and recommended. npm cache clean --force removes everything, requiring re-downloads. Use verify for maintenance, clean for a fresh start.
# === AUDIT ===
du -sh ~/.npm/ # npm cache
du -sh ~/Library/Caches/Yarn/ # Yarn Classic
du -sh $(pnpm store path) # pnpm store
find ~ -name node_modules -maxdepth 5 -type d | xargs du -sh | sort -rh | head
# === CLEAN ===
npm cache clean --force # Clear npm cache
yarn cache clean # Clear Yarn cache
pnpm store prune # Prune pnpm store
npx npkill # Interactive node_modules cleaner
# === NVM/FNM ===
nvm ls && nvm uninstall v16.20.0 # Remove old Node versions
fnm ls && fnm uninstall v16.20.0
# === PREVENT ===
# Use pnpm for disk-efficient installs
# Use .nvmrc to limit Node versions
# Run `npx npkill` monthly