agentsclimarketplace

Browser profile

Skill vanducng/skills/skills/browser-profile

Manage named persistent browser profiles (cookies, localStorage, IndexedDB, cache) that both you and Claude can use against the SAME Chrome window without collisions. Each profile lives in its own `--user-data-dir` and exposes a deterministic `--remote-debugging-port`. Use when the user says "open profile X", "attach to profile X", "log me into staging once and reuse it", or asks to test frontend flows with persistent auth across runs. Pairs with the `agent-browser` CLI (`agent-browser connect <port>`) for the CDP attach step.From its SKILL.md

Install
npx -y skills add vanducng/skills --skill browser-profile

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 6 commands, including `npm install -g agent-browser` and 5 more.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.6 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

browser-profile

A thin profile registry on top of Chrome's --user-data-dir + --remote-debugging-port. Solves three problems at once:

  1. Persistent state per logical user. Cookies, localStorage, IndexedDB, disk cache survive across runs.
  2. Manual access. You open the profile in real Chrome and log in / poke around without Claude involved.
  3. Programmatic access on the same window. Claude attaches via CDP using agent-browser connect <port> - no separate Chromium spawn, no SingletonLock collision.

Why not Playwright launchPersistentContext? Because that path requires Playwright to own the browser lifecycle - you can't have a normal Chrome window on the same user-data-dir simultaneously. The CDP-attach pattern here lets both of you share one window; connect-over-CDP is exactly how agent-browser participates in it. That's also why agent-browser must attach in connect mode, never --profile mode: profile mode launches its own Playwright-owned browser, which breaks the shared window this skill exists to provide.

When to use

  • Frontend tests where re-running the login flow on every iteration is wasteful or impossible (MFA, SSO).
  • Long-lived debugging sessions where you want to come back tomorrow and have the same logged-in dashboards.
  • Hand-off flows: you log in manually, then ask Claude to drive the rest.

Not for: cloud-only / anti-bot use cases (use Browserbase contexts via vd:browser --context-id instead) or one-shot ephemeral scraping (just use agent-browser directly, no profile needed).

Prerequisites

  • macOS with Google Chrome at /Applications/Google Chrome.app (override via BROWSER_PROFILE_CHROME env var).
  • agent-browser CLI on PATH (npm install -g agent-browser, then one-time agent-browser install) - used by attach.
  • Optional: jq for pretty profile list output.

Quick start

SKILL="${CLAUDE_SKILL_DIR:-$(for d in "$HOME/skills/skills/browser-profile" "$HOME/.claude/skills/browser-profile" "$HOME/.agents/skills/browser-profile"; do [ -d "$d" ] && { echo "$d"; break; }; done)}/scripts"

# 1. Open a fresh profile manually (you'll log in once)
"$SKILL/profile-open.sh" retell-staging

# 2. In another shell - let Claude attach to that same window
"$SKILL/profile-attach.sh" retell-staging
# → env-sanitized `agent-browser connect <port-for-retell-staging>` + UA verification

# 3. List profiles and their status
"$SKILL/profile-list.sh"

# 4. When done
"$SKILL/profile-close.sh" retell-staging

Naming convention: <env>-<role>. Examples: retell-staging, goclaw-admin, cnb-snowflake-ui.

Command reference

ScriptPurpose
profile-open.sh <name>Launch headed Chrome with the profile's user-data-dir and deterministic debug port. Creates the dir on first run. Refuses if already open.
profile-attach.sh <name>Run env-sanitized agent-browser connect <port> so the agent-browser daemon drives this profile's Chrome (connect mode, never --profile), then verify the attachment via navigator.userAgent. Probes the CDP endpoint first; suggests open if nothing is listening.
profile-list.shShow all profiles with status (open / closed), port, dir size.
profile-close.sh <name>Send SIGTERM to the Chrome PID for that profile, clear stale lock files.
profile-export.sh <name> [<out.json>]Dump cookies + localStorage as Playwright-compatible storageState.json for CI replay. Requires the profile to be open.
profile-reset.sh <name>Destructive. Wipe the profile dir. Asks for confirmation.

How port allocation works

Ports are deterministic from the profile name so attach doesn't need a registry file:

port = 9300 + (cksum(name) % 100)

Range 9300–9399 avoids the conventional 9222. If two names hash to the same port, open will fail loudly - rename one.

Profile directory layout

