Before this change, the main skill served by the CLI (`agent-browser
skills get agent-browser`) was a ~40-line discovery stub whose content
was essentially "run `agent-browser skills get <name>` before doing
anything." Agents already inside the CLI got no signal from it — the
content they needed to actually use the tool lived only in the `--full`
references.
Split the two jobs apart:
- **`skill-data/core/`** (new) — the runtime usage guide. 420-line
`SKILL.md` covering the snapshot-and-ref loop, common workflows
(login, extract, screenshot, multi-tab, sessions, iframes, dialogs),
waiting strategies, element selection strategies, troubleshooting,
and when to load a specialized skill. Supplementary `references/` and
`templates/` (moved from `skills/agent-browser/`) provide the full
command reference under `--full`.
- **`skills/agent-browser/SKILL.md`** — still the discovery stub that
`npx skills add` installs, now marked `hidden: true` so it stays out
of `skills list` inside the CLI. Body is a clean pointer to
`agent-browser skills get core` and the specialized skills.
The `hidden: true` frontmatter flag is a new, general mechanism: skills
marked hidden are omitted from `skills list` and `skills get --all` but
can still be fetched by explicit name. This keeps the stub reachable
for anyone who installed via `npx skills add` without polluting the
CLI-side skill listing.
## Behavior
```
$ agent-browser skills list
agentcore Run agent-browser on AWS Bedrock AgentCore cloud browsers...
core Core agent-browser usage guide. Read this before running...
dogfood Systematically explore and test a web application...
electron Automate Electron desktop apps (VS Code, Slack, Discord...)
slack Interact with Slack workspaces using browser automation...
vercel-sandbox Run agent-browser + Chrome inside Vercel Sandbox microVMs...
$ agent-browser skills get core # the actual usage guide
# ~420 lines of workflows, patterns, troubleshooting
$ agent-browser skills get agent-browser # still works if called explicitly
# the thin stub, now pointing at `core`
```
External `npx skills add vercel-labs/agent-browser` behavior is
unchanged: it finds and installs the thin `agent-browser` stub, which
tells the agent to run `agent-browser skills get core` for real
content. Version drift protection is preserved — the stub is the only
thing that gets copied; the real content is always runtime-fetched.
## Updated
- `cli/src/skills.rs` — `SkillInfo.hidden: bool`, parsed from
frontmatter; `run_list` and `run_get --all` filter it. 3 new unit
tests for the frontmatter parser.
- `cli/src/output.rs` — top-level `--help` and `skills` subcommand help
reference `skills get core` / `skills get core --full`.
- `AGENTS.md` — "update these files for user-facing features" now
points at `skill-data/core/` instead of the stub, with a note that
the stub is not the right place for feature content.
- `README.md`, `docs/src/app/skills/page.mdx` — describe the new
split and `skills get core --full` as the recommended entry point.
- `evals/cases/{command-usage,skill-selection}.ts` — expect
`skills get core` in agent output instead of `skills get
agent-browser`. Eval lib still reads `skills/agent-browser/SKILL.md`
(simulating what an agent sees after `npx skills add`).
All 11 skills unit tests pass. `cargo clippy -- -D warnings` and
`cargo fmt --check` clean. Verified end-to-end: `skills list` shows
`core` + specialized (no stub), `skills get core` returns the new
content, `skills get agent-browser` still returns the stub on explicit
request.
304 lines
8.2 KiB
Markdown
304 lines
8.2 KiB
Markdown
# Authentication Patterns
|
|
|
|
Login flows, session persistence, OAuth, 2FA, and authenticated browsing.
|
|
|
|
**Related**: [session-management.md](session-management.md) for state persistence details, [SKILL.md](../SKILL.md) for quick start.
|
|
|
|
## Contents
|
|
|
|
- [Import Auth from Your Browser](#import-auth-from-your-browser)
|
|
- [Persistent Profiles](#persistent-profiles)
|
|
- [Session Persistence](#session-persistence)
|
|
- [Basic Login Flow](#basic-login-flow)
|
|
- [Saving Authentication State](#saving-authentication-state)
|
|
- [Restoring Authentication](#restoring-authentication)
|
|
- [OAuth / SSO Flows](#oauth--sso-flows)
|
|
- [Two-Factor Authentication](#two-factor-authentication)
|
|
- [HTTP Basic Auth](#http-basic-auth)
|
|
- [Cookie-Based Auth](#cookie-based-auth)
|
|
- [Token Refresh Handling](#token-refresh-handling)
|
|
- [Security Best Practices](#security-best-practices)
|
|
|
|
## Import Auth from Your Browser
|
|
|
|
The fastest way to authenticate is to reuse cookies from a Chrome session you are already logged into.
|
|
|
|
**Step 1: Start Chrome with remote debugging**
|
|
|
|
```bash
|
|
# macOS
|
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222
|
|
|
|
# Linux
|
|
google-chrome --remote-debugging-port=9222
|
|
|
|
# Windows
|
|
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
|
|
```
|
|
|
|
Log in to your target site(s) in this Chrome window as you normally would.
|
|
|
|
> **Security note:** `--remote-debugging-port` exposes full browser control on localhost. Any local process can connect and read cookies, execute JS, etc. Only use on trusted machines and close Chrome when done.
|
|
|
|
**Step 2: Grab the auth state**
|
|
|
|
```bash
|
|
# Auto-discover the running Chrome and save its cookies + localStorage
|
|
agent-browser --auto-connect state save ./my-auth.json
|
|
```
|
|
|
|
**Step 3: Reuse in automation**
|
|
|
|
```bash
|
|
# Load auth at launch
|
|
agent-browser --state ./my-auth.json open https://app.example.com/dashboard
|
|
|
|
# Or load into an existing session
|
|
agent-browser state load ./my-auth.json
|
|
agent-browser open https://app.example.com/dashboard
|
|
```
|
|
|
|
This works for any site, including those with complex OAuth flows, SSO, or 2FA -- as long as Chrome already has valid session cookies.
|
|
|
|
> **Security note:** State files contain session tokens in plaintext. Add them to `.gitignore`, delete when no longer needed, and set `AGENT_BROWSER_ENCRYPTION_KEY` for encryption at rest. See [Security Best Practices](#security-best-practices).
|
|
|
|
**Tip:** Combine with `--session-name` so the imported auth auto-persists across restarts:
|
|
|
|
```bash
|
|
agent-browser --session-name myapp state load ./my-auth.json
|
|
# From now on, state is auto-saved/restored for "myapp"
|
|
```
|
|
|
|
## Persistent Profiles
|
|
|
|
Use `--profile` to point agent-browser at a Chrome user data directory. This persists everything (cookies, IndexedDB, service workers, cache) across browser restarts without explicit save/load:
|
|
|
|
```bash
|
|
# First run: login once
|
|
agent-browser --profile ~/.myapp-profile open https://app.example.com/login
|
|
# ... complete login flow ...
|
|
|
|
# All subsequent runs: already authenticated
|
|
agent-browser --profile ~/.myapp-profile open https://app.example.com/dashboard
|
|
```
|
|
|
|
Use different paths for different projects or test users:
|
|
|
|
```bash
|
|
agent-browser --profile ~/.profiles/admin open https://app.example.com
|
|
agent-browser --profile ~/.profiles/viewer open https://app.example.com
|
|
```
|
|
|
|
Or set via environment variable:
|
|
|
|
```bash
|
|
export AGENT_BROWSER_PROFILE=~/.myapp-profile
|
|
agent-browser open https://app.example.com/dashboard
|
|
```
|
|
|
|
## Session Persistence
|
|
|
|
Use `--session-name` to auto-save and restore cookies + localStorage by name, without managing files:
|
|
|
|
```bash
|
|
# Auto-saves state on close, auto-restores on next launch
|
|
agent-browser --session-name twitter open https://twitter.com
|
|
# ... login flow ...
|
|
agent-browser close # state saved to ~/.agent-browser/sessions/
|
|
|
|
# Next time: state is automatically restored
|
|
agent-browser --session-name twitter open https://twitter.com
|
|
```
|
|
|
|
Encrypt state at rest:
|
|
|
|
```bash
|
|
export AGENT_BROWSER_ENCRYPTION_KEY=$(openssl rand -hex 32)
|
|
agent-browser --session-name secure open https://app.example.com
|
|
```
|
|
|
|
## Basic Login Flow
|
|
|
|
```bash
|
|
# Navigate to login page
|
|
agent-browser open https://app.example.com/login
|
|
agent-browser wait --load networkidle
|
|
|
|
# Get form elements
|
|
agent-browser snapshot -i
|
|
# Output: @e1 [input type="email"], @e2 [input type="password"], @e3 [button] "Sign In"
|
|
|
|
# Fill credentials
|
|
agent-browser fill @e1 "user@example.com"
|
|
agent-browser fill @e2 "password123"
|
|
|
|
# Submit
|
|
agent-browser click @e3
|
|
agent-browser wait --load networkidle
|
|
|
|
# Verify login succeeded
|
|
agent-browser get url # Should be dashboard, not login
|
|
```
|
|
|
|
## Saving Authentication State
|
|
|
|
After logging in, save state for reuse:
|
|
|
|
```bash
|
|
# Login first (see above)
|
|
agent-browser open https://app.example.com/login
|
|
agent-browser snapshot -i
|
|
agent-browser fill @e1 "user@example.com"
|
|
agent-browser fill @e2 "password123"
|
|
agent-browser click @e3
|
|
agent-browser wait --url "**/dashboard"
|
|
|
|
# Save authenticated state
|
|
agent-browser state save ./auth-state.json
|
|
```
|
|
|
|
## Restoring Authentication
|
|
|
|
Skip login by loading saved state:
|
|
|
|
```bash
|
|
# Load saved auth state
|
|
agent-browser state load ./auth-state.json
|
|
|
|
# Navigate directly to protected page
|
|
agent-browser open https://app.example.com/dashboard
|
|
|
|
# Verify authenticated
|
|
agent-browser snapshot -i
|
|
```
|
|
|
|
## OAuth / SSO Flows
|
|
|
|
For OAuth redirects:
|
|
|
|
```bash
|
|
# Start OAuth flow
|
|
agent-browser open https://app.example.com/auth/google
|
|
|
|
# Handle redirects automatically
|
|
agent-browser wait --url "**/accounts.google.com**"
|
|
agent-browser snapshot -i
|
|
|
|
# Fill Google credentials
|
|
agent-browser fill @e1 "user@gmail.com"
|
|
agent-browser click @e2 # Next button
|
|
agent-browser wait 2000
|
|
agent-browser snapshot -i
|
|
agent-browser fill @e3 "password"
|
|
agent-browser click @e4 # Sign in
|
|
|
|
# Wait for redirect back
|
|
agent-browser wait --url "**/app.example.com**"
|
|
agent-browser state save ./oauth-state.json
|
|
```
|
|
|
|
## Two-Factor Authentication
|
|
|
|
Handle 2FA with manual intervention:
|
|
|
|
```bash
|
|
# Login with credentials
|
|
agent-browser open https://app.example.com/login --headed # Show browser
|
|
agent-browser snapshot -i
|
|
agent-browser fill @e1 "user@example.com"
|
|
agent-browser fill @e2 "password123"
|
|
agent-browser click @e3
|
|
|
|
# Wait for user to complete 2FA manually
|
|
echo "Complete 2FA in the browser window..."
|
|
agent-browser wait --url "**/dashboard" --timeout 120000
|
|
|
|
# Save state after 2FA
|
|
agent-browser state save ./2fa-state.json
|
|
```
|
|
|
|
## HTTP Basic Auth
|
|
|
|
For sites using HTTP Basic Authentication:
|
|
|
|
```bash
|
|
# Set credentials before navigation
|
|
agent-browser set credentials username password
|
|
|
|
# Navigate to protected resource
|
|
agent-browser open https://protected.example.com/api
|
|
```
|
|
|
|
## Cookie-Based Auth
|
|
|
|
Manually set authentication cookies:
|
|
|
|
```bash
|
|
# Set auth cookie
|
|
agent-browser cookies set session_token "abc123xyz"
|
|
|
|
# Navigate to protected page
|
|
agent-browser open https://app.example.com/dashboard
|
|
```
|
|
|
|
## Token Refresh Handling
|
|
|
|
For sessions with expiring tokens:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Wrapper that handles token refresh
|
|
|
|
STATE_FILE="./auth-state.json"
|
|
|
|
# Try loading existing state
|
|
if [[ -f "$STATE_FILE" ]]; then
|
|
agent-browser state load "$STATE_FILE"
|
|
agent-browser open https://app.example.com/dashboard
|
|
|
|
# Check if session is still valid
|
|
URL=$(agent-browser get url)
|
|
if [[ "$URL" == *"/login"* ]]; then
|
|
echo "Session expired, re-authenticating..."
|
|
# Perform fresh login
|
|
agent-browser snapshot -i
|
|
agent-browser fill @e1 "$USERNAME"
|
|
agent-browser fill @e2 "$PASSWORD"
|
|
agent-browser click @e3
|
|
agent-browser wait --url "**/dashboard"
|
|
agent-browser state save "$STATE_FILE"
|
|
fi
|
|
else
|
|
# First-time login
|
|
agent-browser open https://app.example.com/login
|
|
# ... login flow ...
|
|
fi
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
1. **Never commit state files** - They contain session tokens
|
|
```bash
|
|
echo "*.auth-state.json" >> .gitignore
|
|
```
|
|
|
|
2. **Use environment variables for credentials**
|
|
```bash
|
|
agent-browser fill @e1 "$APP_USERNAME"
|
|
agent-browser fill @e2 "$APP_PASSWORD"
|
|
```
|
|
|
|
3. **Clean up after automation**
|
|
```bash
|
|
agent-browser cookies clear
|
|
rm -f ./auth-state.json
|
|
```
|
|
|
|
4. **Use short-lived sessions for CI/CD**
|
|
```bash
|
|
# Don't persist state in CI
|
|
agent-browser open https://app.example.com/login
|
|
# ... login and perform actions ...
|
|
agent-browser close # Session ends, nothing persisted
|
|
```
|