browser-trace
browserbase/skills
捕获任何浏览器自动化操作的完整 DevTools 协议跟踪记录,将数据流划分为可按页面搜索的桶,并将跟踪记录附加到正在进行的会话中以进行调试。
...展开全部浏览器跟踪
将第二个只读 CDP 客户端连接到一个已由主自动化程序驱动的浏览器会话中。该跟踪功能将 DevTools 的完整数据流记录为 NDJSON 格式,并并行采集屏幕截图和 DOM 转储,最后将所有内容切片整理成一个 bash 工具可搜索的目录树。
此技能不驱动页面——它仅进行监听。请将其与 browser 技能、 browse、Stagehand、Playwright,或任何支持 CDP 协议的工具配合使用。
何时使用
- 用户希望调试浏览器自动化运行(表单提交失败、元素缺失、导航卡死、JS 异常)。
- 用户有一个正在运行的自动化任务,希望在运行过程中附加跟踪信息,而无需重启该任务。
- 用户希望将 CDP 数据流拆分为网络、控制台、DOM 和页面等不同类别。
- 用户希望获取随时间变化的截图和 DOM 快照,并通过时间戳将其与 CDP 事件关联。
如果用户仅需驱动浏览器,请改用 browser 技能。
设置检查
node --version # require Node 18+
which browse || npm install -g browse
which jq || true # optional — used only for ad-hoc querying
验证 browse cdp 是否存在:
browse --help | grep -q "^\s*cdp " || echo "browse cdp not available — update browse"
工作原理
每个 Chrome DevTools 目标都支持多个并发 CDP 客户端。您的主自动化程序是一个客户端;本技能会添加第二个客户端,该客户端仅启用观察域(网络、控制台、运行时、日志、页面),且绝不会发送操作命令。
该追踪器包含三个部分:
- Firehose:
browse cdp将每个 CDP 事件以每行一个 JSON 对象的形式流式传输至cdp/raw.ndjson. - 采样器:一个轮询循环调用
browse screenshot --cdp并--path browse get html body --cdp以一定间隔(默认2秒)调用该函数。该辅助程序在--cdp采样时,以便从其自身进程中连接到被追踪的目标;一旦浏览守护进程会话连接到 CDP 目标,该会话中的后续命令就无需重复--cdp. - Bisector:运行结束后,
bisect-cdp.mjs会遍历raw.ndjson一次,将其切分为按 CDP 方法作为键的桶级 JSONL 文件,并利用顶级Page.frameNavigated事件作为边界,对每页进行二分。
快速入门
本地 Chrome
# 1. Launch Chrome with a debugger port (any user-data-dir keeps it isolated).
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome-o11y \
about:blank &
# 2. Start the tracer.
node scripts/start-capture.mjs 9222 my-run
# 3. Run your main automation against port 9222.
browse open https://example.com --cdp 9222
# ...whatever the run does...
# 4. Stop and bisect.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
Browserbase 远程
两个辅助函数封装了平台端的记录管理: bb-capture.mjs 创建或连接到一个会话并启动追踪器; bb-finalize.mjs 在结束时将平台生成文件(最终会话元数据、服务器日志、下载内容)导入运行目录。
一旦最后一个 CDP 客户端断开连接,Browserbase 便会立即结束会话。请使用 `
--keep-alive` 创建会话,然后在启动追踪器之前或与其同时,将会话的 `connectUrl` 关联到自动化脚本中。bb-capture.mjs --new该操作会处理保持活动状态的会话及追踪器的配置;您的自动化仍需手动附加。
export BROWSERBASE_API_KEY=...
# 1. Create a keep-alive session AND start the tracer in one step.
# Prints the session id, connectUrl prefix, and a live debugger URL you
# can open in a browser to watch the run interactively.
node scripts/bb-capture.mjs --new my-run
# 2. Drive automation. bb-capture stamped the session id into the manifest.
SID=$(jq -r .browserbase.session_id .o11y/my-run/manifest.json)
CONNECT_URL="$(browse cloud sessions get "$SID" | jq -r .connectUrl)"
BROWSE_NAME=my-run-browser
browse open https://example.com --cdp "$CONNECT_URL" --session "$BROWSE_NAME"
browse open https://news.ycombinator.com --session "$BROWSE_NAME"
# 3. Stop the tracer, bisect, then pull platform artifacts and release.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
node scripts/bb-finalize.mjs my-run --release
附加到已运行的会话(例如由您的生产环境操作员创建的会话)—— bb-capture.mjs 接受会话 ID 代替 --new:
# Pick a running session (filter client-side; browse cloud sessions list has no --status flag)
browse cloud sessions list | jq -r '.[] | select(.status == "RUNNING") | .id'
node scripts/bb-capture.mjs mid-flight-debug
# ...tracer runs alongside the existing automation client; no disruption...
node scripts/stop-capture.mjs mid-flight-debug
node scripts/bisect-cdp.mjs mid-flight-debug
node scripts/bb-finalize.mjs mid-flight-debug # without --release: leave the session running
您从 Browserbase 平台获得的内容
bb-capture.mjs 添加一个 browserbase 块到 manifest.json (会话 ID、项目、区域、开始时间、到期时间、调试器 URL)。 bb-finalize.mjs 写入:
— 最终/browserbase/session.json browse cloud sessions get快照 (proxyBytes, 状态, 结束时间, 视口, …)—/browserbase/logs.json browse cloud sessions logs输出。通常为空。CDP数据流在cdp/raw.ndjson是权威数据源;此处仅为辅助渠道。— 会话下载的文件(如有)(当无文件时,脚本会丢弃生成的空 22 字节 ZIP 文件)/browserbase/downloads.zip
会话重放数据文件的获取已弃用,且不再进行获取。请使用 screenshots/ 和 dom/ 中的截图和DOM转储作为可视化基准。
清单中的 debugger_url 选项将打开由 Browserbase 提供的交互式 Chrome DevTools 视图——这在追踪器将海量数据流写入磁盘的同时,便于观察长时间运行的自动化过程。
文件系统布局
.o11y//
manifest.json run metadata: target, domains, started_at, stopped_at
index.jsonl one line per sample: {ts, screenshot, dom, url}
cdp/
raw.ndjson full CDP firehose (one JSON object per line)
summary.json {sessionId, duration, totalEvents, pages[]} — see shape below
network/{requests,responses,finished,failed,websocket}.jsonl session-wide buckets (always written)
console/{logs,exceptions}.jsonl
runtime/all.jsonl
log/entries.jsonl
page/{navigations,lifecycle,frames,dialogs,all}.jsonl
dom/all.jsonl (only if O11Y_DOMAINS includes DOM)
target/{attached,detached}.jsonl
pages/ per-page slices, indexed by top-level frameNavigated boundaries
000/ first concrete page
url.txt the URL for this page
summary.json this page's domains/network/timing block (same shape as a pages[] entry)
raw.jsonl firehose scoped to this page
network/, console/, page/, runtime/, log/, target/, dom/ same buckets, only non-empty files
screenshots/.png one PNG per sample interval
dom/.html one HTML dump per sample interval
browserbase/ added by bb-finalize.mjs (Browserbase runs only)
session.json final `browse cloud sessions get` snapshot (proxyBytes, status, ended_at, …)
logs.json `browse cloud sessions logs` output (often [])
downloads.zip `browse cloud sessions downloads get` output (only if the session downloaded files)
当通过 bb-capture.mjs, manifest.json 还包含一个顶级 browserbase 块: session_id, project_id, region, started_at, expires_at, keep_alive, debugger_url.
摘要形状
cdp/summary.json 是任何分析的入口点:它包含会话级别的总计数据以及一个 pages[] 以顶级 Page.frameNavigated作为索引的数组。每页的条目按导航顺序输出(第0页=第一个具体URL)。
{
"sessionId": "45f28023-…",
"duration": { "startMs": 1777312533000, "endMs": 1777312609000, "totalMs": 76000 },
"totalEvents": 420,
"pages": [
{
"pageId": 0,
"url": "https://example.com/",
"startMs": 1777312533000, "endMs": 1777312538886, "durationMs": 5886,
"eventCount": 60,
"domains": {
"Network": { "count": 18, "errors": 1 },
"Console": { "count": 2 },
"Page": { "count": 24 },
"Runtime": { "count": 13 }
},
"network": { "requests": 4, "failed": 1, "byType": { "Document": 2, "Script": 1, "Other": 1 } }
}
]
}
startMs / endMs / durationMs 表示实际时间(毫秒),由 manifest.started_at 加上每个事件的CDP单调时间戳的偏移量。 domains[*] 仅包含 errors/warnings 非零的键。
使用 query.mjs
若需交互式探索,请使用 scripts/query.mjs 代替记住路径:
node scripts/query.mjs my-run list # one-line table of pages
node scripts/query.mjs my-run page 1 # full summary for page 1
node scripts/query.mjs my-run page 1 network/failed # cat failed.jsonl for page 1
node scripts/query.mjs my-run errors # all errors across pages, attributed by pid
node scripts/query.mjs my-run errors 2 # errors from page 2 only
node scripts/query.mjs my-run hosts # top hosts by request count
node scripts/query.mjs my-run host api.example.com # all requests/responses for a host
node scripts/query.mjs my-run summary # full summary.json
在后台,它只是读取 cdp/summary.json ,并生成 cdp/pages/ 树结构——一旦掌握了形状, jq/rg 。
顶级遍历技巧
# All failed network requests (use jq -c to keep it line-delimited)
jq -c '.params' .o11y//cdp/network/failed.jsonl
# Find requests to a specific host
jq -c 'select(.params.request.url | test("api\\.example\\.com"))' \
.o11y//cdp/network/requests.jsonl
# 4xx/5xx responses
jq -c 'select(.params.response.status >= 400)
| {status: .params.response.status, url: .params.response.url}' \
.o11y//cdp/network/responses.jsonl
# Console errors only
jq -c 'select(.params.type == "error")' .o11y//cdp/console/logs.jsonl
# Sequence of URLs visited
jq -r '.params.frame.url' .o11y//cdp/page/navigations.jsonl
# Find the screenshot taken closest to a timestamp (e.g., when an exception fired)
ls .o11y//screenshots/ | sort | awk -v t=20260427T1714123NZ '
$0 >= t { print; exit }'
请参阅 REFERENCE.md 以获取完整的 jq 配方库以及按方法分类的二分搜索映射。请参阅 EXAMPLES.md 以获取端到端的调试场景。
最佳实践
- 在 Browserbase 上使用 `
bb-capture.mjs`:它会强制执行--keep-alive,获取 connectUrl,捕获调试器 URL,并为清单添加时间戳。手动操作容易导致错误。 - 请勿对非您拥有的会话执行
--release操作:bb-finalize.mjs --release仅适用于您使用--new。当通过bb-capture.mjs附着到生产会话时,请运行bb-finalize.mjs时请勿使用--release,以便原始自动化继续运行。 - 对于远程操作,顺序很重要:在 Browserbase 上,请先于(或与)追踪器一起连接主自动化客户端,并使用
--keep-alive。否则,一旦追踪器的 WS 关闭,会话就会立即结束。 - 轮询间隔不要小于约1秒:每次采样都会执行浏览器CLI读取命令并截取Chrome屏幕截图。2秒是一个不错的默认值。
- 请谨慎选择域名:默认设置(
Network Console Runtime Log Page)已涵盖大部分调试需求。若需检测DOM用于检测DOM树变异(噪声很大),通过O11Y_DOMAINS="$O11Y_DOMAINS DOM". - 通过挂载该会话的
connectUrl使用browse open ... --cdp "$CONNECT_URL" --session。--session标志用于指定本地浏览器守护进程;它并非 Browserbase 会话附加标志。 - 始终运行
stop-capture.mjs,即使在崩溃后也是如此,这样背景进程才不会滞留,且清单文件能被stopped_at. - 每次运行进行一次二分法排查:
bisect-cdp.mjs是幂等的——它每次都会覆盖raw.ndjson每次执行时。
故障排除
browse cdp exited immediately:通常表示目标不可达(端口错误)或 Browserbase 会话已结束。对于远程情况,请使用browse cloud sessions get——如果status是COMPLETED,请使用--keep-alive并先连接自动化。- 尽管进程正在运行,但
raw.ndjson却为空:请确认CDP客户端是否确实在驱动该页面。追踪器仅会发出浏览器生成的事件,因此处于空闲状态的浏览器只会产生约5行连接/发现消息,除此之外不会有其他内容。 - 所有截图看起来完全一样:检查
index.jsonl——如果url未发生变化,说明页面尚未进行导航。轮询循环的运行与主自动化进程的节奏无关。 - Browserbase 会话在运行中途结束:这很可能是触发了
--timeout。请使用更长的超时时间重新创建会话(BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...) 重新创建,或移除超时标志。 bb-capture.mjs显示“未运行(not RUNNING)”:您尝试附加的会话已结束。列出候选项并browse cloud sessions list | jq '.[] | select(.status == "RUNNING")'并重试。browserbase/logs.json[]为空:这是预期的——browse cloud sessions logs在实际中较为稀疏。CDP数据流在cdp/raw.ndjson中的数据才是权威来源。- 会话录制(rrweb)在哪里?:会话重放数据检索已被弃用;此技能不会检索该数据。请使用
screenshots/中的截图流以及dom/.
完整参考请参阅 REFERENCE.md。 示例调试运行请参阅 EXAMPLES.md。
---
name: browser-trace
description: Capture a full DevTools-protocol trace of any browser automation, bisect the stream into per-page searchable buckets, and attach a trace to an in-progress session for debugging.
license: MIT
---
# Browser Trace
Attach a **second, read-only CDP client** to a browser session that is already being driven by your main automation. The trace records the full DevTools firehose to NDJSON, polls for screenshots and DOM dumps in parallel, and slices everything into a directory tree that bash tools can search.
This skill does **not** drive pages — it only listens. Pair it with the `browser` skill, `browse`, Stagehand, Playwright, or anything else that speaks CDP.
## When to use
- The user wants to debug a browser-automation run (failing form, missing element, hung navigation, JS exception).
- The user has a running automation and wants to attach a trace mid-flight without restarting it.
- The user wants to split a CDP firehose into network / console / DOM / page buckets.
- The user wants screenshots + DOM snapshots over time, joined to CDP events by timestamp.
If the user just wants to **drive** the browser, use the `browser` skill instead.
## Setup check
```bash
node --version # require Node 18+
which browse || npm install -g browse
which jq || true # optional — used only for ad-hoc querying
```
Verify `browse cdp` exists:
```bash
browse --help | grep -q "^\s*cdp " || echo "browse cdp not available — update browse"
```
## How it works
Every Chrome DevTools target accepts **multiple concurrent CDP clients**. Your main automation is one client; this skill adds a second one that only enables observation domains (Network, Console, Runtime, Log, Page) and never sends action commands.
The tracer has three pieces:
1. **Firehose**: `browse cdp <target>` streams every CDP event as one JSON object per line to `cdp/raw.ndjson`.
2. **Sampler**: a polling loop calls `browse screenshot --cdp <target> --path <file>` and `browse get html body --cdp <target>` on an interval (default 2s). The helper passes `--cdp` when it samples so it can attach to the traced target from its own process; once a browse daemon session is attached to a CDP target, follow-up commands in that session do not need to repeat `--cdp`.
3. **Bisector**: after the run, `bisect-cdp.mjs` walks `raw.ndjson` once, slices it into per-bucket JSONL files keyed by CDP method, and additionally bisects per page using top-level `Page.frameNavigated` events as boundaries.
## Quickstart
### Local Chrome
```bash
# 1. Launch Chrome with a debugger port (any user-data-dir keeps it isolated).
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome-o11y \
about:blank &
# 2. Start the tracer.
node scripts/start-capture.mjs 9222 my-run
# 3. Run your main automation against port 9222.
browse open https://example.com --cdp 9222
# ...whatever the run does...
# 4. Stop and bisect.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
```
### Browserbase remote
Two helpers wrap the platform-side bookkeeping: `bb-capture.mjs` creates or attaches to a session and starts the tracer; `bb-finalize.mjs` pulls platform artifacts (final session metadata, server logs, downloads) into the run dir at the end.
> Browserbase ends a session as soon as its last CDP client disconnects. **Create with `--keep-alive`, then attach automation to the session's `connectUrl` before or together with the tracer.** `bb-capture.mjs --new` handles the keep-alive session and tracer setup; your automation still needs to attach.
```bash
export BROWSERBASE_API_KEY=...
# 1. Create a keep-alive session AND start the tracer in one step.
# Prints the session id, connectUrl prefix, and a live debugger URL you
# can open in a browser to watch the run interactively.
node scripts/bb-capture.mjs --new my-run
# 2. Drive automation. bb-capture stamped the session id into the manifest.
SID=$(jq -r .browserbase.session_id .o11y/my-run/manifest.json)
CONNECT_URL="$(browse cloud sessions get "$SID" | jq -r .connectUrl)"
BROWSE_NAME=my-run-browser
browse open https://example.com --cdp "$CONNECT_URL" --session "$BROWSE_NAME"
browse open https://news.ycombinator.com --session "$BROWSE_NAME"
# 3. Stop the tracer, bisect, then pull platform artifacts and release.
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
node scripts/bb-finalize.mjs my-run --release
```
Attaching to a session that's *already running* (e.g. one your production worker created) — `bb-capture.mjs` accepts a session id instead of `--new`:
```bash
# Pick a running session (filter client-side; browse cloud sessions list has no --status flag)
browse cloud sessions list | jq -r '.[] | select(.status == "RUNNING") | .id'
node scripts/bb-capture.mjs <session-id> mid-flight-debug
# ...tracer runs alongside the existing automation client; no disruption...
node scripts/stop-capture.mjs mid-flight-debug
node scripts/bisect-cdp.mjs mid-flight-debug
node scripts/bb-finalize.mjs mid-flight-debug # without --release: leave the session running
```
#### What you get from the Browserbase platform
`bb-capture.mjs` adds a `browserbase` block to `manifest.json` (session id, project, region, started_at, expires_at, debugger URL). `bb-finalize.mjs` writes:
- `<run>/browserbase/session.json` — final `browse cloud sessions get` snapshot (proxyBytes, status, ended_at, viewport, …)
- `<run>/browserbase/logs.json` — `browse cloud sessions logs` output. **Often empty.** The CDP firehose in `cdp/raw.ndjson` is the source of truth; this is a side channel.
- `<run>/browserbase/downloads.zip` — files the session downloaded, if any (the script discards the empty 22-byte zip you get when there are none)
Session replay artifact fetching is **deprecated** and isn't fetched. Use the screenshots + DOM dumps in `screenshots/` and `dom/` for visual ground truth.
The live `debugger_url` in the manifest opens an interactive Chrome DevTools view served by Browserbase — handy for *watching* a long-running automation while the tracer captures the firehose to disk.
## Filesystem layout
```
.o11y/<run-id>/
manifest.json run metadata: target, domains, started_at, stopped_at
index.jsonl one line per sample: {ts, screenshot, dom, url}
cdp/
raw.ndjson full CDP firehose (one JSON object per line)
summary.json {sessionId, duration, totalEvents, pages[]} — see shape below
network/{requests,responses,finished,failed,websocket}.jsonl session-wide buckets (always written)
console/{logs,exceptions}.jsonl
runtime/all.jsonl
log/entries.jsonl
page/{navigations,lifecycle,frames,dialogs,all}.jsonl
dom/all.jsonl (only if O11Y_DOMAINS includes DOM)
target/{attached,detached}.jsonl
pages/ per-page slices, indexed by top-level frameNavigated boundaries
000/ first concrete page
url.txt the URL for this page
summary.json this page's domains/network/timing block (same shape as a pages[] entry)
raw.jsonl firehose scoped to this page
network/, console/, page/, runtime/, log/, target/, dom/ same buckets, only non-empty files
screenshots/<iso-ts>.png one PNG per sample interval
dom/<iso-ts>.html one HTML dump per sample interval
browserbase/ added by bb-finalize.mjs (Browserbase runs only)
session.json final `browse cloud sessions get` snapshot (proxyBytes, status, ended_at, …)
logs.json `browse cloud sessions logs` output (often [])
downloads.zip `browse cloud sessions downloads get` output (only if the session downloaded files)
```
When a run was started via `bb-capture.mjs`, `manifest.json` also carries a top-level `browserbase` block: `session_id`, `project_id`, `region`, `started_at`, `expires_at`, `keep_alive`, `debugger_url`.
### Summary shape
`cdp/summary.json` is the entry point for any analysis: it has session-level totals and a `pages[]` array indexed by top-level `Page.frameNavigated`. Per-page entries are emitted in navigation order (page 0 = first concrete URL).
```json
{
"sessionId": "45f28023-…",
"duration": { "startMs": 1777312533000, "endMs": 1777312609000, "totalMs": 76000 },
"totalEvents": 420,
"pages": [
{
"pageId": 0,
"url": "https://example.com/",
"startMs": 1777312533000, "endMs": 1777312538886, "durationMs": 5886,
"eventCount": 60,
"domains": {
"Network": { "count": 18, "errors": 1 },
"Console": { "count": 2 },
"Page": { "count": 24 },
"Runtime": { "count": 13 }
},
"network": { "requests": 4, "failed": 1, "byType": { "Document": 2, "Script": 1, "Other": 1 } }
}
]
}
```
`startMs` / `endMs` / `durationMs` are wall-clock ms, derived from `manifest.started_at` plus the offset of each event's CDP monotonic timestamp. `domains[*]` only includes `errors`/`warnings` keys when non-zero.
### Drilling in with `query.mjs`
For interactive exploration, use `scripts/query.mjs <run-id> <command>` instead of remembering paths:
```bash
node scripts/query.mjs my-run list # one-line table of pages
node scripts/query.mjs my-run page 1 # full summary for page 1
node scripts/query.mjs my-run page 1 network/failed # cat failed.jsonl for page 1
node scripts/query.mjs my-run errors # all errors across pages, attributed by pid
node scripts/query.mjs my-run errors 2 # errors from page 2 only
node scripts/query.mjs my-run hosts # top hosts by request count
node scripts/query.mjs my-run host api.example.com # all requests/responses for a host
node scripts/query.mjs my-run summary # full summary.json
```
Behind the scenes it just reads `cdp/summary.json` and the `cdp/pages/<pid>/` tree — feel free to bypass it with raw `jq`/`rg` once you know the shape.
## Top traversal recipes
```bash
# All failed network requests (use jq -c to keep it line-delimited)
jq -c '.params' .o11y/<run>/cdp/network/failed.jsonl
# Find requests to a specific host
jq -c 'select(.params.request.url | test("api\\.example\\.com"))' \
.o11y/<run>/cdp/network/requests.jsonl
# 4xx/5xx responses
jq -c 'select(.params.response.status >= 400)
| {status: .params.response.status, url: .params.response.url}' \
.o11y/<run>/cdp/network/responses.jsonl
# Console errors only
jq -c 'select(.params.type == "error")' .o11y/<run>/cdp/console/logs.jsonl
# Sequence of URLs visited
jq -r '.params.frame.url' .o11y/<run>/cdp/page/navigations.jsonl
# Find the screenshot taken closest to a timestamp (e.g., when an exception fired)
ls .o11y/<run>/screenshots/ | sort | awk -v t=20260427T1714123NZ '
$0 >= t { print; exit }'
```
See **REFERENCE.md** for the full jq recipe library and a method-by-method bisect map. See **EXAMPLES.md** for end-to-end debug scenarios.
## Best practices
1. **Use `bb-capture.mjs` on Browserbase**: it enforces `--keep-alive`, fetches the connectUrl, captures the debugger URL, and stamps the manifest. Doing it manually invites mistakes.
2. **Don't `--release` a session you don't own**: `bb-finalize.mjs --release` is for sessions *you* created with `--new`. When attaching to a production session via `bb-capture.mjs <session-id>`, run `bb-finalize.mjs` without `--release` so the original automation keeps running.
3. **Order matters for remote**: on Browserbase, attach the main automation client before (or together with) the tracer, and create the session with `--keep-alive`. Otherwise the session ends as soon as the tracer's WS closes.
4. **Don't poll faster than ~1s**: each sample runs browser CLI read commands and screenshots Chrome. 2s is a good default.
5. **Pick domains deliberately**: defaults (`Network Console Runtime Log Page`) cover most debugging. Add `DOM` for DOM-tree mutations (very noisy) via `O11Y_DOMAINS="$O11Y_DOMAINS DOM"`.
6. **Reuse one Browserbase session for the automation client on remote** by attaching to that session's `connectUrl` with `browse open ... --cdp "$CONNECT_URL" --session <name>`. The `--session` flag names the local browse daemon; it is not a Browserbase session attach flag.
7. **Always run `stop-capture.mjs`**, even after a crash, so background processes don't linger and the manifest gets `stopped_at`.
8. **Bisect once per run**: `bisect-cdp.mjs` is idempotent — it overwrites the per-bucket files from `raw.ndjson` each time.
## Troubleshooting
- **`browse cdp exited immediately`**: usually means the target is unreachable (wrong port) or the Browserbase session has already ended. For remote, verify with `browse cloud sessions get <id>` — if `status` is `COMPLETED`, recreate with `--keep-alive` and attach automation first.
- **Empty `raw.ndjson` even though processes are running**: confirm a CDP client is actually driving the page. The tracer only emits events that the browser generates, so an idle browser produces ~5 lines of attach/discover messages and nothing else.
- **Screenshots all look identical**: check `index.jsonl` — if `url` doesn't change, the page hasn't navigated yet. The polling loop runs independently of the main automation's pace.
- **Browserbase session ends mid-run**: it likely hit `--timeout`. Recreate with a higher timeout (`BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...`) or remove the timeout flag.
- **`bb-capture.mjs <id>` says "not RUNNING"**: the session you tried to attach to ended. List candidates with `browse cloud sessions list | jq '.[] | select(.status == "RUNNING")'` and try again.
- **`browserbase/logs.json` is empty `[]`**: expected — `browse cloud sessions logs` is sparse in practice. The CDP firehose in `cdp/raw.ndjson` is the source of truth.
- **Where's the session recording (rrweb)?**: session replay artifact fetching is deprecated; this skill doesn't fetch it. Use the screenshot stream in `screenshots/` and DOM dumps in `dom/`.
For full reference, see [REFERENCE.md](REFERENCE.md).
For example debug runs, see [EXAMPLES.md](EXAMPLES.md).





首页
