fix(browser): surface detection details and docs

This commit is contained in:
Peter Steinberger
2026-01-16 06:57:20 +00:00
parent 2b16a87f04
commit 028eed5fe8
6 changed files with 70 additions and 4 deletions

View File

@@ -112,3 +112,18 @@ curl -s http://127.0.0.1:18791/tabs
| `browser.noSandbox` | Add `--no-sandbox` flag (needed for some Linux setups) | `false` |
| `browser.attachOnly` | Don't launch browser, only attach to existing | `false` |
| `browser.cdpPort` | Chrome DevTools Protocol port | `18800` |
### Problem: "Chrome extension relay is running, but no tab is connected"
Youre using the `chrome` profile (extension relay). It expects the Clawdbot
browser extension to be attached to a live tab.
Fix options:
1. **Use the managed browser:** `clawdbot browser start --browser-profile clawd`
(or set `browser.defaultProfile: "clawd"`).
2. **Use the extension relay:** install the extension, open a tab, and click the
Clawdbot extension icon to attach it.
Notes:
- The `chrome` profile uses your **system default Chromium browser** when possible.
- Local `clawd` profiles auto-assign `cdpPort`/`cdpUrl`; only set those for remote CDP.

View File

@@ -14,8 +14,10 @@ control server.
Beginner view:
- Think of it as a **separate, agent-only browser**.
- It does **not** touch your personal browser profile.
- The `clawd` profile does **not** touch your personal browser profile.
- The agent can **open tabs, read pages, click, and type** in a safe lane.
- The default `chrome` profile uses the **system default Chromium browser** via the
extension relay; switch to `clawd` for the isolated managed browser.
## What you get
@@ -39,6 +41,14 @@ clawdbot browser --browser-profile clawd snapshot
If you get “Browser disabled”, enable it in config (see below) and restart the
Gateway.
## Profiles: `clawd` vs `chrome`
- `clawd`: managed, isolated browser (no extension required).
- `chrome`: extension relay to your **system browser** (requires the Clawdbot
extension to be attached to a tab).
Set `browser.defaultProfile: "clawd"` if you want managed mode by default.
## Configuration
Browser settings live in `~/.clawdbot/clawdbot.json`.
@@ -71,11 +81,21 @@ Notes:
- `cdpUrl` defaults to `controlUrl + 1` when unset.
- `attachOnly: true` means “never launch a local browser; only attach if it is already running.”
- `color` + per-profile `color` tint the browser UI so you can see which profile is active.
- Auto-detect order: default browser if Chromium-based; otherwise Chrome → Brave → Edge → Chromium → Chrome Canary.
- Default profile is `chrome` (extension relay). Use `defaultProfile: "clawd"` for the managed browser.
- Auto-detect order: system default browser if Chromium-based; otherwise Chrome → Brave → Edge → Chromium → Chrome Canary.
- Local `clawd` profiles auto-assign `cdpPort`/`cdpUrl` — set those only for remote CDP.
## Use Brave (or another Chromium-based browser)
Set `browser.executablePath` to override auto-detection:
If your **system default** browser is Chromium-based (Chrome/Brave/Edge/etc),
Clawdbot uses it automatically. Set `browser.executablePath` to override
auto-detection:
CLI example:
```bash
clawdbot config set browser.executablePath "/usr/bin/google-chrome"
```
```json5
// macOS
@@ -339,6 +359,10 @@ Playwright. If Playwright isnt installed, those endpoints return a clear 501
error. ARIA snapshots and basic screenshots still work for clawd-managed Chrome.
For the Chrome extension relay driver, ARIA snapshots and screenshots require Playwright.
If you see `Playwright is not available in this gateway build`, install the full
Playwright package (not `playwright-core`) and restart the gateway, or reinstall
Clawdbot with browser support.
## How it works (internal)
High-level flow:

View File

@@ -13,6 +13,9 @@ export type BrowserStatus = {
cdpPort: number;
cdpUrl?: string;
chosenBrowser: string | null;
detectedBrowser?: string | null;
detectedExecutablePath?: string | null;
detectError?: string | null;
userDataDir: string | null;
color: string;
headless: boolean;

View File

@@ -63,7 +63,11 @@ export async function requirePwAi(
jsonError(
res,
501,
`Playwright is not available in this gateway build; '${feature}' is unsupported.`,
[
`Playwright is not available in this gateway build; '${feature}' is unsupported.`,
"Install the full Playwright package (not playwright-core) and restart the gateway, or reinstall with browser support.",
"Docs: /tools/browser#playwright-requirement",
].join("\n"),
);
return null;
}

View File

@@ -1,5 +1,6 @@
import type express from "express";
import { resolveBrowserExecutableForPlatform } from "../chrome.executables.js";
import { createBrowserProfilesService } from "../profiles-service.js";
import type { BrowserRouteContext } from "../server-context.js";
import { getProfileContext, jsonError, toStringOrEmpty } from "./utils.js";
@@ -36,6 +37,19 @@ export function registerBrowserBasicRoutes(app: express.Express, ctx: BrowserRou
]);
const profileState = current.profiles.get(profileCtx.profile.name);
let detectedBrowser: string | null = null;
let detectedExecutablePath: string | null = null;
let detectError: string | null = null;
try {
const detected = resolveBrowserExecutableForPlatform(current.resolved, process.platform);
if (detected) {
detectedBrowser = detected.kind;
detectedExecutablePath = detected.path;
}
} catch (err) {
detectError = String(err);
}
res.json({
enabled: current.resolved.enabled,
@@ -48,6 +62,9 @@ export function registerBrowserBasicRoutes(app: express.Express, ctx: BrowserRou
cdpPort: profileCtx.profile.cdpPort,
cdpUrl: profileCtx.profile.cdpUrl,
chosenBrowser: profileState?.running?.exe.kind ?? null,
detectedBrowser,
detectedExecutablePath,
detectError,
userDataDir: profileState?.running?.userDataDir ?? null,
color: profileCtx.profile.color,
headless: current.resolved.headless,

View File

@@ -47,7 +47,10 @@ export function registerBrowserManageCommands(
`cdpPort: ${status.cdpPort}`,
`cdpUrl: ${status.cdpUrl ?? `http://127.0.0.1:${status.cdpPort}`}`,
`browser: ${status.chosenBrowser ?? "unknown"}`,
`detectedBrowser: ${status.detectedBrowser ?? "unknown"}`,
`detectedPath: ${status.detectedExecutablePath ?? status.executablePath ?? "auto"}`,
`profileColor: ${status.color}`,
...(status.detectError ? [`detectError: ${status.detectError}`] : []),
].join("\n"),
);
} catch (err) {