Skip to main content

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.

Use dev for day-to-day browser extension development with watch mode, browser launch, and context-aware update behavior. dev runs the development pipeline and watches your project files. It applies update strategies based on what changed: hot module replacement (HMR), hard reload, or a full restart when the change requires it.

When to use dev

  • Building features and validating changes in real time.
  • Debugging extension behavior in one or more browser targets.
  • Running source-inspection workflows with --source.
Use build for production artifacts, start for production build + launch, and preview to run existing build output only. If your extension lives inside a monorepo/submodule, review how extension.config.* loads env files (including workspace-root fallback): Environment variables.

Dev command capabilities

CapabilityWhat it gives you
Watch mode iterationTight edit → rebuild → validate loop while coding
Browser-target controlExplicit cross-browser validation per command
Profile-aware runsReliable fresh or persisted profiles by workflow need
Source inspection modeStructured output and diagnostics with source flags

Usage

extension dev [path-or-url] [options]
If you omit the path, Extension.js uses the current working folder. You can also pass a GitHub tree URL (for example, https://github.com/user/repo/tree/main/path). Extension.js downloads the repository and runs development mode on the local copy.

Arguments and flags

FlagAliasWhat it doesDefault
[path or url]-Extension path or remote URL.process.cwd()
--browser <browser>-bBrowser/engine target (chromium, chrome, edge, firefox, engine aliases, or comma-separated values).chromium
--profile <path|boolean>-Browser profile path or boolean profile mode.fresh profile
--chromium-binary <path>-Custom Chromium-family binary path.system default
--gecko-binary <path>--firefox-binaryCustom Gecko-family binary path.system default
--polyfill [boolean]-Enable browser.* API compatibility polyfill for Chromium targets.false
--starting-url <url>-Starting URL in launched browser.unset
--port <port>-Dev server port. Use 0 for OS-assigned port.8080
--host <host>-Host to bind the dev server to. Use 0.0.0.0 for Docker/dev containers.127.0.0.1
--no-open-Do not automatically launch browser.browser launches by default
--no-browser-Do not launch browser.browser launch enabled
--no-reload-Skip the content-script reload runtime and on-rebuild reload dispatch. Reload tabs manually to see changes.reload runtime enabled
--wait [boolean]-Wait for dist/extension-js/<browser>/ready.json and exit.disabled
--wait-timeout <ms>-Timeout for --wait mode.60000
--wait-format <pretty|json>-Output format for wait results (json is machine-readable).pretty
--extensions <list>-Comma-separated companion extensions or store URLs.unset
--install [boolean]-Install project dependencies when missing.command behavior default
--author--author-modeEnable maintainer diagnostics.disabled
When dev runs, Extension.js emits machine-readable metadata under:
  • dist/extension-js/<browser>/ready.json
  • dist/extension-js/<browser>/events.ndjson (newline-delimited JSON)
For automation (Playwright, continuous integration (CI), AI agents), prefer these files over terminal log parsing. Treat ready.json as the readiness contract:
  • status: "starting" while booting
  • status: "ready" when runtime is ready
  • status: "error" for startup/compile failures
  • runId uniquely identifies a runtime session
  • startedAt marks the runtime session start timestamp

--no-browser and readiness synchronization

--no-browser only disables browser launch. It does not block external runners until the compile finishes. For Playwright/CI/AI workflows:
  1. Run extension dev --no-browser as a long-lived process.
  2. Run extension dev --wait --browser=<browser> as the readiness gate.
  3. Launch external browser automation only after status: "ready".
--wait targets a second process (or CI step) and exits non-zero on error/timeout. When --wait sees a stale ready.json from a dead process (pid no longer alive), it keeps waiting for a live producer. If you pass both --wait and --no-browser in the same command invocation, --wait takes precedence. The command runs in wait-only mode.

--no-reload for a clean dev bundle

--no-reload skips the content-script reinjection wrapper and the on-rebuild reload dispatch. The dev dist stays close to a production bundle and an open tab is not disturbed when files change. Reload the extension or page yourself to pick up changes. --no-reload is only supported on extension dev. Passing it to start, preview, or build exits with an error. Internally it sets EXTENSION_NO_RELOAD=true so the develop process can read it from outside the CLI argv.

Source inspection workflow

Use source options only with dev. Source inspection opens a target URL in the browser and prints the full, live HTML after your content scripts run. Use this to verify what your extension actually changes.
  • --source [url] to inspect a page (defaults to --starting-url or https://example.com)
  • --watch-source / --no-watch-source to re-print HTML on each rebuild
start and preview do not support source-inspection flags.

Source flags

FlagWhat it doesDefault behavior
--source [url]Enable source inspection flow.disabled
--watch-source [boolean]Re-print source output on watched updates.true when --source is enabled
--source-format <pretty|json|ndjson>Output format for source inspection.falls back to log format or json
--source-summary [boolean]Emit compact summary output.disabled
--source-meta [boolean]Include page metadata.enabled when source is on
--source-probe <selectors>Comma-separated CSS selectors to probe.unset
--source-tree <off|root-only>Include compact extension tree details.unset
--source-console [boolean]Include console summary.disabled
--source-dom [boolean]Include DOM snapshots/diffs.enabled when watch-source is on
--source-max-bytes <bytes>Cap output payload size.unset
--source-redact <off|safe|strict>Redaction strategy for source output.format-dependent
--source-include-shadow <off|open-only|all>Control Shadow DOM inclusion.open-only when source is on
--source-diff [boolean]Include diff metadata on watch updates.enabled when watch-source is on

Logging flags

FlagWhat it doesDefault
--logs <off|error|warn|info|debug|trace|all>Minimum log level.off
--log-context <list|all>Context filter (background, content, page, sidebar, popup, options, devtools).all
--log-format <pretty|json|ndjson>Logger output format.pretty
--no-log-timestampsDisable timestamps in pretty mode.timestamps enabled
--no-log-colorDisable color in pretty mode.color enabled
--log-url <pattern>Filter log events by URL substring/regex.unset
--log-tab <id>Filter log events by tab ID.unset

Shared global options

Also supports Global flags.

Examples

Running a local extension

extension dev ./my-extension

Running a remote extension from GitHub

Pass a GitHub tree URL as the argument to develop a remote extension locally:
extension dev https://github.com/nicedoc/browserless/tree/main/packages/screencast

Inspecting page HTML with source mode

extension dev ./my-extension --source https://example.com

Running in Firefox

extension dev ./my-extension --browser firefox

Running in multiple browsers in sequence

extension dev ./my-extension --browser=chrome,firefox

Running inside Docker or a dev container

When you run inside Docker, dev containers, or GitHub Codespaces, bind the dev server to 0.0.0.0 so the host machine can reach it:
extension dev ./my-extension --host 0.0.0.0
Combine with --port 0 to let the OS choose an available port automatically:
extension dev ./my-extension --host 0.0.0.0 --port 0

Running in Brave as a custom binary

extension dev ./my-extension --chromium-binary /path/to/brave

Best practices

  • Browser compatibility: Test your extension in different browsers to verify it works on every target.
  • Polyfilling: If Firefox or a Gecko-based browser is also a target, use --polyfill. This flag enables browser.* API compatibility in Chromium-based browsers.
  • Source inspection workflows: Use dev (not start/preview) when you need source inspection options.
  • Automation reliability: Treat dev as the watch-mode companion (--no-browser + dev --wait). Treat start as the production companion (--no-browser + start --wait). Use --wait-format=json for scripts and CI automation.

Next steps