Find and remove orphan node_modules on a Mac

REVIEW build-cache

A node_modules directory is reproducible from its project's package.json and one install command. The ones worth removing are orphans: the project is gone, or nothing in it has changed for a long time.

What it is

Everything a compiler or a package manager wrote so it would not have to do the work twice: Xcode DerivedData and Archives, node_modules directories, __pycache__, .gradle, Rust target/ directories, and the virtual disk Docker Desktop stores its images in.

What it is for

It makes the second build faster than the first. On a developer's Mac it is usually the single largest reclaimable category, and none of it is source code: every byte is reproducible from a repository and a build command.

Is it safe to delete?

Yes for the build outputs, which Broza moves to quarantine; the next build recreates them. The Docker virtual disk is the exception: Broza only reports its size and points at docker system prune, because shrinking that file is Docker's job, not a file manager's.

What Broza counts as an orphan

A leaf node_modules directory is orphan when it is not tool-managed and either its parent has no package.json (the project is gone), or none of the project's other entries changed for the --unused-after period (one year by default).

Tool-managed directories are left out: anything under ~/Library (package-manager stores such as pnpm's), under a hidden directory (~/.vscode/extensions, ~/.npm/_npx, ~/.cache) or inside an .app bundle. In monorepos only leaf node_modules are proposed. Orphans are rated REVIEW and moved to quarantine, never deleted outright.

Check it on your Mac

Broza is a free, open-source command-line tool. Every command below is read-only except clean, and clean is a dry run until you add --apply.

broza suggest --category build-cache --unused-after 6m
broza clean --category build-cache

Not installed yet? Install Broza with Homebrew, the installer script, or Cargo.

Related guides