Choose the right target
How it works
Use--browser to choose a target in dev, start, preview, and build.
If you do not specify a browser, the CLI defaults to chromium.
--browser accepts exactly these values, alone or comma-separated:
--browser=all is also accepted and expands to chrome, edge, firefox.
safari (and its webkit-based alias) is the exception: it’s a macOS-only build target supported by build and dev only, not preview or start. See Building Safari extensions.
Requested target vs. launch binary
The browser you request determines the artifact. The binary is just the runtime. When you runextension dev --browser=chromium, Extension.js always:
- Writes output to
dist/chromium(the folder is named after the requested target, never after the binary that launches). - Resolves browser-specific manifest fields for the requested target.
chrome and chromium it looks for another managed Chromium-family binary (one previously downloaded by npx extension install) and uses it as the runtime instead:
- Requested
chromiummissing: falls back to managed Chrome, then managed Edge. - Requested
chromemissing: falls back to managed Chromium, then managed Edge.
npx extension install chromium. The warn deliberately omits the substitute binary path. The session’s identity card already carries a Binary row that names the exact binary in use, so the fact is printed once. The output folder and the emitted manifest are exactly what they would be without the fallback.
Binary provenance labels
The identity card labels where the session’s binary came from:Chromium snapshots vs stable
The managedchromium install is a tip-of-tree snapshot, not a stable release. When a stable system Chromium exists, Extension.js swaps to it automatically and prints a warn with the opt-out. Set EXTENSION_PREFER_CHROMIUM_SNAPSHOT=true to keep the cached snapshot instead.
Within the Chromium family this substitution is safe: dist/chrome and dist/chromium are byte-identical because manifest prefixes resolve per engine family, not per vendor. See Browser-specific manifest fields for the prefix rules.
To pre-install managed binaries for reproducible runs, use npx extension install <browser> or npx extension install all (which covers chromium too).
Supported browsers
Named browser targets:
Named forks (auto-located from your system, no binary path required):
If a named fork is not installed, Extension.js exits with install guidance. See Running other browsers.
Engine-based targets (custom binary required):
Extension.js treats
firefox-based as a Gecko engine target internally.
Safari and other WebKit targets
In addition to the Chromium family and Firefox (Gecko engine), Extension.js can build your extension into a Safari app on macOS.
Safari is a build target:
build and dev are supported, but preview and start are not (Safari extensions can’t be auto-loaded into a live browser). It requires macOS with the full Xcode app. See Building Safari extensions for the full workflow, requirements, and how to enable the extension in Safari.
Multi-browser selection
You can run multiple named browsers in one command:--browser=chrome,edge,firefox).
Constraints and behavior
chromium-basedrequires--chromium-binaryin commands that launch a browser (dev,start,preview);buildneeds no binary.gecko-based/firefox-basedrequire--gecko-binaryunder the same conditions.- Engine-based targets route to the same Chromium/Firefox runners with engine-aware behavior.
- As
buildtargets, engine targets get their owndist/<target>folder,.env.<target>resolution,EXTENSION_BROWSERvalue, and manifest prefix. See What engine targets mean forbuild.
Best practices
- Use named browsers for daily iteration:
chrome,edge, andfirefoxare the fastest path for regular testing. - Use engine-based mode intentionally: Prefer
chromium-based/gecko-basedwhen validating custom binaries or shipping a family-generic build. - Keep profiles isolated per browser: Reduce cross-browser state leakage while debugging.
- Pair with browser-specific fields: Use browser-prefixed manifest keys for true behavior differences.

