Files
openclaw/docs/tools/chrome-extension.md
Peter Steinberger 5350b92dc8 fix(browser): wake extension relay through gateway (#122537)
* fix(browser): wake extension relay through gateway

* fix(browser): preserve manual extension relay pairing
2026-08-12 02:13:03 -07:00

301 lines
12 KiB
Markdown

---
summary: "Chrome extension: securely automate signed-in tabs with automatic local pairing"
read_when:
- You want an agent to drive your signed-in Chrome without remote-debugging prompts
- You are installing, pairing, disabling, or troubleshooting the OpenClaw Chrome extension
- You need the Chrome native bootstrap security and platform support model
title: "Chrome Extension"
---
# 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 run this command before loading the extension:
```bash
openclaw browser extension install
```
Keep the command running. It copies the bundled extension to a stable
OpenClaw-owned directory, predicts the unpacked extension ID from that exact
path, and pre-registers an origin-locked native host in existing Chrome-family
user-data roots. Only after pre-registration succeeds does it print the stable
path to load.
Chrome does not let a normal CLI silently install an unpacked extension. This
one step is unavoidable:
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 you complete those steps. The extension
pairs on its first native call; you do not need to open its popup, reload the
extension, or restart Chrome during a normal first-time setup. The installer
then reads the profile's `Secure Preferences` and verifies that Chrome loaded
the approved realpath under the predicted ID.
The installer 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:
```bash
openclaw browser extension install --wait-ms 60000
```
For automation, use `--json`. The result includes the stable copy, discovered
IDs and profiles, 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:
```bash
openclaw config set browser.defaultProfile chrome
```
```json5
{
browser: {
profiles: {
chrome: { driver: "extension" },
},
},
}
```
Fresh automatic pairings use **All tabs**. Existing valid pairings are never
overwritten, and older pairings keep their stored access mode.
For 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.
### 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.
## Automatic setup controls
Settings shows redacted relay/native bootstrap status and an **Use automatic
local setup** switch.
- Turning automatic setup off preserves a valid existing pairing but prevents
new native bootstrap 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 **Load unpacked**.
## Status and removal
Inspect the installation without printing credentials:
```bash
openclaw browser extension status
openclaw browser extension status --json
```
Remove only OpenClaw-owned native-host manifests and launchers:
```bash
openclaw browser extension uninstall-host
```
This does not remove the unpacked extension from Chrome. Use
`chrome://extensions` for that. It also does not delete the stable extension
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:
```bash
openclaw browser extension pair
```
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; the selected
profile relay must already be running before the extension connects.
For a laptop that has Chrome but does not run OpenClaw or a browser node, pair
directly to a remote Gateway:
```bash
openclaw browser extension pair \
--gateway-url wss://gateway.example.com
```
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.
Print non-secret endpoint metadata:
```bash
openclaw browser extension cdp
openclaw browser extension cdp --json
```
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 one local bootstrap pairing.
It does not request `activeTab`, `contextMenus`, `scripting`, or `sidePanel`.
## Native bootstrap security
The native host is `ai.openclaw.browser_bootstrap`. Each
`chrome.runtime.sendNativeMessage` call starts one process, reads one request,
writes one response, and exits.
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 or a bounded non-secret failure code.
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 unpacked 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 extension manifest has no
`key`; registration authorizes only exact IDs derived from 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.
## Troubleshooting
```bash
openclaw browser extension status --json
openclaw browser doctor --browser-profile chrome
openclaw doctor
```
- **No extension ID detected:** keep Chrome running, rerun `extension install`,
and use **Load unpacked** only after the command says native bootstrap is
ready and prints the stable path.
- **Extension was loaded before native setup:** restart Chrome once to clear its
cached native-host miss, then rerun the ordered install flow.
- **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:** confirm `openclaw gateway run` or the managed Gateway
service is running for local setup, or confirm the browser node is running
for browser-node setup. Then run browser doctor. No separate browser prewarm
should be necessary.
See [Browser](/tools/browser) for the full profile model and the managed
`openclaw` and Chrome MCP `user` profiles.