$HOME/.claude/browser-profiles/
├── retell-staging/
│   ├── Default/                 # Chrome user data (cookies.db, Local Storage/, IndexedDB/, Cache/, …)
│   ├── DevToolsActivePort       # written by Chrome on launch; contains the actual port + WS path
│   ├── SingletonLock            # dangling symlink to "<hostname>-<pid>"; may be stale after a crash
│   └── .browser-profile.pid     # PID of the Chrome process we launched (for `close`)
└── goclaw-admin/
    └── ...

SingletonLock is Chrome's own collision marker - a dangling symlink whose target encodes <hostname>-<pid> (so -f/-e tests see nothing; only -L does). The scripts treat a profile as open only when that PID is a live Chrome whose command line carries this --user-data-dir; stale locks left by crashed sessions are cleared automatically on open.

Security

  • Profile dirs are created with chmod 700. Storage cookies are tied to your user account.
  • Never commit $HOME/.claude/browser-profiles/ to any repo.
  • Same applies to storageState.json exports - those are bearer credentials.
  • The skill never prints cookies / tokens to stdout.

Integration points

  • vd:cook flows that hit authenticated dashboards - start a step with profile-attach.sh <name> so agent-browser is pre-connected to the right session.
  • vd:browser-trace - attaches as a third CDP client on the same target, gets a full trace without interfering. Use the profile's deterministic port as the trace target.
  • vd:web-e2e - project-aware full e2e on top of these profiles: boot/health checks, auth-state probing, flows, and reports. The e2e config's profile field names a profile managed here.
  • Playwright storageState fixtures - export storageState.json once, then any Playwright test (local or CI) gets the same identity via { storageState: '<path>' }.

Troubleshooting

SymptomCauseFix
open refuses: "profile already open"A live Chrome owns this profileRun profile-close.sh <name> first, or use profile-attach.sh if you intended to share
list shows no-cdpChrome is running but not answering on the deterministic port (launched without the debug flag, or another Chrome took over)profile-close.sh <name> then profile-open.sh <name>
attach says "no CDP endpoint"Chrome not running on that portRun profile-open.sh <name> first
Cookies disappear after sleep/wakeService-worker eviction by ChromeRe-login. Chrome's call, not ours. Open issue if reproducible.
Port collision between two profilescksum hash collisionRename one of them (e.g., add a -2 suffix)
Chrome won't launch (corrupted profile)Crash during last sessionprofile-reset.sh <name> and re-login - wipes the whole dir

Future (deliberately out of scope for MVP)

  • Cross-platform Chrome path resolution (Linux, Windows).
  • Registry JSON with last_used, custom port overrides, descriptions.
  • Auto-renew expired cookies via headless re-login.
  • Headless mode for CI - use profile-export.sh + Playwright storageState instead; persistent-context headless is flaky upstream.

What ships with it: 7 files

10.0 KB alongside SKILL.md, 7 of them executable

scripts/

Gives 0 of the 12 instructions most context ai engineering skills give in ~1.7k tokens

Counted across 1,328 of the 2,349 authors here whose files we hold, read 2026-09-06

  • Dispatch a fresh subagent for each taskin 76 of 1328, across 59 files
  • Perform spec compliance review before code quality reviewin 44 of 1328, across 34 files
  • Dispatch a final code reviewer after all tasksin 38 of 1328, across 26 files
  • Answer subagent questions before allowing implementationin 36 of 1328, across 26 files
  • Use the least powerful model capable of the taskin 33 of 1328, across 26 files
  • Create a TodoWrite list for all tasksin 32 of 1328, across 22 files
  • Perform a task review after each implementationin 31 of 1328, across 24 files
  • Extract all tasks and context from the planin 29 of 1328, across 20 files
  • Provide full task text to subagentsin 28 of 1328, across 20 files
  • Use git worktrees for isolated workspacesin 25 of 1328, across 20 files
  • Specify the model explicitly when dispatching a subagentin 23 of 1328, across 18 files
  • Execute all tasks from the plan without stoppingin 21 of 1328, across 16 files

Said here and by no other author read

  • Use profile-open.sh to launch a headed Chrome profile
  • Use profile-attach.sh to connect the agent to a profile
  • Use profile-list.sh to view all profiles and status
  • Use profile-close.sh to terminate a profile session
  • Use profile-export.sh to dump cookies and localStorage
  • Use profile-reset.sh to wipe a profile directory

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.