> ## Documentation Index
> Fetch the complete documentation index at: https://bun-1dd33a4e-farm-de84d354-pm-sbom.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# bun prune

> Remove packages that are not in bun.lock from node_modules

`bun prune` deletes everything in `node_modules` that the current `bun.lock` would not install — packages left behind after switching branches, removing a dependency, or installing with another package manager. With the isolated linker, this includes stale entries in `node_modules/.bun`.

It never contacts the registry, never runs lifecycle scripts, and never modifies `bun.lock` or `package.json`.

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun prune
```

```
bun prune v1.4.0 (abc12345)

- @types/node@20.11.5
- left-pad@1.3.0
2 packages removed (checked 948) [22.00ms]
```

Packages removed from a workspace or nested `node_modules` folder show the folder in parentheses, e.g. `- typescript@5.4.0 (packages/app/node_modules)`.

### `--production`

Also remove everything `bun install --production` would not install (i.e. `devDependencies`). This lets you build with dev dependencies and ship without them:

```dockerfile theme={"theme":{"light":"github-light","dark":"dracula"}}
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
RUN bun prune --production
```

`--omit=dev`, `--omit=optional`, and `--omit=peer` work the same way they do for `bun install`.

### `--dry-run`

List what would be removed without deleting anything:

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun prune --production --dry-run
```

```
bun prune v1.4.0 (abc12345)

- typescript@5.4.0
1 package can be removed (checked 948) [9.00ms]
  bun prune --production
```

### `--filter`

Prune only the selected workspaces' `node_modules` folders (same patterns as [`bun install --filter`](/pm/filter)). Shared locations — the root `node_modules`, or `node_modules/.bun` with the isolated linker — are cleaned too, but anything an unselected workspace still needs is kept.

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
bun prune --production --filter app
```

### Notes

* Always runs from the workspace root and covers every workspace's `node_modules`, even when invoked inside a workspace package.
* Requires `bun.lock` to match `package.json`. If you edited dependencies since the last install, run `bun install` first.
* Uses the same linker as `bun install` would. If `node_modules` was created with the other linker, `bun prune` refuses to run — pass the matching `--linker`, or run `bun install`.
* Packages are matched by name. A package at the wrong version is left for `bun install` to replace. A nested copy (`node_modules/a/node_modules/b`) is only removed once the correct version is installed above it; otherwise Bun keeps it and prints a warning.
* Never removes workspace folders, `.bin` entries still in use, dot-directories like `.cache`, plain files, or anything outside `node_modules`.
* Packages disabled for the current `os`/`cpu` are removed. Pass `--os`/`--cpu` to prune for another platform.
* Works on a pruned monorepo checkout (e.g. `turbo prune` output) the same way `bun install --frozen-lockfile` does.
* If any entry fails to delete, the rest are still removed and the command exits `1`.
* `--global` is not supported.
* To clean the global cache instead, use [`bun pm cache rm`](/pm/cli/pm#cache).
