mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-17 08:02:12 -06:00
5350b92dc8
* fix(browser): wake extension relay through gateway * fix(browser): preserve manual extension relay pairing
301 lines
12 KiB
Markdown
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.
|