How to Delete node_modules Recursively on a Mac
Delete node_modules recursively on a Mac with one find command: list and size every folder first, skip the ones you need, and clear npm and pnpm caches.
Updated · 7 min read
To delete node_modules recursively on a Mac, cd into your projects folder and run find . -type d -name node_modules -prune -exec rm -rf {} +. Run it without -exec rm -rf {} + first to list what will go. Every folder comes back with npm install or pnpm install, so stale projects are safe to clear.
TL;DR
cd ~/code # your projects folder, never / or ~
# 1. List every node_modules folder, biggest first
find . -type d -name node_modules -prune -exec du -sh {} + | sort -hr
# 2. Delete them all
find . -type d -name node_modules -prune -exec rm -rf {} +
- Scope it to the folder that holds your projects. Global tools and editor extensions also use
node_modules. - The package manager caches (
~/.npm, the pnpm store) are separate and have their own clean commands. - On pnpm, most of the space is in the store, not in each project.
Can I delete the node_modules folder?
Yes. node_modules is a build artifact. Your dependencies are defined by package.json and pinned by the lockfile (package-lock.json, pnpm-lock.yaml, yarn.lock or bun.lock), and reinstalling recreates the folder.
What you actually give up:
- Time and bandwidth. The next install downloads anything that is not already in your package manager’s cache.
- Native builds. Packages with native code may compile again on install.
- Hand edits. Anything you changed directly inside
node_modulesis gone. Patches made withpatch-packageorpnpm patchare stored outside it and re-applied on install. - Offline work. If you are about to go offline, keep the projects you need.
Why node_modules takes up so much space
Every project gets its own dependency tree, including transitive dependencies, TypeScript type packages, prebuilt native binaries for your platform and build tools. A single React Native or Next.js project can reach several gigabytes.
With npm, each project’s node_modules holds real copies of every file. Ten projects on the same framework store that framework ten times. Git worktrees multiply it again, because each worktree usually gets its own node_modules. If you use worktrees, see how to remove and prune git worktrees.
How to find every node_modules folder
List them
cd ~/code
find . -type d -name node_modules -prune
-prune is the important part. It stops find from descending into a node_modules folder once it has found one, so you get only the top-level folder for each project, not the hundreds of nested node_modules inside it. It also makes the search much faster.
See how big each one is
find . -type d -name node_modules -prune -exec du -sh {} + | sort -hr
Get a single total
find . -type d -name node_modules -prune -print0 | xargs -0 du -sch | tail -1
Treat these numbers as an upper bound if you use pnpm or Bun. The section on APFS clones below explains why du can overcount.
Find only stale projects
To list folders whose top level has not changed in 30 days (roughly, projects you have not installed into for a month):
find . -type d -name node_modules -prune -mtime +30
A folder’s modification time changes when entries are added or removed directly inside it, which happens on install. It is a reasonable proxy for “not touched lately”, not a guarantee.
How to delete node_modules recursively
Delete all of them
After checking the list:
find . -type d -name node_modules -prune -exec rm -rf {} +
Delete only stale ones
find . -type d -name node_modules -prune -mtime +30 -exec rm -rf {} +
Move them to the Trash instead
Recent macOS versions include a trash command (check with which trash). It lets you undo the cleanup until you empty the Trash:
find . -type d -name node_modules -prune -exec trash {} +
Moving tens of thousands of small files to the Trash is slower than rm -rf, and the space is not freed until you empty it.
Delete node_modules in a single project
rm -rf node_modules
Where not to run it
Do not run these commands from / or from your home folder. node_modules folders also live in places your tools depend on, for example:
- Global npm packages, such as
/opt/homebrew/lib/node_modules(Homebrew Node) or~/.nvm/versions/node/<version>/lib/node_modules(nvm) - Editor extensions, such as those under
~/.vscode/extensionsor~/.cursor/extensions - App bundles and other tools that ship their own JavaScript dependencies
Run find from the folder that holds your projects, such as ~/code or ~/Developer.
What about npkill?
npkill is an open-source interactive tool that does the same search and shows the results in your terminal. You move through the list and delete folders one at a time:
npx npkill
It is a good fit if you prefer choosing project by project. npx downloads the package from npm the first time you run it. The find commands above do the same job with nothing to install.
Clean the package manager caches too
Deleting node_modules does not touch the caches your package manager keeps so that reinstalling is fast. Those can be several gigabytes on their own.
npm
npm keeps its cache in ~/.npm (see npm config get cache), with package data in ~/.npm/_cacache.
du -sh ~/.npm
npm cache verify # checks the cache and garbage-collects unneeded data
npm cache clean --force # deletes the cache entirely
pnpm
pnpm store path # e.g. ~/Library/pnpm/store/v10 with pnpm 10 on macOS
du -sh "$(pnpm store path)"
pnpm store prune # removes packages no project references anymore
pnpm store prune is safe: it only removes unreferenced packages. Per pnpm’s own help, the cost is that future installs may need to download those packages again.
Yarn and Bun
On most setups, yarn cache clean clears Yarn’s cache and bun pm cache rm clears Bun’s global cache. Run yarn cache dir to see where Yarn keeps it before deleting.
Why pnpm saves space (and what APFS clones change)
pnpm stores each version of each file once, in a content-addressable store shared by all projects. A project’s node_modules does not get its own copies. pnpm’s default import method, auto, tries to clone files from the store first, falls back to hard links when cloning is not supported, and copies only as a last resort.
On a Mac, APFS supports clones (copy-on-write files). A clone looks like a normal, independent file, but it shares its data blocks with the original until one of them is modified. On our test Mac, files inside a pnpm project’s node_modules/.pnpm had a link count of 1 (stat -f %l), consistent with clones rather than hard links.
That has three practical consequences:
duand Finder overcount. Both report a clone’s full size, even though the blocks are shared with the store. Ten pnpm projects can each show 2 GB while together using little more than the store itself.- Deleting one pnpm project’s node_modules frees little. The shared blocks stay on disk as long as the store or another project still references them.
- The real space is reclaimed by pruning the store, after removing the projects you no longer need.
Bun also uses clones on macOS by default on most setups, so the same caveat about du applies. npm writes real copies, so with npm, du is accurate and deleting node_modules frees what it reports.
node_modules and caches at a glance
| Path | What it is | Safe to delete? | How it comes back |
|---|---|---|---|
<project>/node_modules |
Installed dependencies for one project | Yes | npm install, pnpm install, yarn, bun install |
~/.npm/_cacache |
npm download cache | Yes | Refilled on next install |
~/Library/pnpm/store |
pnpm content-addressable store | Prune it; deleting it forces full re-downloads | Refilled on next install |
/opt/homebrew/lib/node_modules, ~/.nvm/.../lib/node_modules |
Global npm packages | No, unless you mean to uninstall them | Reinstall with npm i -g |
| Editor extension folders | Extension dependencies | No | Reinstall the extension |
For the rest of a developer Mac, see the guide to freeing up space on a Mac for developers. If Docker is part of your JavaScript workflow, shrinking Docker.raw is usually the next biggest win.
Do it in one click with DevCleanup
DevCleanup’s Projects screen finds every node_modules folder across your projects with its real size and lets you clear the ones you pick in one go. Sizes are real-space numbers: APFS clones and hard links are not double counted, so pnpm and Bun projects show what deleting them will actually free. DevCleanup never deletes a git repository, and every action is logged in History with how to restore it. Scanning is free; developer cleanup actions are part of Pro ($29 one-time).
Frequently asked questions
Can I delete the node_modules folder?
Yes. node_modules is rebuilt from package.json and your lockfile by running npm install, pnpm install, yarn or bun install. You only lose time and bandwidth, plus any manual edits made directly inside node_modules.
What is the command to delete node_modules in every project?
From your projects folder, run find . -type d -name node_modules -prune -exec rm -rf {} +. Run the same find without the -exec part first to see exactly which folders it will remove.
Why is node_modules so big?
Every project installs its own full dependency tree, including transitive dependencies, TypeScript types, native binaries and build tools. With npm, each project has its own copy of every file, so ten projects using the same framework store it ten times.
Does deleting node_modules free space if I use pnpm?
Less than you might expect. pnpm keeps one copy of each file in a global store and links or clones it into each project, so most of the space lives in the store. Run pnpm store prune to remove packages no project references anymore.