Skip to content

Add cookie-sync skill [Experimental]#49

Merged
shrey150 merged 14 commits intomainfrom
shrey/cookie-sync
Mar 25, 2026
Merged

Add cookie-sync skill [Experimental]#49
shrey150 merged 14 commits intomainfrom
shrey/cookie-sync

Conversation

@shrey150
Copy link
Copy Markdown
Contributor

@shrey150 shrey150 commented Mar 19, 2026

Summary

  • Adds a new cookie-sync skill that exports cookies from a local Chrome browser (via CDP) and injects them into a Browserbase cloud session
  • Enables authenticated cloud browsing with full session replay and observability — the cloud browser is logged into all the same sites as your local Chrome
  • Integrates with Browserbase Contexts for persistent cookie reuse across sessions (sync once, create many sessions)
  • Zero npm dependencies — uses Node 22+ built-in WebSocket and fetch
  • Supports Chrome 146+ (remote debugging flag) and older Chrome (--remote-debugging-port=9222), plus Brave, Edge, and Chromium

What's in the skill

File Purpose
SKILL.md Agent-facing docs with prereqs, usage, troubleshooting
scripts/cookie-sync.mjs Self-contained sync script (~200 lines)
REFERENCE.md Architecture, env vars, browser compat, security notes
EXAMPLES.md Common patterns (basic sync, context reuse, screenshots)
LICENSE.txt MIT

Context integration (new vs Shub's original)

The original script creates a plain keepAlive session. This version also creates a Browserbase Context with persist: true, so:

  1. Cookies are saved back to the context when the session ends
  2. Future sessions can reuse the context via BROWSERBASE_CONTEXT_ID env var
  3. No need to re-sync from Chrome every time (until cookies expire)

Marked as Experimental because

  • Requires Chrome 146+ or manual --remote-debugging-port flag
  • Cookie lifetime depends on target site session policies (not in our control)
  • Chrome's DevToolsActivePort file can be flaky if Chrome crashes

Test plan

  • Run cookie-sync with Chrome 146+ remote debugging enabled
  • Verify cookies are exported and injected (check cookie count)
  • Navigate to an authenticated page (e.g., Gmail) and confirm login state
  • Save context ID and create a second session reusing it
  • Verify second session starts with cookies from context

🤖 Generated with Claude Code


Note

Medium Risk
Adds a new script that exports sensitive local browser cookies and injects them into a persistent Browserbase context/session, so misconfiguration or misuse could expose credentials. Also introduces new Node dependencies and a large lockfile that may affect supply-chain/update risk.

Overview
Adds a new experimental cookie-sync skill that exports cookies from a locally running Chromium-based browser (via CDP) and injects them into a persistent Browserbase context for reuse with the browse CLI.

Includes a new Node.js CLI script (scripts/cookie-sync.mjs) with flags for domain filtering, reusing an existing context, and optional advanced stealth and geolocated residential proxy settings, plus supporting docs (SKILL.md, REFERENCE.md, EXAMPLES.md) and new npm manifests (package.json/package-lock.json) under skills/cookie-sync.

Written by Cursor Bugbot for commit 89bc7f2. This will update automatically on new commits. Configure here.

Exports cookies from a local Chrome browser (via CDP) and injects them into a
new Browserbase cloud session, enabling authenticated browsing with full session
replay and observability. Integrates with Browserbase Contexts for persistent
cookie reuse across sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
shrey150 and others added 2 commits March 19, 2026 12:16
When Chrome is launched with --remote-debugging-port (which requires
--user-data-dir and doesn't create a DevToolsActivePort file), users
can now set CDP_URL=ws://127.0.0.1:9222 instead of hacking a fake
DevToolsActivePort file. This is the only working path on Chrome stable
until chrome://flags/#allow-remote-debugging lands.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The allow-remote-debugging flag is only available in Chrome Beta/Dev/Canary
as of March 2026. Updated SKILL.md description and prerequisites so the
agent clearly communicates this limitation to users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
- --domains flag to selectively sync cookies for specific sites
- --stealth flag for Browserbase advanced stealth mode
- --proxy "City,ST,US" for residential proxy with geolocation
- --persist / --context CLI flags (replaces env-var-only config)
- addUrlsToCookies() fix: secure cookies (e.g. Google auth) were
  silently dropped by Network.setCookies without a URL field
- Chrome 146+ version check with actionable error message

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

There are 6 total unresolved issues (including 2 from previous reviews).

Autofix Details

Bugbot Autofix prepared fixes for all 4 issues found in the latest run.

  • ✅ Fixed: Documented CDP_URL env var is never read
    • Added early return in getLocalWsUrl() to check and return process.env.CDP_URL if set, enabling the documented fallback for Chrome < 146.
  • ✅ Fixed: Version check hard-exits for valid older Chrome
    • Modified checkChromeVersion() to skip version check when CDP_URL or CDP_PORT_FILE env vars are set, allowing older Chrome versions with custom debugging configurations.
  • ✅ Fixed: getDebugUrl function is defined but never called
    • Removed the unused getDebugUrl function definition to eliminate dead code.
  • ✅ Fixed: Documented BROWSERBASE_CONTEXT_ID env var is never read
    • Added fallback to process.env.BROWSERBASE_CONTEXT_ID when CLI.contextId is not provided, enabling the documented env var approach.

Create PR

Or push these changes by commenting:

@cursor push 6979b9d909
Preview (6979b9d909)
diff --git a/skills/cookie-sync/scripts/cookie-sync.mjs b/skills/cookie-sync/scripts/cookie-sync.mjs
--- a/skills/cookie-sync/scripts/cookie-sync.mjs
+++ b/skills/cookie-sync/scripts/cookie-sync.mjs
@@ -74,6 +74,10 @@
 // ---------------------------------------------------------------------------
 
 function getLocalWsUrl() {
+  if (process.env.CDP_URL) {
+    return process.env.CDP_URL;
+  }
+
   const home = homedir();
   const IS_WINDOWS = process.platform === 'win32';
 
@@ -249,10 +253,6 @@
   });
 }
 
