Add browser-trace skill#83
Merged
derekmeegan merged 5 commits intomainfrom Apr 27, 2026
Merged
Conversation
Capture the full CDP firehose plus periodic screenshots and DOM dumps
alongside any browser automation (browse, Stagehand, Playwright, Puppeteer
— anything that speaks CDP), then bisect the stream into per-page
searchable buckets keyed by top-level navigations.
The skill is purely observational: it adds a second CDP client that
enables read-only domains (Network, Console, Runtime, Log, Page) and
never sends action commands, so it can attach to an in-flight automation
without disrupting it.
Layout produced under .o11y/<run-id>/:
manifest.json, index.jsonl
cdp/raw.ndjson full firehose, NDJSON
cdp/summary.json {sessionId, duration, totalEvents, pages[]}
cdp/<domain>/... session-wide buckets
cdp/pages/<pid>/ per-page slices, indexed by Page.frameNavigated
summary.json, raw.jsonl, network/, console/, page/, ...
screenshots/<iso-ts>.png, dom/<iso-ts>.html
browserbase/ added by bb-finalize.sh on remote runs
Scripts (pure bash + jq, no Python/Node deps beyond the existing browse CLI):
start-capture.sh / stop-capture.sh / snapshot-loop.sh
bisect-cdp.sh — splits raw.ndjson into session-wide and per-page buckets,
writes the structured summary.json
query.sh — drill-down helper: list, page <pid> [bucket], errors,
hosts, host <h>, timeline, summary
bb-capture.sh / bb-finalize.sh — Browserbase wrappers; bb-capture handles
--keep-alive + connectUrl resolution + manifest stamping with
the session id, region, and live debugger URL; bb-finalize
writes browserbase/{session.json, logs.json, downloads.zip}
and optionally releases the session
The CDP firehose is sourced via `browse cdp <target>`, which streams
DevTools-protocol events as NDJSON. That command requires
@browserbasehq/browse-cli alpha or a release that includes
browserbase/stagehand#1905; lifecycle events specifically require
browserbase/stagehand#2056.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the cookie-sync skill's pattern: each script becomes a Node ESM module, with a shared scripts/lib.mjs for common helpers and a minimal package.json (no dependencies — pure Node stdlib, so no `npm install` step is needed). scripts/lib.mjs shared helpers, BUCKETS table, isTopNav scripts/start-capture.mjs spawn detached `browse cdp` + sampler scripts/snapshot-loop.mjs screenshot+DOM+url poll loop (internal) scripts/stop-capture.mjs SIGTERM+grace+SIGKILL, sweep .partials scripts/bisect-cdp.mjs page-aware bisect + structured summary.json scripts/query.mjs drill-down: list/page/errors/hosts/host/timeline scripts/bb-capture.mjs Browserbase wrapper (--new or attach by id) scripts/bb-finalize.mjs pull session.json/logs.json/downloads.zip Output layout, per-page bisection logic, summary.json shape, and the query.mjs subcommands are identical to the bash versions. SKILL.md, REFERENCE.md, and EXAMPLES.md updated to invoke `node scripts/foo.mjs` instead of `bash scripts/foo.sh`. Dogfooded end-to-end against a Browserbase session and against the saved /Users/d/Desktop/browserbase/o11y-demo-1 run — page bisection, durations, error attribution, host counts all match the bash output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Shorter, more action-oriented name that reads cleanly as a slash command and pairs naturally with the autobrowse skill (which can use the trace output as the structured "what just happened" data for its loop). Renames: - skills/browser-observability/ → skills/browser-trace/ - SKILL.md frontmatter `name`, doc H1s, package.json name - marketplace.json plugin entry (name, skills path, description, keywords) - README.md skills table row - "observer" → "tracer" throughout the prose for consistency with the new name No behaviour change — all script interfaces, output layout, summary.json shape, and query.mjs subcommands are unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix three issues flagged on PR #83: - query.mjs cmdTimeline: was printing every navigation followed by every lifecycle event, so all `[NAV …]` lines bunched before any `[init]`/`[load]` lines. Now reads cdp/raw.ndjson directly and emits top-level frameNavigated and lifecycle events in actual stream order. - query.mjs cmdHost: was using `url.startsWith('https://' + hostname)`, which would match `https://api.example.com.evil.tld/...` when the user asked for `api.example.com`. Switched to exact `new URL(url).hostname` comparison via a small `hostMatches` helper. - query.mjs: removed the unused `emitJsonl` helper (defined but never called — same class of dead-code issue Bugbot raised against the bash version's `cat_bucket_across`). Bugbot also flagged the bash bb-capture.sh's `| grep ... || true` that silently swallowed start-capture failures. The .mjs version already handles this correctly via `if (start.status !== 0) process.exit(...)`, so no change needed there. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shrey150
approved these changes
Apr 27, 2026
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4f28fb7. Configure here.
Two more issues from Cursor Bugbot on PR #83: 1. Console errors and warnings were being silently dropped from the per-page summary. computePageSummary classified each event by `method.split('.')[0]`, which puts Runtime.consoleAPICalled events into a `Runtime` bucket — but errors/warnings from those events were being recorded under the key `Console`. The output loop iterates `counts.entries()` and looks up errors/warnings by that domain key, so the Console errors/warnings never made it into the rollup. Added a `domainFor(method)` helper that returns 'Console' for `Runtime.consoleAPICalled` and the standard `method.split('.')[0]` otherwise. Now matches the schema documented in SKILL.md. 2. cmdHosts grouped by `URL.host` (port included) but cmdHost compared against `URL.hostname` (port stripped), so `hosts` output couldn't be piped into `host` when a port was present. Switched `hostMatches` to `URL.host` for consistency. Impostor protection (rejecting `example.com.evil.tld` for `example.com` queries) is preserved by the exact-equality check. Verified against /Users/d/Desktop/browserbase/o11y-demo-1: every page now shows Console + Runtime as distinct domain blocks; page 4 (httpbin/418) correctly attributes the 418 status to a Log error. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
A new skill that captures a full DevTools-protocol trace alongside any browser automation, then bisects the stream into per-page searchable buckets. Drop in next to the existing
browserskill — it is purely observational, never drives the page, and works withbrowse, Stagehand, Playwright, or anything else speaking CDP.What's in the box
skills/browser-trace/:SKILL.md— when to use it, local + Browserbase quickstarts, filesystem layout, summary shape, drill-down viaquery.mjsREFERENCE.md— full bisect map, per-page drill-down recipes, Browserbase platform pairing, troubleshooting matrixEXAMPLES.md— five end-to-end debug scenarios (failing form submit, third-party network audit, page hang, prod JS-exception repro, attaching to an in-flight Browserbase session)scripts/— Node ESM, no third-party deps (so nonpm installstep):start-capture.mjs/stop-capture.mjs/snapshot-loop.mjs— lifecycle of a trace runbisect-cdp.mjs— splitsraw.ndjsoninto session-wide buckets + per-page subdirs and writes a structuredsummary.jsonquery.mjs— drill-down helper:list,page <pid> [bucket],errors,hosts,host <h>,timelinebb-capture.mjs/bb-finalize.mjs— Browserbase wrappers that handle--keep-alive,connectUrlresolution, manifest stamping (session id, region, live debugger URL), and post-run artifact pulls (bb sessions get,bb sessions logs,bb sessions downloads get)lib.mjs— shared helpers (run dir, JSONL I/O, BUCKETS table,isTopNav)Filesystem layout produced
summary.jsonis the entry point for any analysis:{ "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 } } } ] }Drilling in
Why "trace" and not "observability"
browser-tracereads more cleanly as a slash command, accurately describes the artifact (a time-ordered recording of CDP events plus aligned screenshots/DOM), and pairs naturally with future research-loop skills (e.g.autobrowse) that can use the per-page summary as their structured "what just happened" data.Compatibility note
The CDP firehose is sourced via
browse cdp <target>, which currently ships under the alpha tag of@browserbasehq/browse-cli(@browserbasehq/browse-cli@alpha, since browserbase/stagehand#1905). Lifecycle events (Page.lifecycleEvent) specifically require browserbase/stagehand#2056. The skill'scompatibility:field calls this out, and bisect/query degrade gracefully on older builds.Marketplace + README
marketplace.jsonregisters a newbrowser-traceplugin pointing at./skills/browser-trace(mirrors thebrowserbase-clipattern — companion skill, own plugin, can be installed independently).README.mdskills table gets a new row, placed in the observability cluster betweensite-debuggerandbb-usage.How it was built
Dogfooded end-to-end against:
localhost:9222bb sessions create --keep-alive+bb-capture.mjs <session-id>Each iteration ran the full pipeline (capture → automation → stop → bisect → query) and surfaced bugs (CDP timestamp clock-mixing, race on
session.jsonafter--release, partial DOM-dump cleanup) that were fixed before submission.Test plan
jq -e . .claude-plugin/marketplace.json— JSON validatesnpx skills add browserbase/skillslists the new plugin/plugin install browser-trace@browserbaseworksquery.mjs listproduces the page tableBROWSERBASE_API_KEYset —bb-capture.mjs --newstamps the manifest and prints the live debugger URL;bb-finalize.mjs --releasewrites session.json withstatus: COMPLETED🤖 Generated with Claude Code
Note
Medium Risk
Adds a new tracing skill that spawns/kills background processes, writes artifacts to disk, and can create/release Browserbase sessions via
bb, so incorrect usage could leak processes or impact active sessions. Existing skills are unchanged aside from marketplace/README registration.Overview
Introduces a new
browser-traceskill that records a read-only CDP “firehose” alongside screenshots and DOM snapshots, then post-processes the run into searchable per-domain and per-page JSONL buckets plus acdp/summary.jsonrollup.Adds Node (ESM) helper scripts to start/stop captures, bisect
raw.ndjsoninto the output tree, query runs (list,page,errors,hosts,timeline), and optionally integrate with Browserbase viabbto create/attach sessions, stamp manifests with session metadata, fetch artifacts, and optionally release sessions.Registers the new plugin in
.claude-plugin/marketplace.jsonand documents it inREADME.md, with full reference and example playbooks underskills/browser-trace/.Reviewed by Cursor Bugbot for commit 53fe4fb. Bugbot is set up for automated code reviews on this repo. Configure here.