fix(browser): default to chrome extension takeover

This commit is contained in:
Peter Steinberger
2026-01-15 08:50:08 +00:00
parent 75d2785d20
commit 4275ed68a2
10 changed files with 37 additions and 27 deletions

View File

@@ -53,6 +53,7 @@
- Agents: stabilize sub-agent announce status from runtime outcomes and normalize Result/Notes. (#835) — thanks @roshanasingh4.
- Apps: use canonical main session keys from gateway defaults across macOS/iOS/Android to avoid creating bare `main` sessions.
- Browser: ship a built-in `chrome` profile for extension relay and start the relay automatically when running locally.
- Browser: default `browser.defaultProfile` to `chrome` (existing Chrome takeover mode).
- Embedded runner: suppress raw API error payloads from replies. (#924) — thanks @grp06.
- Auth: normalize Claude Code CLI profile mode to oauth and auto-migrate config. (#855) — thanks @sebslight.
- Daemon: clear persisted launchd disabled state before bootstrap (fixes `daemon install` after uninstall). (#849) — thanks @ndraiman.

View File

@@ -23,11 +23,10 @@ Related:
## Quick start (local)
```bash
clawdbot browser status
clawdbot browser start
clawdbot browser tabs
clawdbot browser open https://example.com
clawdbot browser snapshot
clawdbot browser --browser-profile chrome tabs
clawdbot browser --browser-profile clawd start
clawdbot browser --browser-profile clawd open https://example.com
clawdbot browser --browser-profile clawd snapshot
```
## Profiles

View File

@@ -2357,7 +2357,7 @@ Defaults:
enabled: true,
controlUrl: "http://127.0.0.1:18791",
// cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override
defaultProfile: "clawd",
defaultProfile: "chrome",
profiles: {
clawd: { cdpPort: 18800, color: "#FF4500" },
work: { cdpPort: 18801, color: "#0066CC" },

View File

@@ -30,10 +30,10 @@ agent automation and verification.
## Quick start
```bash
clawdbot browser status
clawdbot browser start
clawdbot browser open https://example.com
clawdbot browser snapshot
clawdbot browser --browser-profile clawd status
clawdbot browser --browser-profile clawd start
clawdbot browser --browser-profile clawd open https://example.com
clawdbot browser --browser-profile clawd snapshot
```
If you get “Browser disabled”, enable it in config (see below) and restart the
@@ -49,7 +49,7 @@ Browser settings live in `~/.clawdbot/clawdbot.json`.
enabled: true, // default: true
controlUrl: "http://127.0.0.1:18791",
cdpUrl: "http://127.0.0.1:18792", // defaults to controlUrl + 1
defaultProfile: "clawd",
defaultProfile: "chrome",
color: "#FF4500",
headless: false,
noSandbox: false,

View File

@@ -239,7 +239,7 @@ Notes:
- Requires `browser.enabled=true` (default is `true`; set `false` to disable).
- Uses `browser.controlUrl` unless `controlUrl` is passed explicitly.
- All actions accept optional `profile` parameter for multi-instance support.
- When `profile` is omitted, uses `browser.defaultProfile` (defaults to "clawd").
- When `profile` is omitted, uses `browser.defaultProfile` (defaults to "chrome").
- Profile names: lowercase alphanumeric + hyphens only (max 64 chars).
- Port range: 18800-18899 (~100 profiles max).
- Remote profiles are attach-only (no start/stop/reset).

View File

@@ -10,14 +10,15 @@ describe("browser config", () => {
expect(resolved.color).toBe("#FF4500");
expect(shouldStartLocalBrowserServer(resolved)).toBe(true);
const profile = resolveProfile(resolved, resolved.defaultProfile);
expect(profile?.cdpPort).toBe(18800);
expect(profile?.cdpUrl).toBe("http://127.0.0.1:18800");
expect(profile?.cdpIsLoopback).toBe(true);
expect(profile?.name).toBe("chrome");
expect(profile?.driver).toBe("extension");
expect(profile?.cdpPort).toBe(18792);
expect(profile?.cdpUrl).toBe("http://127.0.0.1:18792");
const chrome = resolveProfile(resolved, "chrome");
expect(chrome?.driver).toBe("extension");
expect(chrome?.cdpPort).toBe(18792);
expect(chrome?.cdpUrl).toBe("http://127.0.0.1:18792");
const clawd = resolveProfile(resolved, "clawd");
expect(clawd?.driver).toBe("clawd");
expect(clawd?.cdpPort).toBe(18800);
expect(clawd?.cdpUrl).toBe("http://127.0.0.1:18800");
});
it("derives default ports from CLAWDBOT_GATEWAY_PORT when unset", () => {
@@ -26,14 +27,14 @@ describe("browser config", () => {
try {
const resolved = resolveBrowserConfig(undefined);
expect(resolved.controlPort).toBe(19003);
const profile = resolveProfile(resolved, resolved.defaultProfile);
expect(profile?.cdpPort).toBe(19012);
expect(profile?.cdpUrl).toBe("http://127.0.0.1:19012");
const chrome = resolveProfile(resolved, "chrome");
expect(chrome?.driver).toBe("extension");
expect(chrome?.cdpPort).toBe(19004);
expect(chrome?.cdpUrl).toBe("http://127.0.0.1:19004");
const clawd = resolveProfile(resolved, "clawd");
expect(clawd?.cdpPort).toBe(19012);
expect(clawd?.cdpUrl).toBe("http://127.0.0.1:19012");
} finally {
if (prev === undefined) {
delete process.env.CLAWDBOT_GATEWAY_PORT;
@@ -80,7 +81,7 @@ describe("browser config", () => {
controlUrl: "http://127.0.0.1:18791",
cdpUrl: "http://example.com:9222",
});
const profile = resolveProfile(resolved, resolved.defaultProfile);
const profile = resolveProfile(resolved, "clawd");
expect(profile?.cdpPort).toBe(9222);
expect(profile?.cdpUrl).toBe("http://example.com:9222");
expect(profile?.cdpIsLoopback).toBe(false);
@@ -127,5 +128,6 @@ describe("browser config", () => {
},
});
expect(resolveProfile(resolved, "chrome")).toBe(null);
expect(resolved.defaultProfile).toBe("clawd");
});
});

View File

@@ -7,6 +7,7 @@ import {
DEFAULT_CLAWD_BROWSER_COLOR,
DEFAULT_CLAWD_BROWSER_CONTROL_URL,
DEFAULT_CLAWD_BROWSER_ENABLED,
DEFAULT_BROWSER_DEFAULT_PROFILE_NAME,
DEFAULT_CLAWD_BROWSER_PROFILE_NAME,
} from "./constants.js";
import { CDP_PORT_RANGE_START, getUsedPorts } from "./profiles.js";
@@ -182,7 +183,7 @@ export function resolveBrowserConfig(cfg: BrowserConfig | undefined): ResolvedBr
const attachOnly = cfg?.attachOnly === true;
const executablePath = cfg?.executablePath?.trim() || undefined;
const defaultProfile = cfg?.defaultProfile ?? DEFAULT_CLAWD_BROWSER_PROFILE_NAME;
const defaultProfileFromConfig = cfg?.defaultProfile?.trim() || undefined;
// Use legacy cdpUrl port for backward compatibility when no profiles configured
const legacyCdpPort = rawCdpUrl ? cdpInfo.port : undefined;
const profiles = ensureDefaultChromeExtensionProfile(
@@ -190,6 +191,11 @@ export function resolveBrowserConfig(cfg: BrowserConfig | undefined): ResolvedBr
controlPort,
);
const cdpProtocol = cdpInfo.parsed.protocol === "https:" ? "https" : "http";
const defaultProfile =
defaultProfileFromConfig ??
(profiles[DEFAULT_BROWSER_DEFAULT_PROFILE_NAME]
? DEFAULT_BROWSER_DEFAULT_PROFILE_NAME
: DEFAULT_CLAWD_BROWSER_PROFILE_NAME);
return {
enabled,

View File

@@ -2,6 +2,7 @@ export const DEFAULT_CLAWD_BROWSER_ENABLED = true;
export const DEFAULT_CLAWD_BROWSER_CONTROL_URL = "http://127.0.0.1:18791";
export const DEFAULT_CLAWD_BROWSER_COLOR = "#FF4500";
export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd";
export const DEFAULT_BROWSER_DEFAULT_PROFILE_NAME = "chrome";
export const DEFAULT_AI_SNAPSHOT_MAX_CHARS = 80_000;
export const DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS = 10_000;
export const DEFAULT_AI_SNAPSHOT_EFFICIENT_DEPTH = 6;

View File

@@ -4,6 +4,7 @@ import path from "node:path";
import type { BrowserProfileConfig, ClawdbotConfig } from "../config/config.js";
import { loadConfig, writeConfigFile } from "../config/config.js";
import { deriveDefaultBrowserCdpPortRange } from "../config/port-defaults.js";
import { DEFAULT_BROWSER_DEFAULT_PROFILE_NAME } from "./constants.js";
import { resolveClawdUserDataDir } from "./chrome.js";
import { parseHttpUrl, resolveProfile } from "./config.js";
import {
@@ -134,7 +135,7 @@ export function createBrowserProfilesService(ctx: BrowserRouteContext) {
throw new Error(`profile "${name}" not found`);
}
const defaultProfile = cfg.browser?.defaultProfile ?? "clawd";
const defaultProfile = cfg.browser?.defaultProfile ?? DEFAULT_BROWSER_DEFAULT_PROFILE_NAME;
if (name === defaultProfile) {
throw new Error(
`cannot delete the default profile "${name}"; change browser.defaultProfile first`,

View File

@@ -31,7 +31,7 @@ export type BrowserConfig = {
noSandbox?: boolean;
/** If true: never launch; only attach to an existing browser. Default: false */
attachOnly?: boolean;
/** Default profile to use when profile param is omitted. Default: "clawd" */
/** Default profile to use when profile param is omitted. Default: "chrome" */
defaultProfile?: string;
/** Named browser profiles with explicit CDP ports or URLs. */
profiles?: Record<string, BrowserProfileConfig>;