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
| Capability | What it gives you |
|---|
| Watch mode iteration | Tight edit → rebuild → validate loop while coding |
| Browser-target control | Explicit cross-browser validation per command |
| Profile-aware runs | Reliable fresh or persisted profiles by workflow need |
| Source inspection mode | Structured output and diagnostics with source flags |
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
| Flag | Alias | What it does | Default |
|---|
[path or url] | - | Extension path or remote URL. | process.cwd() |
--browser <browser> | -b | Browser/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-binary | Custom 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-mode | Enable 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:
- Run
extension dev --no-browser as a long-lived process.
- Run
extension dev --wait --browser=<browser> as the readiness gate.
- 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
| Flag | What it does | Default 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
| Flag | What it does | Default |
|---|
--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-timestamps | Disable timestamps in pretty mode. | timestamps enabled |
--no-log-color | Disable 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