Turn it on
Start a dev session with the control flags you need:What you can do
Address a context
Reading and acting share one vocabulary: you name the surface, Extension.js resolves it against the session itâs already tracking.Example: did my extension actually change the page?
This runs on the default template as-is.--context page evaluates in the active tabâs MAIN world, so you can check what your content script really did to the page:
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.
To call into the background instead, target a Firefox or MV2 session, where the background is a page that evaluates normally:
--context background returns an explanatory error instead of a value on those builds. Use --context page or --context content on Chromium MV3. The extension_eval MCP tool defaults to the page context on Chromium MV3 sessions for exactly this reason; on Firefox/MV2 its default stays background.
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.
(
eval --context background on a Chromium MV3 build returns an explanatory error. The MV3 background is a service worker, and Chromeâs extension CSP rejects unsafe-eval there on every MV3 build, not only in production. Evaluate in page/content on Chromium MV3, or target the background on a Firefox/MV2 build. 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, and 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.

