Turn it on
Start a dev session with the control flags you need:What you can do
| Command | What it does | Gate |
|---|---|---|
extension logs | Stream logs from every context (SW, content, popup, options, sidebar, devtools) in one ordered timeline | — |
extension inspect | Read the live, post-injection DOM of a surface | — |
extension storage get | set | Read or write your extension’s chrome.storage | --allow-control |
extension reload | Reload the extension or a tab | --allow-control |
extension open <popup|options|sidebar> | Open an extension surface | --allow-control |
extension open action | Trigger the toolbar action — opens its popup, or replays onClicked | --allow-control |
extension open command --name <cmd> | Replay a keyboard-shortcut command | --allow-control |
extension eval "<expr>" --context <c> | Evaluate an expression in a context and return the value | --allow-eval |
Address a context
Reading and acting share one vocabulary — you name the surface, Extension.js resolves it against the session it’s already tracking.| Address | Means |
|---|---|
--context background | the service worker (or MV2 background page) |
--context popup / options / sidebar | that extension surface, if it’s open |
--context content --url "https://shop.example/*" | the isolated content world on matching pages |
--context content --tab 7 | the content world in a specific tab |
Example: did my background handler actually run?
console.log your expression triggers flows out through extension logs at the same time, correlated by sequence — so you see the return value and the side effects.
Cross-browser support
Extension.js debugs through an in-browser companion, not the Chrome DevTools Protocol, so the core loop reaches your own surfaces on both Chrome and Firefox — the old “Firefox uses RDP, not supported” wall is gone for these tools.| Capability | Chromium | Firefox |
|---|---|---|
logs, inspect, eval, storage, reload, open (incl. action/command) | ✓ | ✓ (verified) |
inspect --deep-dom (closed shadow roots) | ✓ | — (uses CDP) |
extension_list_extensions (MCP tool) | ✓ | — (uses CDP) |
extension_list_extensions is an MCP tool rather than a CLI verb — it connects over the DevTools Protocol, so it’s Chromium-only.)
Safety
The gates are intentional, not bureaucratic:- Observation needs nothing. Reading logs and DOM is always available.
- Bounded operations need
--allow-control.storage,reload, andopenchange state, so you opt in per session. evalneeds--allow-evaland a per-session token. The token is written to a0600file outsidedist/so it never ships in a build — a random local process can’t quietly drive your service worker.- Nothing reaches production. The control channel exists only during
dev/preview; it’s gated on a port that isn’t present in a built bundle.
With an AI agent
The same operations are exposed as MCP tools through@extension.dev/mcp (extension_logs, extension_eval, extension_storage, extension_reload, extension_open, extension_list_extensions). The gates are identical — an assistant observes freely but only acts when you’ve enabled it for the session.
Next steps
- Trigger actions and keyboard commands — test handlers without clicking, headless and in CI.
- Run both MCP servers — Extension.js control alongside Chrome DevTools MCP.
- CI templates — wire these into a pull-request gate.

