# Use npkill to find and delete old node_modules folders

> npkill is a free terminal tool that finds every node_modules folder on your computer, shows its size and age, and deletes the ones you pick.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-10-06 | Topics: [Node.js](https://flaviocopes.com/tags/node/) | Canonical: https://flaviocopes.com/npkill/

[npkill](https://github.com/zaldih/npkill) is a free terminal tool that finds every `node_modules` folder inside a directory, shows how much space each one takes and how long ago you last touched the project, and deletes the ones you pick with one key.

I ran it in my `~/dev` folder in October 2026. In about 13 seconds it found 128 `node_modules` folders, 58.68 GB in total. Over two runs I deleted all of them except the 9 that belong to projects I'm working on, and npkill reported 49.89 GB of space released.

You don't have to install it. If you have [Node.js](https://flaviocopes.com/nodejs/) on your computer, open a terminal in the folder that holds your projects and run:

```bash
npx npkill
```

npkill is open source under the MIT license, made by Nya García Gallardo and Juan Torres Gómez. It works on macOS, Linux and Windows.

## Why node_modules folders get so big

Every JavaScript project keeps its dependencies in its own `node_modules` folder. npm gives each project its own copy of every package, so if ten projects use React, you have ten copies of React on your disk.

A fresh Vite and React app starts at about 53 MB, as I measured in [my post about the size of node_modules](https://flaviocopes.com/node-modules-size/). Real projects add a router and a database client, and the folder keeps growing.

Some tools make it much bigger. My biggest folder belongs to the Remotion project I use to render the intro videos for my posts, and it's 7.6 GB. Of that, 7.3 GB is build cache. Remotion bundles the code of a video with [webpack](https://flaviocopes.com/webpack/), and webpack keeps its cache in `node_modules/.cache/webpack`.

The real problem is old projects. You finish something, you move on, and its `node_modules` folder stays on your disk forever. Deleting it is safe, because `npm install` rebuilds it from `package.json` and the lockfile when you come back to the project.

## How to run npkill

The simplest way is [npx](https://flaviocopes.com/npx/), which downloads the package and runs it. The first time, npx asks you to confirm the download:

```bash
npx npkill
```

If you'd rather have the `npkill` command always available, install it globally:

```bash
npm install -g npkill
```

By default npkill scans the folder you're in and everything inside it. Use `-d` to start somewhere else:

```bash
npx npkill -d ~/dev
```

It needs a real terminal window to draw its interface, and it refuses to start in a very narrow one (60 columns or less).

> The README on GitHub already describes the next version of npkill, with multi-select, a search mode and JSON output. As of October 2026 that version isn't on npm yet. The latest npm release is from June 2024, and that's the version `npx npkill` runs and the one this post describes. If a key or a flag from the README does nothing, that's why.

## Reading the list

npkill adds folders to the list as it finds them, then calculates two numbers for each one.

**Size** is the space the folder takes, in megabytes. Add `-gb` to see gigabytes, which is easier to read when the folders are big.

**Last_mod** is how many days ago you changed a file in that project, not counting `node_modules`. `772d` means you haven't touched the project in more than two years, so this column shows you which projects you abandoned.

At the top, **Releasable space** adds up every folder in the list, and **Space saved** counts what you deleted so far.

You do everything with the keyboard:

- `↑` and `↓`, or `k` and `j`, move one row
- `Space` deletes the selected folder (so does the forward `Del` key, which on a Mac laptop is `fn` + `delete`)
- `PgUp` and `PgDn`, or `u` and `d`, move one page, and `Home` and `End` jump to the first and last row
- `o` opens the project folder, in Finder on a Mac, so you can check what it is before deleting
- `e` shows errors, like a folder you don't have permission to read
- `q` quits

A deleted folder gets a `[DELETED]` label in the list. It doesn't go to the Trash: on macOS and Linux npkill runs `rm -rf` on it, so it's gone right away. For `node_modules` that's fine, since `npm install` brings it back.

When you quit, npkill prints how much you freed:

```txt
Space released: 40.72 GB
Thanks for using npkill!
```

## Sort by age to find old projects

The list comes in the order npkill finds the folders. Sort it with `-s`. This puts the projects you haven't touched in the longest time at the top:

```bash
npx npkill -s last-mod
```

This puts the biggest folders at the top:

```bash
npx npkill -s size
```

You can also sort with `-s path`, which is alphabetical.

## How I use npkill

The first time I used npkill was in December 2022, to clean up `~/www/old`, the folder where my old website projects end up.

In October 2026 I ran it twice in `~/dev`, where I keep my Mac apps, CLI tools and experiments.

In the first run, with a plain `npx npkill`, I deleted the `node_modules` of six showreel projects. Those are the Remotion projects that render the 30-second videos for my app launches, and each one had between 0.78 and 2.11 GB of `node_modules`. The six together freed 9.16 GB.

Then I ran it again sorted by age, in gigabytes:

```bash
npx npkill -gb -s last-mod
```

The top of the list was boilerplate projects and example apps from past Bootcamp editions, untouched for 500 to 770 days. I went down the list and deleted every folder except the ones I'm working on now. That was 113 more folders and 40.72 GB.

I kept 9 folders. The biggest is the 7.6 GB `node_modules` of the Remotion project that renders my post intro videos. I still use that project, and its build cache saves time on every render.

Each scan of `~/dev` took about 13 seconds.

## The folders marked with ⚠️

Some `node_modules` folders belong to apps, not to your projects. Visual Studio Code and Cursor extensions ship with their own `node_modules`, and so do some desktop apps built with Electron. Delete one of those and the extension or the app breaks until you reinstall it.

npkill can't know which folder is which, so it guesses from the path. It marks a folder with ⚠️ when it sits inside a hidden folder (one whose name starts with a dot, like `~/.cursor`), inside a Mac app in `/Applications`, or inside `AppData` on Windows. For those rows it doesn't calculate the age, and shows `xx` instead.

On my Mac, `~/.cursor/extensions` has 11 `node_modules` folders and `~/.vscode/extensions` has 19. Leave those alone.

`~/.npm/_npx` has 115. That's the npx cache, where npkill itself ends up after you run it with `npx`. Those are safe to delete, because npx downloads a package again the next time you run it.

You only see these folders when you scan a place that contains them, like your home folder. `-f` starts the scan from your home folder, and `-x` leaves out every folder npkill would mark with ⚠️:

```bash
npx npkill -f -x
```

## Search for other folders

`node_modules` is the default, but `-t` searches for any folder name you give it:

```bash
npx npkill -t dist
```

`dist` and `build` hold build output in many JavaScript projects, `vendor` holds the dependencies of a PHP project installed with Composer, and `target` is where Rust puts its builds. Be careful with generic names, because some projects keep scripts in a folder called `build`, and npkill can't tell the difference.

You can search for one name at a time. Names that start with a dot work too, like `.next` for the Next.js build folder, but npkill treats them as hidden folders. Every result gets a ⚠️ and no age, and `-x` hides all of them.

## Exclude folders

`-E` skips folders. Put the names inside quotes, separated by commas:

```bash
npx npkill -E "clients, archive"
```

npkill matches these names as text anywhere in the path. `-E "old"` skips a folder called `old`, but it also skips a project called `golden-app`, because "golden" contains "old". Pick names that don't appear inside other names.

The same rule explains a default you might not expect. npkill always excludes `.git`, so a project folder called `flavio.github.io` never shows up in the list.

## Delete everything at once

`-D` deletes every folder npkill finds, as soon as it has measured it. It's made for cases like a backup folder full of copied projects, where you want every `node_modules` gone without picking them one by one.

Before it starts, npkill shows a warning and waits for you to press `y`. The warning recommends two things. Add `-x` so it skips the ⚠️ folders, because without it `-D` deletes those too. And try it first with `--dry-run`, which pretends to delete without touching anything:

```bash
npx npkill -d ~/backups -D -x --dry-run
```

When the list looks right, run the same command without `--dry-run`. Add `-y` if you don't want to see the warning. npkill still opens its interface while it works, and you quit with `q` when it's done.

## Before you delete

If the project has a lockfile (`package-lock.json`, `pnpm-lock.yaml` or `bun.lock`), the next install gets the exact versions you had. If it doesn't, npm picks the versions again from the ranges in `package.json`, and you may get newer ones. I explain how the lockfile works in [this lesson of my free Node.js course](https://flaviocopes.com/courses/nodejs/package-lock-and-reproducible-installs/).

Build caches stored in `node_modules/.cache`, like webpack's, go away with the folder, so the first build after reinstalling is slower.

The size npkill shows can be bigger than the space you get back. npkill measures each folder with `du`. [pnpm](https://flaviocopes.com/pnpm/) doesn't copy packages into each project: it keeps one copy in a global store (on my Mac that's `~/Library/pnpm/store/v10`) and hard links the files into `node_modules`. Bun on macOS does something similar with copy-on-write clones of its cache. When you delete those folders, the files are still in the store, so you free much less than npkill reports.

To clean the store, run `pnpm store prune`, which removes the packages no project uses, or `bun pm cache rm`, which clears Bun's cache. I explain how pnpm and Bun share packages in [Managing node_modules efficiently with pnpm and Bun](https://flaviocopes.com/managing-node-modules-efficiently/). Most of the projects I cleaned used npm, so most of my 49.89 GB was real space.

## Can a coding agent run npkill?

Usually not. Coding agents tend to run commands without an interactive terminal, and the npm version of npkill refuses to start there. This is what it prints when a Cursor agent runs it:

```txt
Oh no! Npkill does not support this terminal (TTY is required). This is a bug, which has to be fixed. Please try another command interpreter (for example, CMD in windows)
```

If you want an agent to help with the cleanup, ask it to list the folders with `find` and [du](https://flaviocopes.com/linux-command-du/), then delete the ones you approve:

```bash
find ~/dev -name node_modules -type d -prune -exec du -sh '{}' +
```

It's the same command from my post on [removing all the node_modules folders](https://flaviocopes.com/how-to-bulk-remove-node-modules/), with `du -sh` in place of `rm -rf`. That post's one-liner is also the alternative to npkill when you want to delete every `node_modules` under a folder and don't need to see the list first.
