If you work across multiple JavaScript projects on a Mac, you have probably noticed that disk space quietly disappears even after you delete a project folder. The culprit is often pnpm's global content-addressable store, and the fix is a single command: pnpm store prune. This article explains exactly what the store is, where it lives, how much space it can consume, and how to clean it safely without breaking any of your active projects.
What Is the pnpm Content-Addressable Store?
Unlike npm or Yarn, pnpm never duplicates a package file. Instead, every file for every version of every package you have ever installed lives exactly once inside a global store directory. Projects do not get their own copy — their node_modules directories contain hard links (or reflinks on APFS) back to those store files. This design is why pnpm is so fast and why it saves space across active projects. The trade-off is that the store grows continuously over time, and files for deleted or upgraded projects remain behind as orphans.
Default Store Location on macOS
On Apple Silicon and Intel Macs running macOS Sequoia or Tahoe, the store sits at:
~/.local/share/pnpm/store/v3— the default for pnpm 8 and 9 (most users)~/Library/pnpm/store/v3— older installs or installs configured viaPNPM_HOME
You can always confirm your exact path by running:
pnpm store path
The output is the directory you will want to inspect before and after pruning.
How Large Does the Store Get?
The store size depends entirely on how many projects and package versions have passed through your machine. On a Mac used for active JavaScript development, sizes in the following ranges are common:
| Usage Profile | Typical Store Size | Notes |
|---|---|---|
| Light (1-2 small projects) | 200 MB – 800 MB | Few dependencies, infrequent upgrades |
| Moderate (several active repos) | 1 GB – 4 GB | React, Next.js, Vite typical stacks |
| Heavy (many repos, frequent updates) | 5 GB – 15 GB+ | Multiple framework versions, monorepos |
| After pruning (same machine) | 50–80% of prior size | Only packages referenced by remaining node_modules are kept |
The exact savings depend on how many old package versions you have accumulated. Upgrading a monorepo from React 17 to React 18 across ten packages, for example, can leave hundreds of React 17 file entries in the store that are no longer referenced by any live node_modules directory.
How pnpm store prune Works
pnpm store prune performs a reachability scan. It walks every node_modules/.modules.yaml and node_modules/.pnpm directory it can find on the filesystem and builds a set of all store paths currently referenced by a live installation. Any store entry not in that set is considered unreferenced and is deleted. Because hard links are used, deleting an entry only frees disk space when the link count on that inode reaches zero — meaning no node_modules directory on your machine still points to that file. The prune command handles all of that automatically.
What It Does NOT Delete
- Files that are still hard-linked into any surviving
node_moduleson your Mac - Your
pnpm-lock.yamlfiles orpackage.jsonfiles — those are never touched - The store metadata or index structures that pnpm needs to operate
How to Run pnpm store prune: Step-by-Step
-
Check your current store size so you have a before/after reference:
du -sh $(pnpm store path) -
Optionally delete project-level node_modules you no longer need. The more stale
node_modulesdirectories you remove first, the more the prune can clean up. For any project you no longer actively run, delete itsnode_modulesfolder before pruning:rm -rf /path/to/old-project/node_modules -
Run the prune command:
pnpm store prunepnpm will scan your filesystem and remove orphaned packages. On a large store this can take 30–90 seconds. The command prints the number of packages removed and the space freed.
-
Verify the result:
du -sh $(pnpm store path)Compare this to the size you noted in step 1.
-
Confirm your projects still work. Run
pnpm installinside one of your active projects. pnpm will re-download any store entry it needs — but in practice, nothing referenced by a livenode_modulesshould have been removed, so installs should complete instantly from cache.
Is It Safe? Understanding the Risk
Running pnpm store prune is safe as long as you understand one edge case: the scan is filesystem-wide, but only for directories that pnpm knows how to discover. If you have a project on an external drive that is not currently mounted, or inside a container image, those node_modules directories will not be counted as live. After pruning, when you bring that project back online and run pnpm install, pnpm will simply re-download the missing packages from the registry. You will not lose code, configuration, or lock files — only cached binaries, which are always re-fetchable.
In short: pnpm store prune is the equivalent of clearing a download cache. The worst realistic outcome is a slightly slower next install for an unmounted project.
The Bigger Picture: pnpm Is Not Your Only Space Consumer
Even after pruning the pnpm store, developers on macOS often find that their disks remain surprisingly full. The pnpm store is one of several developer caches that accumulate silently. Other common culprits include:
~/Library/Caches/— application caches for browsers, Xcode simulators, CocoaPods, Homebrew, and more~/Library/Developer/Xcode/DerivedData/— compiled Xcode build artifacts, often 10–30 GB on active iOS/macOS projects~/.cargo/registry/and~/.cargo/git/— Rust crate source and git checkouts~/.m2/repository/— Maven local repository for Java/Kotlin projects~/.gradle/caches/— Gradle build caches- Orphaned
node_modulesfrom npm and Yarn projects (these are not touched bypnpm store prune)
If you want to see the full picture without hunting through Terminal, a tool like Crumb can audit all of these locations at once and show what is safe to delete before you remove anything. For a broader walkthrough of what developer caches tend to balloon, see the guide on cleaning up node_modules on Mac.
Automating pnpm store prune on macOS
Running the prune manually every few weeks is a reasonable cadence for most developers. If you prefer automation, you can schedule it with a launchd plist or a simple cron entry. Because the command is idempotent and safe, running it automatically poses no risk to your projects.
A minimal cron entry to run the prune every Sunday at 3 AM:
0 3 * * 0 /usr/local/bin/pnpm store prune >> ~/Library/Logs/pnpm-prune.log 2>&1
Replace /usr/local/bin/pnpm with the output of which pnpm on your system. On Apple Silicon Macs that installed pnpm via Homebrew, the path is typically /opt/homebrew/bin/pnpm.
Comparing pnpm Store Management Commands
pnpm ships three store-related commands and it is worth understanding how they differ before you run any of them:
pnpm store path— prints the absolute path to the store directory; no data is modifiedpnpm store prune— removes unreferenced package files; the only safe routine-maintenance commandpnpm store verify— checks the integrity of stored files by recomputing checksums; useful after a storage error but can be slow on large stores
There is no built-in "nuke the entire store" command, which is intentional. If you truly want to wipe everything and start fresh, you can delete the store directory manually after checking its path with pnpm store path, then run pnpm install in each project to repopulate it. This is rarely necessary outside of troubleshooting a corrupted store. For a broader look at recovering disk space across your whole Mac, the how to free up space on Mac guide covers both developer and non-developer sources.