Every JavaScript project keeps its own copy of its dependencies in node_modules, often a few hundred megabytes each. Projects you finished months ago keep theirs too. Removing them is safe: npm install brings them back if you return to a project.
Find them, with their sizes
In Terminal, from the folder where you keep your code (for example ~/Developer):
find . -name node_modules -type d -prune -exec du -sh {} + | sort -h-prune stops the search going inside each node_modules, which would otherwise list thousands of nested ones and take far longer. The largest appear last.
Only the old ones
To list node_modules whose project’s package.json hasn’t changed in 90 days:
find . -name package.json -not -path "*/node_modules/*" -mtime +90 -execdir test -d node_modules ; -printA package.json that hasn’t changed is a good sign a project is idle, though not proof: check the list before removing anything.
Remove them
- In Finder, drag the
node_modulesfolders you’ve chosen to the Trash. You can put them back until you empty it. - In Terminal,
rm -rf path/to/project/node_modulesremoves one immediately, with no way back. Run it inside the project folder, never on a path you haven’t checked.
Emptying the Trash is what returns the space to your disk.
Stop them piling up
- pnpm keeps one shared copy of each package and links projects to it, so many projects cost much less space than with npm.
- Package managers keep their own download caches too (npm’s
~/.npm, pnpm’s store, Yarn and Bun caches). They’re safe to clear and are fetched again when needed.
Freeing space matters beyond tidiness: macOS needs free disk space to swap, and a nearly full disk is one of the most common reasons a Mac feels slow.