How to delete old node_modules folders on a Mac
Every JavaScript project keeps its own copy of its dependencies, and a few hundred megabytes each adds up fast, especially when an AI tool has helped you start a new project every week. Here's how to find them, what's safe to remove and how to do it without losing work.
Is it safe to delete node_modules?
Almost always. node_modules is rebuilt from your package.json and lockfile the next time you run npm install, pnpm install, yarn or bun install. Your source code isn't inside it.
The exceptions are worth knowing before you delete in bulk:
- No lockfile. Without
package-lock.json,pnpm-lock.yaml,yarn.lockorbun.lock, a reinstall may pick newer versions than the ones the project last worked with. - Hand edits. If someone patched a file inside
node_moduleswithoutpatch-packageorpnpm patch, that edit is lost. - Offline or removed packages. A reinstall needs the registry, and a private or unpublished package may not come back.
- Projects you're using this week. You'll wait for the reinstall. Old projects are the ones worth clearing.
Find every node_modules folder and its size
In Terminal, from the folder that holds your projects (here ~/dev; use yours):
find ~/dev -name node_modules -type d -prune -print0 | xargs -0 du -sh | sort -h
-prune stops find descending into each node_modules, so nested ones aren't counted twice and the command finishes quickly. The largest folders are listed last.
To list only projects where nothing near the top has changed in 30 days (a rough test, but a quick one), check the project's own files rather than node_modules:
find ~/dev -name node_modules -type d -prune | while read -r nm; do
project=$(dirname "$nm")
if [ -z "$(find "$project" -maxdepth 2 -mtime -30 -not -path '*/node_modules*' -print -quit)" ]; then
du -sh "$nm"
fi
done
Check the project's work is saved first
Deleting node_modules doesn't touch your code, but clearing out old projects is usually the moment people delete the whole folder too. Before you do, check each one's Git state:
cd ~/dev/my-project
git status --short # changes that aren't committed
git log --branches --not --remotes --oneline # commits that aren't pushed anywhere
If either prints anything, that work exists only on your Mac.
Delete them
One project:
rm -rf ~/dev/my-project/node_modules
Every node_modules under a folder (review the list from the first command before you run this; rm -rf skips the Trash):
find ~/dev -name node_modules -type d -prune -exec rm -rf {} +
Commands like these remove files permanently. If you'd rather be able to change your mind, move folders to the Trash in Finder instead.
Don't forget the package caches
Package managers also keep a shared download cache, separate from each project:
| Manager | Cache | Clear it with |
|---|---|---|
| npm | ~/.npm/_cacache | npm cache clean --force |
| pnpm | ~/Library/pnpm/store | pnpm store prune |
| Yarn | ~/Library/Caches/Yarn | yarn cache clean |
| Bun | ~/.bun/install/cache | bun pm cache rm |
Build output is worth a look too: .next, dist, .turbo and .parcel-cache in old projects are rebuilt by the next build.
How ElfClean does it
ElfClean looks in the project folders you choose and offers node_modules, .next, build folders, Rust target and Python virtual environments in projects you haven't touched for 30 days. Recent projects start unticked.
Each project shows its Git state. A project with changes that aren't committed or pushed anywhere is marked At risk and never ticked for you, and it's checked again just before anything is removed. Everything goes to the Trash, and History can put it back.
More guides
- Where Ollama and Hugging Face store models on a Mac, and how to remove them
- What Claude Code, Codex and Cursor leave on your Mac
- How to clear Xcode DerivedData, simulators and device support
- What System Data is on a Mac, and how to make it smaller
- How to find large files and duplicates on a Mac
- How to free up Docker disk space on a Mac
- Clear pip, uv, Homebrew, Cargo and other caches on a Mac
- Mac cleaners for developers compared: CleanMyMac alternatives