Skip to content

Commit b10de32

Browse files
author
bcode
committed
docs(skills): polish BROWSER.md Way 1 and Way 2 from harness install.md
Bring the canonical Way 1/Way 2 facts from browser-use/browser-harness:install.md into BROWSER.md, translated to the session.connect() API. Surfaced during v0.1.0 testing where the agent was failing to connect locally. Way 1 - Explicit per-profile + sticky framing for the chrome://inspect checkbox. - Chrome 144+ popup-may-reappear caveat with concrete causes (daemon restart, browser restart, time elapsed, "Allow for N hours"). Tells the agent to expect this rather than treating a 403 on a previously working connection as a hard failure. - Failure-mode list mapping the two distinct error strings to the right user instruction. Way 2 - Per-platform launch command (Linux, macOS, Windows cmd, Windows PowerShell) so the agent can pick the right shell without guessing. - Default profileDir-based connect (reads DevToolsActivePort) instead of the ws:// URL form, which is more reliable. - Two precisions verbatim from harness install.md: 1. --user-data-dir must not be the platform default; Chrome 136+ silently no-ops the port flag in that case. Platform default paths listed for all three OSes. 2. Cookie encryption is bound to the original profile dir; copying a profile to a custom dir transfers bookmarks and extensions but not logins. Tells the agent to fall back to Way 1 if logins are needed instead of attempting the copy. - Fix old example: bare ws://host:port/devtools/browser without a UUID suffix does not work — Chrome's browser-level endpoint includes a per-process UUID. The wsUrl form is now scoped as an escape hatch with a working example. Top-of-Connecting decision rule (Way 1 for real-browser tasks, Way 2 for unattended automation, cloud opt-in only) now appears before the three Way blocks. Source: https://github.com/browser-use/browser-harness/blob/main/install.md +32 lines net (162 -> 194). No code touched; tests still 8 pass + 5 chrome-gated skip; resolveSkillsDir still substitutes {{SKILLS_DIR}} to zero literal matches in materialized BROWSER.md.
1 parent 50afa3b commit b10de32

1 file changed

Lines changed: 42 additions & 10 deletions

File tree

packages/bcode-browser/skills/BROWSER.md

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,63 @@ Use the `browser_execute` tool to run JavaScript against a connected browser via
1313

1414
## Connecting
1515

16-
You always call `session.connect(...)` once at the start of your work. The `Session` is fresh on the first `browser_execute` call of an opencode session; subsequent calls reuse it. Three connection methods, in order of preference for typical tasks:
16+
You always call `session.connect(...)` once at the start of your work. The `Session` is fresh on the first `browser_execute` call of an opencode session; subsequent calls reuse it. Three connection methods, in order of preference for typical tasks.
1717

18-
**Way 1 — connect to the user's running Chrome (real profile, popup-gated).** Best when the task involves the user's actual logged-in sites.
18+
For most tasks where the agent acts on behalf of the user in their normal browser, use **Way 1**. For automation that runs without the user watching, or any case where popup interruptions are unacceptable, use **Way 2** or a cloud browser. Cloud is only used when the user opts in.
19+
20+
**Way 1 — connect to the user's running Chrome (real profile, popup-gated).** Inherits the user's everyday Chrome logins, extensions, history, and bookmarks. Right choice when the task involves the user's actual logged-in sites.
1921

2022
```js
2123
// Auto-detect the most-recently-launched Chrome with remote debugging enabled.
2224
await session.connect()
2325
```
2426

25-
The user must have ticked "Allow remote debugging for this browser instance" once at `chrome://inspect/#remote-debugging` (sticky per-profile), and on Chrome 144+ click "Allow" on the in-browser popup at first attach. If `connect()` fails with a 403/permission message, ask the user to do this. To wait for the click instead of erroring fast, pass `{ profileDir: "/abs/path", timeoutMs: 30000 }`.
27+
For this to work the user must have, **once**, navigated to `chrome://inspect/#remote-debugging` in their target Chrome and ticked "Allow remote debugging for this browser instance". This setting is per-profile and sticky: tick it once and it persists across every future Chrome launch of that profile. On Chrome 144 and later, the first attach also triggers an in-browser "Allow remote debugging?" popup that the user must click Allow on. The popup may reappear on later attaches under conditions that are not fully characterized — daemon restart, browser restart, time elapsed, version-dependent options like "Allow for N hours" — so be ready to ask the user to click Allow again if a previously working connection starts 403'ing.
28+
29+
Failure modes and what they mean:
30+
31+
- **`connect()` throws "No running browser with remote debugging detected"** — the checkbox at `chrome://inspect/#remote-debugging` has not been ticked in any running Chrome profile, or no Chrome is running. Ask the user to open their target Chrome and tick the box.
32+
- **`connect()` throws with "403" / "permission" / "WS closed before open"** — the checkbox is ticked but the user hasn't clicked Allow on the popup yet. By default `connect()` errors fast (5s per candidate). To wait up to 30s for the click: pass `{ profileDir: "<abs path to user's profile>", timeoutMs: 30000 }`. Passing `profileDir` skips the OS scan and reads the WebSocket URL straight from `<profileDir>/DevToolsActivePort` — works on every Chrome version including 144+ which doesn't serve `/json/version`.
33+
34+
**Way 2 — connect to a Chrome you (or the user) launched with a debug port (isolated profile, no popups, ever).** Right choice for unattended automation, or whenever popup interruptions are unacceptable.
2635

