package.json, and prints Bun commands in its own output.
The Extension.js CLI itself runs on Node. That split is the whole answer to the question below.
Can I use Bun instead of Node?
For your project, yes. For the CLI process, no.
Bun stays your interface. Node stays the runtime that executes the CLI. You need both installed.
Create a project with Bun
package.json pins the manager that you used:
package.json
Install and build
bun.lock file. Extension.js reads the lockfile on later runs to keep choosing Bun.
extension binary, so bun run dev, bun run build, and bun run preview all work.
Why the CLI needs Node
The published packages declare"engines": {"node": ">=22.12"}. The CLI checks process.versions.node at startup and stops when the version is too low.
Bun reports a Node compatibility version that is lower than that floor. Forcing the Bun runtime therefore trips the guard:
--bun and the same command works. Plain bunx respects the #!/usr/bin/env node shebang on the CLI binary, so the process runs on Node while Bun handles resolution and caching.
How Extension.js detects Bun
Detection reads the project, not the command that you typed. Three signals feed it:- A
bun.lockorbun.lockblockfile at the project root. - A
packageManagerfield inpackage.jsonthat namesbun. - The
npm_config_user_agentenvironment variable that Bun sets when it runs a script.
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.filedo not belong in extension code. That code runs in the browser. - Extension.js writes no Bun-specific scripts. The
dev,build, andpreviewscripts are the same for every manager. - A template that you import through
extension createships without a lockfile. Extension.js stripsbun.lockandbun.lockbfrom it. Your own install then decides the tree.
Next steps
- Compare with the Deno setup.
- Learn how Extension.js handles Node APIs.
- Learn how to manage Extension configuration.

