Skip to main content

Chrome extension

The OpenClaw Chrome extension lets the browser tool automate eligible tabs in your signed-in Chrome profile. It uses chrome.debugger, so it does not require Chrome’s blocking remote-debugging consent prompt. The extension is browser automation infrastructure. It does not include chat, page sharing, a prompt box, or a tab copilot. Its popup shows connection state, the current access mode, a Pause/Allow action for the current eligible tab, and a Settings link.

Requirements

  • Google Chrome, Chrome for Testing, or Chromium
  • OpenClaw installed on the same machine as Chrome, or an OpenClaw browser node on that machine
  • macOS or Linux for automatic native bootstrap
  • Chrome launched at least once so its user-data directory exists
Windows keeps manual pairing. Current Chromium launches native hosts directly only when the registered host is a Windows executable; OpenClaw does not install a script launcher or registry key without a proven binary framing path.

Install

Launch Chrome, then pre-register the native host before adding the extension:
Keep the command running. It pre-registers an origin-locked native host for the exact official Chrome Web Store identity and for OpenClaw’s deterministic development IDs. After pre-registration succeeds, add OpenClaw from the Chrome Web Store. The extension pairs on its first native call; you do not need to open its popup, reload it, or restart Chrome during a normal first-time setup. The installer then inspects the profile’s Preferences and Secure Preferences backing files and verifies the exact Store ID independently from any extension path. Chromium selects the backing file by settings-enforcement policy; Linux normally uses Preferences. Both files receive the same ownership, path, file type, permission, and size checks. For extension development, the command also copies the bundled extension to a stable OpenClaw-owned directory. Use that unpacked copy only as a development fallback:
  1. Open chrome://extensions.
  2. Enable Developer mode.
  3. Click Load unpacked.
  4. Select the path printed by the command.
Leave the install command running while completing either Store or development setup. For unpacked development, the installer verifies that Chrome loaded the approved realpath under its predicted deterministic ID. The installer recognizes the official Store installation only by the exact Foundation Store ID. That identity never makes a recorded path OpenClaw-owned. For unpacked development, it accepts an ID only when all of these are true:
  • the ID matches Chrome’s 32-character extension ID format;
  • Chrome records the install location as unpacked;
  • the recorded extension path resolves exactly to the installed or bundled OpenClaw extension directory;
  • the recorded ID equals Chromium’s deterministic path ID for that exact canonical realpath.
The extension name is not trusted. Existing native-host files with the same host name are not overwritten unless they are verifiably OpenClaw-owned. Use a different bounded wait when needed:
For automation, use --json. The result reports Store discovery separately from approved unpacked IDs and paths, plus native-host registration health and whether manual setup is required. It never includes a relay key or pairing string.

Use it

Select the built-in chrome profile, or make it the default:
Fresh automatic pairings use All tabs. Existing valid pairings are never overwritten, and older pairings keep their stored access mode. For fresh local setup, native bootstrap connects the extension through the local Gateway’s exact /browser/extension route. That first authenticated connection wakes the lazy browser-control service and starts the profile’s loopback relay; OpenClaw and local clients such as mcporter then use that profile relay port. Keep openclaw gateway run or the managed Gateway service running. A separate browser request or prewarm step is not required. Browser-node setup remains different: the extension connects to the relay on the browser-node host while the node uses its configured remote Gateway. An explicit --gateway-url pairing connects directly to that remote Gateway and remains a manual-only flow.

Standalone direct-loopback relay

