> ## Documentation Index
> Fetch the complete documentation index at: https://extension.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Bun projects with Extension.js

> Use Bun as the package manager and script runner for a browser extension. Extension.js detects Bun, pins it in package.json, and builds from bun.lock.

Bun works as the package manager and the script runner for an Extension.js project. Extension.js detects Bun, records it in `package.json`, and prints Bun commands in its own output.

From Extension.js 4.1.21, the CLI runs on Bun too, from Bun 1.2 onward. The question below has two halves, and they now have different answers than they used to.

## Can I use Bun instead of Node?

Yes, for your project and for the CLI process both.

| What you want | Works with Bun |
| - | - |
| Install dependencies (`bun install`) | Yes |
| Run the scaffolder (`bunx extension`) | Yes |
| Run scripts (`bun run dev`, `bun run build`) | Yes |
| Execute the CLI on the Bun runtime | Yes, from Bun 1.2 |

Plain `bunx extension` still runs the CLI on Node, because the published binary carries a `#!/usr/bin/env node` shebang. Add `--bun`, or set `run.bun` in `bunfig.toml`, to execute it on Bun instead.

## Create a project with Bun

```bash theme={null}
bunx extension@latest create my-extension --template=content
```

Extension.js sees that Bun invoked it. The next steps that it prints name Bun:

```plaintext theme={null}
Next steps:
  1. cd my-extension
  2. bun install
  3. bun dev
     Run the extension in a fresh browser profile.
```

The generated `package.json` pins the manager that you used:

```json package.json theme={null}
{
  "packageManager": "bun@1.2.13"
}
```

## Install and build

```bash theme={null}
bun install
```

That writes a `bun.lock` file. Extension.js reads the lockfile on later runs to keep choosing Bun.

```bash theme={null}
bun run build
```

The scripts that the scaffolder writes are manager-agnostic. Each one calls the `extension` binary, so `bun run dev`, `bun run build`, and `bun run preview` all work.

## Which Bun versions work

Extension.js needs Bun 1.2 or newer. The CLI reads `process.versions.bun` at startup and judges Bun on its own version, never on the Node version that Bun reports, because the two do not track each other. Bun 1.1.38 and Bun 1.2.0 both report Node 22.6.0, and only one of them finishes a build.

Below 1.2, Bun cannot load the rspack native binding, so an older Bun fails deep inside the bundler rather than at the door. The guard stops it first:

```plaintext theme={null}
[Extension.js] Requires Bun >= 1.2 (you are on 1.1.38). Run bun upgrade, or run the extension CLI on Node.js >= 22.12 instead.
```

Bun is detected through `process.versions.bun`, which the runtime sets itself, so every route into it is covered: the `--bun` flag on `bunx` and `bun run`, and a `run.bun` default in `bunfig.toml`.

## How Extension.js detects Bun

Detection reads the project, not the command that you typed. Three signals feed it:

* A `bun.lock` or `bun.lockb` lockfile at the project root.
* A `packageManager` field in `package.json` that names `bun`.
* The `npm_config_user_agent` environment variable that Bun sets when it runs a script.

Extension.js supports `npm`, `pnpm`, `yarn`, `bun`, and `deno`. When no signal is present, it probes your `PATH` in the order `pnpm`, `yarn`, `bun`.

## Automatic dependency installs

`extension dev` and `extension build` install missing dependencies before they compile. The install runs through the manager that was detected, and it passes `--ignore-scripts`. A postinstall script in a dependency therefore does not run during that step.

## Caveats

* Bun-specific runtime APIs such as `Bun.file` do not belong in extension code. That code runs in the browser.
* Extension.js writes no Bun-specific scripts. The `dev`, `build`, and `preview` scripts are the same for every manager.
* A template that you import through `extension create` ships without a lockfile. Extension.js strips `bun.lock` and `bun.lockb` from it. Your own install then decides the tree.

## Next steps

* Compare with the [Deno setup](/docs/languages-and-frameworks/deno).
* Learn how Extension.js handles [Node APIs](/docs/languages-and-frameworks/node).
* Learn how to manage [Extension configuration](/docs/features/extension-configuration).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.