From playwright-profiles
This skill should be used when the user asks to "capture auth for my app", "sign into deckchecker", "save login for seatify", "add my app to playwright auth", "authenticate to my site", "set up QA user profiles", "sign in as admin", "sign in as planner", or wants to set up reusable authenticated browsing for a custom web app. Triggers on app names, custom domains, multi-user/QA auth, or any request to save auth state for a URL that is not a well-known external service. Complements auth-browse (external services) by handling the user's own apps and custom sites.
npx claudepluginhub neonwatty/playwright-profiles --plugin playwright-profilesThis skill uses the workspace's default tool permissions.
Save reusable authenticated browser sessions for custom web apps (the user's own projects, client apps, staging environments, etc.) using the persistent Chrome profile at `~/.playwright-cli/`.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Save reusable authenticated browser sessions for custom web apps (the user's own projects, client apps, staging environments, etc.) using the persistent Chrome profile at ~/.playwright-cli/.
waitFor patternsBoth use the same ~/.playwright-cli/sign-in.mjs script and shared Chrome profile.
Ask the user for:
deckchecker, seatify-staging, client-portal). Used as the identifier for future sign-ins.https://deckchecker.app/login, https://staging.seatify.app/login)./dashboard — most common/home/eventsIf the user does not know the post-login URL, suggest common patterns or tell them to skip it (the script will use manual Enter instead).
Run via Bash:
node ~/.playwright-cli/sign-in.mjs add <name> <login-url> <wait-for-pattern>
Example:
node ~/.playwright-cli/sign-in.mjs add deckchecker https://deckchecker.app/login /dashboard
If no waitFor was provided, omit the third argument — the script defaults to the hostname.
Tell the user to run the sign-in command in a separate terminal:
node ~/.playwright-cli/sign-in.mjs login <name>
The script defaults to Playwright's built-in Chromium, which works while Chrome is open. Custom apps rarely have bot detection, so this is almost always fine. If the user's app uses Google OAuth for login and it gets blocked, retry with --tier chrome (Chrome must be closed first):
node ~/.playwright-cli/sign-in.mjs login <name> --tier chrome
This is interactive — Claude cannot run it. The user signs in manually. The script auto-detects completion using the waitFor pattern (defaults to the hostname when omitted from add). The user can also press Enter at any time to save manually.
After the user confirms sign-in is complete, validate the captured auth:
node ~/.playwright-cli/sign-in.mjs check <name>
Review the output:
--persistent --profile instead.If the app uses Supabase (look for sb-*-auth-token in the check output), note the real session TTL. Supabase access tokens typically expire in 1 hour — inform the user that profiles will need refresh before each work session.
Then test browsing:
For the user's own apps (no bot detection), use state-load — it injects cookies into the existing headless session without interfering with per-repo session isolation or cli.config.json settings:
playwright-cli open <app-url>
playwright-cli state-load ~/.playwright-cli/auth-<name>.json
playwright-cli reload
playwright-cli snapshot
Take a snapshot to confirm the user is signed in. If the app redirects to the login page, the session may not have saved correctly — re-run sign-in.
Only use --persistent --profile when state-load fails (sites with bot detection like Cloudflare Turnstile or Google OAuth). Note: --browser chrome launches the real Chrome app and can conflict with the user's personal Chrome on macOS — close the session promptly when done.
playwright-cli open <app-url> --headed --browser chrome --persistent --profile ~/.playwright-cli/chrome-profile
Tell the user:
<name>node ~/.playwright-cli/sign-in.mjs login <name>state-load (headless, non-interfering with session isolation)auth-<name>.json); multiple accounts on the same domain need distinct site names (e.g., seatify-admin, seatify-planner)For apps that need multiple authenticated users (e.g., testing admin vs planner roles), use --profile to isolate each user's Chrome session. Without --profile, all sign-ins share a single Chrome profile — meaning a second sign-in to the same domain overwrites the first user's cookies.
node ~/.playwright-cli/sign-in.mjs add seatify-admin https://seatify.app/login /dashboard
node ~/.playwright-cli/sign-in.mjs add seatify-planner https://seatify.app/login /dashboard
Tell the user to run each in a separate terminal:
node ~/.playwright-cli/sign-in.mjs login seatify-admin --profile seatify-admin
node ~/.playwright-cli/sign-in.mjs login seatify-planner --profile seatify-planner
The --profile <name> flag creates an isolated Chrome directory at ~/.playwright-cli/chrome-profile-<name>/. Each user's session is completely independent.
Multi-user profiles on the same domain share auth files keyed by site name (e.g., auth-seatify-admin.json, auth-seatify-planner.json). Since each role has a distinct site name, state-load works:
playwright-cli open https://seatify.app/dashboard
playwright-cli state-load ~/.playwright-cli/auth-seatify-admin.json
playwright-cli reload
To switch users, load a different auth file:
playwright-cli state-load ~/.playwright-cli/auth-seatify-planner.json
playwright-cli reload
If state-load doesn't work (bot detection), fall back to the persistent profile:
playwright-cli open https://seatify.app/dashboard --headed --browser chrome \
--persistent --profile ~/.playwright-cli/chrome-profile-seatify-admin
Use <app>-<role> as both the site name and profile name: seatify-admin, seatify-planner, deckchecker-owner, client-portal-reviewer. This keeps auth files and Chrome profiles aligned.
For apps with multiple environments (production, staging, dev), register each as a separate site:
node ~/.playwright-cli/sign-in.mjs add seatify https://seatify.app/login /dashboard
node ~/.playwright-cli/sign-in.mjs add seatify-staging https://staging.seatify.app/login /dashboard
node ~/.playwright-cli/sign-in.mjs add seatify-dev http://localhost:3000/login /dashboard
Combine with --profile for multi-user across environments:
node ~/.playwright-cli/sign-in.mjs add seatify-staging-admin https://staging.seatify.app/login /dashboard
node ~/.playwright-cli/sign-in.mjs login seatify-staging-admin --profile seatify-staging-admin
When helping the user determine the waitFor pattern, suggest these common patterns:
| Framework / Pattern | Typical post-login URL |
|---|---|
| Next.js with dashboard | /dashboard |
| SPA with hash routing | #/home or #/dashboard |
| Supabase Auth redirect | /dashboard or the redirectTo path |
| OAuth callback | The final redirect after /auth/callback |
| Multi-step onboarding | /onboarding or /setup |
If unsure, the user can sign in manually (Enter-based) first, then check the browser URL bar to discover the pattern. They can update the site config later with add (same name overwrites).
Once a session is captured, the user can ask Claude to browse the app naturally:
Claude should check auth status first, then browse using the two-tier approach:
state-load (default for custom apps)Injects cookies into the existing headless session. Non-interfering — respects cli.config.json, session isolation, and headless mode.
# Single-user app
playwright-cli open <url>
playwright-cli state-load ~/.playwright-cli/auth-<name>.json
playwright-cli reload
# Multi-user / QA — each role is a separate site name
playwright-cli open <url>
playwright-cli state-load ~/.playwright-cli/auth-seatify-admin.json
playwright-cli reload
When the user mentions a role ("as admin", "as planner"), map it to the corresponding auth file (e.g., auth-deckchecker-admin.json).
--persistent --profile (bot-protected sites only)Only needed when state-load fails — typically external services with Cloudflare Turnstile or Google OAuth that fingerprint the browser itself.
# Default profile
playwright-cli open <url> --headed --browser chrome \
--persistent --profile ~/.playwright-cli/chrome-profile
# Named profile (multi-user)
playwright-cli open <url> --headed --browser chrome \
--persistent --profile ~/.playwright-cli/chrome-profile-<name>
This overrides session isolation and requires headed mode. See the auth-browse skill for details.