A pairing on ws://127.0.0.1:<port>/extension can run without a local Gateway or browser node. On macOS and Linux, the bundled extension can ask the installed native host to start a standalone relay when reconnecting to that endpoint. Automatic local setup must be enabled. Requests are limited to once per minute; the extension still authenticates the relay with connection-bound v2 proofs. This requires both the updated native host and an extension build containing relay wake-up support. Do not assume the Store v2.2.0 build includes that code; the bundled unpacked development copy is the source-build validation path. Automatic wake-up requires the exact 127.0.0.1 host that the daemon serves. Other loopback aliases, including localhost and IPv6, do not trigger wake-up; use the canonical IPv4 endpoint when pairing for standalone operation. Wake-up uses the port in the extension’s existing canonical pairing. It does not switch to the first configured profile. The native host resolves current browser.profiles and permits only an extension-driver relay port, including automatically allocated ports and explicit cdpPort pins. A removed profile or stale port fails closed; correct the pairing to match the current profile. Gateway /browser/extension routes and remote pairings never trigger local daemon wake-up. Browser-node pairings that use a direct loopback relay can use it even when their Gateway hint points to a remote host. An existing listener keeps ownership of its port. Otherwise, the native host spawns dist/extensions/browser/relay-daemon-entry.js as a detached process. The daemon uses the same per-host relay key and stays alive while an extension or CDP client is connected. After both disconnect, it exits following ten minutes of inactivity, checked every 30 seconds. Closing Chrome alone does not stop it while a CDP client remains connected. A later reconnect can wake it again. The standalone daemon defaults to v2-only authentication, independently of the Gateway relay’s legacy default. Only an explicit browser.extensionRelay.allowLegacyAuth=true enables legacy authentication; an unset value, false, or a config-read failure never enables it. Prefer v2 clients so the persistent key is not disclosed to a process occupying the port. Gateway browser control can join a standalone relay that already owns the configured profile and port. It authenticates that exact owner with v2 and uses its existing bridge; it does not start a second listener. Stopping Gateway releases only Gateway’s connections, leaving the daemon, its direct extension connection, and other CDP clients running. Gateway-first automatic setup through /browser/extension remains supported. Both processes need an OpenClaw build that supports this owner-access protocol. A mismatched profile, port, key, or stricter authentication policy produces an error; Gateway never takes over the listener or falls back to legacy credentials. The daemon’s stricter v2-only default is compatible with Gateway’s default.

Choose tab access

  • All tabs exposes every eligible ordinary tab in that Chrome profile, except tabs paused for the current browser session. Use Pause on this tab and Allow on this tab in the popup.
  • Selected tabs uses the OpenClaw tab group as the access-control boundary. Moving a tab into the group grants access; moving it out revokes access.
Open the extension’s Settings page to change the access mode. Switching to Selected tabs immediately detaches ungrouped tabs, including attaches already in flight. Agent-created tabs stay in the OpenClaw group in either mode. The extension excludes incognito tabs, internal pages such as chrome:// and chrome-extension://, and tabs without a usable current URL. file:// access also requires Chrome’s Allow access to file URLs setting. An agent-created tab may start at about:blank while a CDP client initializes it before navigating. The extension allows that specific initial tab, keeps it in the OpenClaw group, and applies the same pause and access-mode controls. Existing blank tabs, manually grouped blanks, and other about: pages remain unavailable. Navigating away, replacing the tab, or restarting or reconnecting the extension ends the initial blank admission; returning to about:blank does not restore it. If creation fails before the extension returns the target, it attempts to close the tab only while it still owns it. Tabs you paused, moved, or navigated during creation are left alone. A redirect, lost connection, or worker shutdown can leave a tab behind; close it manually if needed. An explicitly commanded main-frame navigation of an authorized tab can also use exact about:blank, for example during a performance trace reset. Chrome must confirm the root frame and loader on the same attachment. An iframe navigation or a blank URL alone does not grant access. That temporary admission ends on the next nonblank document, debugger detach, access-mode change, pause, group or window change, tab closure or replacement, reconnect, or extension restart. Failed navigation never closes an existing tab or restores a URL over your navigation.

Automatic setup controls

Settings shows redacted relay/native bootstrap status and the Use automatic local setup switch.
  • Turning automatic setup off preserves a valid existing pairing but prevents new native bootstrap and standalone relay wake-up attempts.
  • Disconnect and disable automatic setup revokes the pairing immediately, detaches debugger sessions, and persists the opt-out.
  • Use local OpenClaw clears the opt-out and retries the native host.
  • Saving an explicit manual pairing also clears the opt-out.
Pre-release development installs that paired before local Gateway wakeup routing keep their existing pairing unchanged. In Settings, use Disconnect and disable automatic setup, then Use local OpenClaw to create the new local pairing. Released builds do not require this recovery step.

Upgrades from the retired tab copilot

If Settings says automation is paused to protect a pre-upgrade copilot session, confirm that old runs are finished. Then click Disconnect and disable automatic setup to discard the retired recovery state, followed by Use local OpenClaw to reconnect. Until that explicit disconnect succeeds, the extension preserves the retired state and blocks relay connections, native setup, manual pairing, tab access changes, and debugger attachment. Chromium caches the first missing-native-host result for the running browser process. If an existing extension already attempted automatic setup before the native host was installed, restart Chrome once (a full browser-process reload). Retrying from the popup or Settings cannot clear that process-level miss. Normal setup avoids it by pre-registering the host before adding or reopening the Store extension. For development, pre-register before Load unpacked.