27-
**Way 2 — connect to a Chrome you (or the user) launched with a debug port (isolated profile, no popups).** Best for unattended automation.
36+
Launch Chrome with `--remote-debugging-port=<port> --user-data-dir=<path>`:
2837

2938
```bash
30-
# User runs this once (or you run it via the `bash` tool):
39+
# Linux
3140
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/bcode-chrome
41+
42+
# macOS
43+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
44+
--remote-debugging-port=9222 --user-data-dir=/tmp/bcode-chrome
45+
46+
# Windows (cmd.exe)
47+
"C:\Program Files\Google\Chrome\Application\chrome.exe" ^
48+
--remote-debugging-port=9222 --user-data-dir=C:\bcode-chrome
49+
50+
# Windows (PowerShell)
51+
& "C:\Program Files\Google\Chrome\Application\chrome.exe" `
52+
--remote-debugging-port=9222 --user-data-dir=C:\bcode-chrome
3253
```
3354

55+
Then connect to it from a snippet — pass the same `--user-data-dir` value as `profileDir` and `connect()` reads the live WebSocket URL out of `<profileDir>/DevToolsActivePort`:
56+
57+
```js
58+
await session.connect({ profileDir: "/tmp/bcode-chrome" }) // or "C:\\bcode-chrome" on Windows
59+
```
60+
61+
Two precisions on the `--user-data-dir`:
62+
63+
- **It must not be Chrome's platform default.** Chrome 136 and later silently no-op the `--remote-debugging-port` flag when `--user-data-dir` is the platform default, even if you pass it explicitly. The platform defaults are `%LOCALAPPDATA%\Google\Chrome\User Data` on Windows, `~/Library/Application Support/Google/Chrome` on macOS, `~/.config/google-chrome` on Linux. An empty or new path gives a fresh clean profile that Chrome will persist there across future launches.
64+
- **You cannot reuse the user's everyday Chrome profile by copying its files into a custom directory.** Chrome will accept the flag and start, so it looks like it works — but cookies are encrypted under a key bound to the *original* directory and will not survive the copy. Bookmarks and extensions transfer; logged-in sessions do not. If you need the user's real logins, use Way 1.
65+
66+
If you have a `wsUrl` directly (e.g. from `fetch("http://127.0.0.1:9222/json/version").then(r => r.json()).then(j => j.webSocketDebuggerUrl)`), you can also pass it as the escape hatch:
67+
3468
```js
35-
await session.connect({ wsUrl: "ws://127.0.0.1:9222/devtools/browser" })
36-
// or, if you know the profile dir:
37-
await session.connect({ profileDir: "/tmp/bcode-chrome" })
69+
await session.connect({ wsUrl: "ws://127.0.0.1:9222/devtools/browser/<uuid>" })
3870
```
3971

40-
The `--user-data-dir` must NOT be Chrome's platform default (`%LOCALAPPDATA%\Google\Chrome\User Data` on Windows, `~/Library/Application Support/Google/Chrome` on macOS, `~/.config/google-chrome` on Linux) — Chrome 136+ silently no-ops the port flag in that case.
72+
The bare `ws://host:port/devtools/browser` form (no UUID suffix) does not work — Chrome's browser-level endpoint includes a per-process UUID. Prefer `{ profileDir }` unless you specifically need the WS URL form.
4173

4274
**Way 3 — provision and connect to a Browser Use cloud browser.** Best when the user can't see the browser, you need a clean profile, geo-located proxy, or fingerprint isolation. Read `{{SKILLS_DIR}}/cloud-browser.md` for the full pattern (provision, stop, swap profile/proxy). Briefly:
4375

@@ -158,5 +190,5 @@ Cache-bust (`?t=${Date.now()}`) is your responsibility: without it, edits to the
158190
- **`session.Page.navigate` hangs forever** → the page is showing a native dialog. Use `session.Page.handleJavaScriptDialog({ accept: true })` to dismiss.
159191
- **Selectors don't find elements that you can see** → likely an iframe or shadow DOM. Read `{{SKILLS_DIR}}/interaction-skills/iframes.md` or `shadow-dom.md`.
160192
- **Actions silently no-op** → the page is mid-load. After `Page.navigate`, await `session.waitFor("Page.loadEventFired")` before driving inputs.
161-
- **Connection refused or 403 on connect()** → Chrome wasn't started with `--remote-debugging-port`, or the user hasn't clicked "Allow" on the remote-debugging prompt. Pass `{ profileDir, timeoutMs: 30000 }` to wait for the click, or fall back to Way 2.
193+
- **Connection refused, 403, or `WS closed before open` on connect()** → see the Way 1 failure-mode list above. Most often: the `chrome://inspect/#remote-debugging` checkbox isn't ticked, or the Chrome 144+ "Allow remote debugging?" popup hasn't been clicked. Pass `{ profileDir, timeoutMs: 30000 }` to wait up to 30s for the click, or fall back to Way 2.
162194
- **Cloud `connect()` fails after a successful provision** → check that `cdp_url` came back in the POST response; some BU regions return `cdpUrl` (camelCase) — accept both. See `{{SKILLS_DIR}}/cloud-browser.md`.

0 commit comments

Comments
 (0)