You ran npm install and it hung, or it printed EINTEGRITY and refused to continue, or it just took twenty minutes to install what should be a small dependency tree. Somebody on Stack Overflow told you to clear the npm cache. Before you do, it is worth understanding what that cache actually is on macOS, what the two supported commands really do, and why a cache that keeps growing is usually working correctly rather than misbehaving.
This is a short tour of the npm cache: where it lives on your Mac, why it looks larger than you expect, when clearing it actually fixes a problem, and how to keep it under control on both your laptop and your CI machines.
Where npm keeps its cache on macOS
By default, npm writes its cache to ~/.npm. The subdirectory that holds package data is ~/.npm/_cacache — a content-addressable store that npm has used since version 5. Under _cacache you will find three folders:
content-v2— the actual tarball payloads, keyed by hash.index-v5— an index that maps package name and version to a content hash.tmp— temporary write buffers.
You can confirm the location on your own machine with:
npm config get cache
You can move it by setting cache=/some/other/path in ~/.npmrc, or per-run with --cache=/some/path. That is useful on CI where you want to point at a mounted volume, but on a laptop the default is fine.
Why the cache grows
Every time npm downloads a tarball for a package version it has not seen, it writes that tarball into content-v2 and adds an index entry. Because packages are stored by content hash, the same version of the same package is only stored once no matter how many projects use it. But every distinct version of every distinct package is stored separately, and the cache never expires entries on its own.
On a machine that has been doing JavaScript work for a few years, ~/.npm/_cacache can easily reach 5 to 20 GB. That is not a bug and it is not a leak. It is what happens when you install React 16, 17, 18, and 19 across a dozen projects over four years.
npm cache verify versus npm cache clean --force
The two commands look similar and they do very different things.
npm cache verify walks the cache, checks that every index entry points at real content, that every content blob's hash matches its filename, and prunes anything that does not. It also compacts the index. Nothing you care about is lost — a "pruned" entry was already garbage, either because a download was interrupted or because a package was unpublished. This is the command you want when npm is refusing to install and complaining about integrity.
npm cache verify
npm cache clean --force deletes the entire cache. The --force flag is required because npm intentionally makes it inconvenient: the cache is a performance optimisation, and if you clean it you will re-download everything on the next install. Newer npm versions self-heal from corruption, so a full clean is rarely needed.
npm cache clean --force
You should reach for verify first. Only fall back to clean --force if a verified cache still produces EINTEGRITY on a package you have not modified.
When a corrupted cache actually causes install failures
The failure mode looks like this: an install worked yesterday, you did not change your package-lock.json, and today the same command fails with EINTEGRITY or sha512-... integrity checksum failed. That is npm telling you the tarball in the cache has a hash that does not match the hash recorded in the lockfile. It can happen when:
- A partial download was killed by a network hiccup and left half a tarball on disk.
- The disk itself flipped bits (rare, but not impossible on ageing SSDs).
- A previous npm process crashed mid-write.
npm cache verify will detect all three cases and prune the bad content, after which the next install fetches fresh copies. If the failure persists after verify, the problem is not in your cache — check the registry, your .npmrc scope configuration, and any corporate proxy in between.
Safe cleanup on CI machines
CI runners have a particular relationship with the npm cache. If the runner is ephemeral (a fresh container per job), there is nothing to clean; the cache dies with the container. If the runner is reused across jobs, you want the cache to persist for install-speed reasons, but you also want it bounded.
Two safe patterns for long-lived runners:
- Run
npm cache verifyat the end of each job. It is cheap and it prevents corrupted entries from accumulating. - Cap the cache size by running
npm cache clean --forceweekly, or by mounting~/.npmon a volume with a size limit and letting new writes fail loudly.
Do not run npm cache clean --force on every job. It defeats the point of the cache and turns every install into a full re-download from the registry.
The _logs folder is separate, and worth knowing about
Alongside ~/.npm/_cacache you will see ~/.npm/_logs. Every npm install, npm run, and failed command writes a log there. These files are small individually but there is no rotation, so a busy developer machine can end up with tens of thousands of log files.
You can safely delete anything in _logs older than a month:
find ~/.npm/_logs -type f -mtime +30 -delete
npm will happily create the folder again on the next command.
Node version managers add their own copies
If you use nvm, fnm, volta, or asdf, each installed Node version has its own bundled npm and can theoretically use its own cache directory. In practice they all default to ~/.npm, so switching Node versions does not multiply your cache. What does multiply is the node_modules folder inside every project you have ever cloned. Those are on your disk under whatever path you keep code in, and they can dwarf the npm cache by an order of magnitude.
A quick way to see how much a single project weighs:
du -sh node_modules
Deleting node_modules is safe as long as you can run npm install again. On a project you have not touched in a year, that is often 500 MB you did not need.
A conservative cleanup routine
For a Mac that is running low on space and has years of Node work on it:
npm cache verifyin your home directory. Wait for the report; it usually finishes in under a minute.du -sh ~/.npmbefore and after so you can see the change.- Delete
~/.npm/_logs/*older than 30 days. - Walk your project folders and delete
node_modulesfrom anything you are not actively working on. - If, and only if,
verifystill leaves you with integrity errors on a fresh install, runnpm cache clean --forceand let the next install re-download.
You will not see multi-gigabyte wins from the cache itself unless something has gone wrong. The real space is in node_modules.
Where VolumeLens fits in
We built VolumeLens because "where did the disk go" is a question the built-in Storage screen refuses to answer. It scans your Mac, draws every folder as a rectangle sized by real on-disk usage, and — with Insights — recognises the npm cache, node_modules trees, and the two dozen other places JavaScript work quietly piles up. Nothing leaves your machine, and the only action the app takes is Move to Trash after you review the list. If you would rather see the whole shape of your disk than clean it one command at a time, try it.