Skip to main content
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. 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

Extension.js sees that Bun invoked it. The next steps that it prints name Bun:
The generated package.json pins the manager that you used:
package.json

Install and build

That writes a bun.lock file. Extension.js reads the lockfile on later runs to keep choosing Bun.
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:
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