Status and removal

Inspect the installation without printing credentials:
An owned registration is not necessarily launchable. Status reports a filesystem readiness snapshot of its registered runtime and native entry. It does not execute either target or verify that its code will run successfully. If an upgrade removes either target, rerun openclaw browser extension install to repair the owned registration. Ownership checks still refuse foreign or malformed manifests and launchers. Remove only OpenClaw-owned native-host manifests and launchers:
This does not remove the Store or unpacked extension from Chrome. Use chrome://extensions for that. It also does not delete the stable development copy or an existing relay key. openclaw browser extension path is read-only. It prints the stable installed copy when present and the bundled source directory otherwise.

Advanced manual pairing

The Settings page owns manual pairing. Generate a host-local pairing string:
Manual pairing remains useful on Windows and for recovery. Treat the complete pairing string as a password. Without --gateway-url, this command retains the host-local /extension relay for standalone manual pairing. It does not wake Browser control. With native wake-up support installed and automatic local setup enabled, the extension can start that relay on reconnect without a local Gateway. Otherwise, the relay must already be running, for example through Browser control or a browser node. For a laptop that has Chrome but does not run OpenClaw or a browser node, pair directly to a remote Gateway:
Paste that string in Settings → Advanced manual pairing. This flow cannot use automatic bootstrap: the remote Gateway owns a different relay key, and the local native host never fetches or copies it. Non-loopback remote URLs require wss://, and the Gateway must expose the exact /browser/extension WebSocket path without a path-rewriting proxy prefix.

External CDP clients

The relay supports Browser Relay Authentication v2 clients such as mcporter. OpenClaw and an external client can stay connected together. When a client enables Runtime, the extension checks current tab access before the relay replays existing execution contexts to that new subscriber. This does not reset another client’s Runtime session. Runtime binding callbacks go only to logical sessions that successfully registered the binding name, independently of Runtime.enable and Runtime.disable. Removing a binding or disconnecting a client preserves other clients’ registrations of the same name. Context-specific registrations with the same name still share the underlying native Runtime; use distinct names when clients need separate context selection. Fetch request interception has one owner per native target session. Another client can use other CDP domains, but cannot replace that owner’s interception settings or resolve its paused requests. Competing interception requests return an error rather than silently changing the active owner’s policy. Fetch response streams also belong to the logical session that acquired them. Related targets (such as frames and workers) have separate logical sessions for each interested parent. Each parent’s ordered auto-attach filter is preserved; the native attachment uses their union. New or broadened interests receive existing children only after the extension accepts the command. The native pause-on-attach setting remains shared: the latest update wins, including DevTools suspend/resume. Resuming a waiting target affects all its logical sessions. Clients still share the underlying tabs. Navigation or page changes can invalidate another client’s snapshot refs; this is not an isolated browser per client or complete isolation of every CDP domain and competing client policy. A complete tab-list request returns an error when native targets cannot yet be matched to Playwright pages, rather than reporting a partial list as complete. If the extension connection drops, its debugger attachments retire before the replacement connection reattaches. An uncertain native Fetch operation also retires the affected attachment instead of retrying the operation against a replacement. Fetch cleanup is bounded; debugger teardown is not a guarantee that pending network requests are canceled. These paths do not change the access mode or paused tabs. Take a fresh snapshot after the target reattaches before using element refs. If a client no longer exposes the target, reconnect that client. If native detach fails, the error is reported and cleanup debt stays with that exact attachment. Other tabs remain usable, but the affected tab cannot acquire a replacement until cleanup succeeds. After restoring Chrome access, retry an explicit attachment or Disconnect. Chrome’s debugger Cancel action can also end the native attachment. Removing or replacing a tab alone is not treated as proof that its debugger client closed. Failed CDP operations are never retried against a replacement session. The connection-lifetime protections require updated extension code as well as an updated OpenClaw installation. Update the Store extension when available. For an unpacked development copy, rerun openclaw browser extension install and reload the installed copy from chrome://extensions. Print non-secret endpoint metadata:
The output includes the loopback endpoint, protocol version, key ID, and fixed challenge/complete resources. It does not include the relay key or an authorization header. cdp --legacy-bearer is a temporary, warned compatibility escape hatch. It works only while browser.extensionRelay.allowLegacyAuth=true and prints the legacy credential on request.

Permissions

The extension requests only:
  • debugger: send CDP commands to allowed tabs;
  • tabs and tabGroups: discover tabs and enforce access mode;
  • storage: persist pairing, access mode, session pauses, and bootstrap opt-out;
  • alarms: wake the MV3 worker for relay/bootstrap retries;
  • nativeMessaging: request a local bootstrap pairing or wake its configured relay.
It does not request activeTab, contextMenus, scripting, or sidePanel.

Native bootstrap security

The native host is ai.openclaw.browser_bootstrap. The extension opens a chrome.runtime.connectNative port for one request, validates the response, then disconnects. The host writes one response and exits; a spawned standalone relay outlives this short-lived native connection. The request uses a versioned, length-prefixed JSON frame with a fresh 16-byte nonce. The host caps input at 4 KiB, requires fatal UTF-8 decoding and exact fields, verifies the caller origin against the exact installed manifest, and returns only a locally generated pairing, a relay status, or a bounded non-secret failure code. The bootstrap request remains exactly {v:1, op:"bootstrap", nonce}. Relay wake-up uses {v:1, op:"ensure_relay", nonce, relayPort} with a required integer port from 1 through 65535. Missing, duplicate, malformed, or extra fields are rejected. After manifest and caller validation, the host checks the requested port against current extension profiles before probing or spawning. No request can supply a host, executable path, or credential to the launcher. The response is below Chrome’s 1 MiB native-message limit. Pairing keys never appear in launcher arguments, manifests, status JSON, or diagnostics. The POSIX launcher and manifest use absolute canonical paths under an OpenClaw-owned mode-0700 directory. Manifests are mode 0600; the launcher is owner-executable. Symlinks, foreign ownership, unsafe modes, path traversal, wildcard origins, and foreign same-name registrations fail closed. The managed manifest authorizes the exact Foundation Chrome Web Store origin plus deterministic development origins in canonical order. The Store identity is a fixed product trust grant, not proof that an arbitrary path is OpenClaw-owned. Install the official Chrome Web Store build for normal use. Only load unpacked development copies you trust: Chrome can give a key-matched unpacked build the same extension identity and native-host access. The unpacked development ID calculation matches Chromium’s crx_file::id_util::GenerateIdForPath: hash the canonical absolute path’s raw bytes with SHA-256 (native UTF-16LE path bytes on Windows, with only a lowercase drive letter uppercased), keep the first 16 digest bytes, then map hexadecimal digits 0 through f to letters a through p. The unpacked extension manifest has no key; only these development IDs depend on approved OpenClaw-owned realpaths. The relay itself uses connection-bound HMAC proofs. The persistent per-host key is not sent in a URL, header, WebSocket subprotocol, or application frame during v2 authentication. On POSIX hosts, each key read rejects foreign-owned and non-regular files and tightens an owned group/other-accessible file to 0600; if tightening fails, the key is refused. Windows uses its existing ACL policy.

Troubleshooting

  • No native host was pre-registered: check the preceding per-browser refusal diagnostics and resolve the reported path, ownership, or permission issue. This summary does not mean that Chrome’s user-data directory is missing. If Chrome has never been launched, launch it first, then rerun extension install before adding the extension.
  • No extension ID detected: keep Chrome running, rerun extension install, then add the official Store extension. Use Load unpacked only as a development fallback after the command says native bootstrap is ready.
  • Extension was loaded before native setup: restart Chrome once to clear its cached native-host miss, then rerun the ordered install flow.
  • Extension version mismatch: reload the unpacked OpenClaw extension from chrome://extensions, then rerun browser doctor. Fully restart Chrome if the running and bundled versions still differ.
  • Waiting for local OpenClaw: run extension status; install or repair the owned native host.
  • Automatic setup disabled: enable it in Settings or click Use local OpenClaw.
  • Manual setup required: use Settings for the advanced pairing flow. This is expected on Windows and direct extension-only remote Gateway setups.
  • Relay unavailable: for /browser/extension pairings, confirm the target Gateway is running. For direct loopback /extension pairings, check native host registration, wake-up support in the extension build, automatic setup, and that the paired port still belongs to an extension profile. Allow for the one-minute wake-up throttle, then run browser doctor. No local Gateway is required for the standalone path.
See Browser for the full profile model and the managed openclaw and Chrome MCP user profiles.