-async function getDebugUrl(sessionId) {
-  return bbFetch(`/sessions/${sessionId}/debug`);
-}
-
 async function waitForSessionRunning(sessionId, maxWaitMs = 30000) {
   const start = Date.now();
   while (Date.now() - start < maxWaitMs) {
@@ -268,6 +268,10 @@
 // ---------------------------------------------------------------------------
 
 function checkChromeVersion() {
+  if (process.env.CDP_URL || process.env.CDP_PORT_FILE) {
+    return;
+  }
+
   const chromePaths = [
     '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
     '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta',
@@ -331,7 +335,7 @@
   }
 
   // Step 3: Set up context (create new, reuse existing, or skip)
-  let contextId = CLI.contextId;
+  let contextId = CLI.contextId || process.env.BROWSERBASE_CONTEXT_ID;
 
   if (!contextId && CLI.persist) {
     const ctx = await createContext();

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Comment thread skills/cookie-sync/scripts/cookie-sync.mjs
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
- Read CDP_URL env var in getLocalWsUrl() for Chrome < 146 fallback
- Clear dangling timeouts in CDP send() on resolve/reject
- Detect terminal session states (ERROR/TIMED_OUT/FAILED) in polling loop
- Skip Chrome version check when CDP_URL or CDP_PORT_FILE is set
- Read BROWSERBASE_CONTEXT_ID env var as fallback for --context flag
- Remove unused getDebugUrl function

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
Replace hand-rolled CDP client and raw fetch API calls with
@browserbasehq/stagehand for browser connections (local + cloud)
and @browserbasehq/sdk for context creation. This dogfoods our
own SDKs and removes ~200 lines of boilerplate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs
Pass model as { modelName, apiKey } object to match Stagehand v3 API.
Cookie sync only uses browser connection, not AI features, so a dummy
API key suffices.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs Outdated
shrey150 and others added 3 commits March 24, 2026 17:43
WSS://host was being converted to httpS://host instead of https://host
because the regex matched case-insensitively but didn't handle the
trailing 's' in wss. Now matches the full wss/ws prefix and maps to
https/http correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Stagehand defaults to openai/gpt-4.1-mini when no model is passed,
but the LLM client is created lazily and never invoked for cookie-only
operations (context.cookies / context.addCookies). The apiKey: 'unused'
hack was unnecessary — verified by tracing the constructor: the AI SDK
model object is only called when act/extract/observe are used.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Stagehand API client (api.ts:213) requires modelApiKey during
BROWSERBASE init, but this is only used for server-side AI features
we don't need. Setting disableAPI: true skips the API client entirely
(v3.ts:928) while still creating the BB session and CDP connection.

Tested e2e with OPENAI_API_KEY and ANTHROPIC_API_KEY both unset —
cookies exported from local Chrome and injected into cloud session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs
…ersion check

- Use /\r?\n/ split for DevToolsActivePort to handle Windows CRLF
- Add Linux Chrome binary names to version check (google-chrome, chromium, etc.)
- Remove existsSync gate so PATH-resolved binaries are found via execSync

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread skills/cookie-sync/scripts/cookie-sync.mjs
shrey150 and others added 2 commits March 24, 2026 22:03
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The API key is scoped to a project, so project ID is redundant.
Removed from script, SKILL.md, REFERENCE.md, and EXAMPLES.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread skills/cookie-sync/scripts/cookie-sync.mjs
Cookie-sync now always creates a persistent context and closes the
temp session after injecting cookies. This lets users browse
authenticated sites with `browse open <url> --context-id <id> --persist`
instead of the raw `node -e` WebSocket hack.

- Remove --persist flag (contexts are always created)
- Remove keepAlive: true (session closes after injection)
- Replace node -e navigation docs with browse CLI workflow
- Add troubleshooting tip for stealth/proxy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@shrey150 shrey150 merged commit 4747945 into main Mar 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants