# Gsd Browser

> Open GSD native browser automation for AI agents. Use gsd-browser when the user needs real Chrome/Chromium control: navigate pages, inspect localhost, click, type, fill forms, take screenshots, capture stable snapshot refs, run assertions and waits, extract structured data, compare visual diffs, inspect console/network behavior, mock or block requests, emulate devices, save auth state, record evidence bundles, scan for prompt injection, or share a live browser viewer for human handoff. Good prompts include "inspect this URL", "verify this user flow", "debug this page", "capture evidence", "scrape this table", "show me the browser", "pause/step through this", "login to a site", or "run a visual regression test". Learn more at https://opengsd.net/ and https://github.com/open-gsd/gsd-browser.

- Skill: `open-gsd/gsd-browser` (Agent Skill, multi-file: 10 files)
- Install (CLI): `npx skillmds@latest add open-gsd/gsd-browser`
- Raw SKILL.md: https://api.skillmd.com/api/skills/open-gsd/gsd-browser/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: open-gsd (https://skillmd.com/u/open-gsd)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/open-gsd/gsd-browser

---


# Browser Automation with gsd-browser

**Primary path for AI agents in 2026+:** Use the MCP server — `gsd-browser mcp`.

It exposes **50+ tools**, live resources (real snapshot/refs/state data), and executable prompts over stdio. All the unique strengths (versioned refs, live viewer + human collaboration/takeover/annotations/recordings, semantic intents, evidence bundles, self-healing action cache, batch execution, vault, visual regression, safety scanning, etc.) are available automatically to Cursor, Claude Desktop, VS Code + Copilot, and any other MCP client.

**Quickstart for agents:**
```bash
gsd-browser mcp
```
Then point your MCP client at it (see `./scripts/mcp-quickstart.sh cursor` or `claude`/`vscode` for tailored configs).

**Essential reading for MCP agents:**
- `docs/mcp.md` — Architecture, capabilities, client config examples, quickstart script.
- `docs/AGENT-BEST-PRACTICES.md` — Golden rules, recommended workflows (login, audit, human-in-the-loop, evidence, self-healing), "When to Use What" table, response envelope usage, prompt/resource patterns.
- `docs/examples/mcp-client-config.json` — Ready example.

The detailed command reference, error recovery, and workflow patterns in this SKILL.md document the exact semantics of the MCP tools (they are a direct 1:1 mapping). Use this as the source of truth when an MCP tool needs deeper clarification.

The installable curated skill pack lives in `gsd-browser-skill/` (installed via the main installer or `gsd-browser skill install`).

## Critical Rules (apply to both direct CLI and MCP usage)

1. **The daemon auto-starts on browser commands.** `daemon health` only reports state; it does not start a session. Use `daemon start` only when you want to pre-warm or verify daemon lifecycle explicitly.
2. **Always re-snapshot after page changes.** Refs are versioned (`@v1:e1`). After navigation, form submission, or dynamic content loading, old refs are stale. Run `gsd-browser snapshot` (or read the `gsd-browser://latest-snapshot` MCP resource) to get fresh refs.
3. **Use `--json` when parsing output.** Use text mode when reading output yourself. Use `--json` when you need to extract values programmatically (e.g., checking assertion results, parsing snapshot refs). MCP tools return rich envelopes containing structured_data.
4. **Positional args have no flag prefix.** Commands like `click`, `type`, `hover` take positional args — do NOT add `--selector`. See exact syntax in command reference below. (MCP equivalents: `browser_click_ref` etc. take `ref` as a simple string param.)
5. **Use `batch` for atomic multi-step flows.** Batch reduces round trips and keeps pass/fail checks in one call. Use separate commands when you need intermediate output (e.g., snapshot to discover refs). MCP equivalent: `browser_batch`.
6. **Use `view` when the user wants to watch or direct the browser.** The live viewer is an authenticated local workbench with Control, Annotate, Record, and Sensitive modes. Keep CLI/MCP commands on the same named session. MCP tools: `browser_view`, `browser_takeover`, `browser_annotation_request`, `browser_record_*`, `browser_goal`, etc.

## Core Workflow

Every browser automation follows this pattern:

1. **Navigate**: `gsd-browser navigate <url>` (or `browser_navigate` via MCP)
2. **Snapshot**: `gsd-browser snapshot` (get versioned refs like `@v1:e1`, `@v1:e2`) — or read MCP resource `gsd-browser://latest-snapshot`
3. **Interact**: Use refs to click, fill, hover (or `browser_act` semantic intents first)
4. **Re-snapshot**: After navigation or DOM changes, get fresh refs

```bash
gsd-browser navigate https://example.com/form
gsd-browser snapshot
# Output: @v1:e1 [input type="email"], @v1:e2 [input type="password"], @v1:e3 [button] "Submit"

gsd-browser fill-ref @v1:e1 "user@example.com"
gsd-browser fill-ref @v1:e2 "password123"
gsd-browser click-ref @v1:e3
gsd-browser wait-for --condition network_idle
gsd-browser snapshot  # REQUIRED — old refs are now stale
```

**MCP agents:** After any navigation or major action, prefer re-reading `gsd-browser://latest-snapshot` (or calling `browser_snapshot`) before using `_ref` tools.

## Command Chaining

Commands can be chained with `&&` in a single shell invocation. Browser state also persists across separate invocations through the background daemon when you stay on the same session.

```bash
# Chain navigate + wait + snapshot
gsd-browser navigate https://example.com && gsd-browser wait-for --condition network_idle && gsd-browser snapshot

# Chain multiple interactions
gsd-browser fill-ref @v1:e1 "user@example.com" && gsd-browser fill-ref @v1:e2 "password123" && gsd-browser click-ref @v1:e3
```

**When to chain:** Use `&&` when you don't need intermediate output. Run commands separately when you need to parse output first (e.g., snapshot to discover refs, then interact). For MCP, use `browser_batch` for atomicity.

---

## Command Reference

Argument syntax: `<arg>` = required positional, `[arg]` = optional positional, `--flag` = named option. Do NOT add `--` prefix to positional args.

(MCP tool names are `browser_` + kebab-to-snake of the CLI command where applicable. Full authoritative list and schemas are returned live by the MCP server via `tools/list`. See `docs/mcp.md` and `docs/AGENT-BEST-PRACTICES.md` for agent-optimized usage.)

### Navigation

```bash
gsd-browser navigate <url>                        # Navigate to a URL
gsd-browser back                                   # Go back in browser history
gsd-browser forward                                # Go forward in browser history
gsd-browser reload                                 # Reload the current page
```

### Interaction

All selectors are **positional** — do NOT use `--selector`.

```bash
# Click
gsd-browser click <selector>                       # Click by CSS selector
gsd-browser click --x 100 --y 200                  # Click by coordinates (no selector)

# Type — positional: <selector> <text>
gsd-browser type <selector> <text>                 # Atomic fill (replaces content)
gsd-browser type <selector> <text> --slowly        # Character-by-character
gsd-browser type <selector> <text> --clear-first   # Clear field before typing
gsd-browser type <selector> <text> --submit        # Press Enter after typing

# Other interaction — all positional selectors
gsd-browser press <key>                            # Press key: Enter, Escape, Tab, Meta+A
gsd-browser hover <selector>                       # Hover over element
gsd-browser scroll --direction down                # Scroll down 300px (default)
gsd-browser scroll --direction up --amount 500     # Scroll up 500px
gsd-browser select-option <selector> <option>      # Select dropdown by label or value
gsd-browser set-checked <selector> --checked       # Check checkbox/radio (omit --checked to uncheck)
gsd-browser drag <source-selector> <target-selector>  # Drag-and-drop
gsd-browser upload-file <selector> <file>...       # Set files on <input type="file">
gsd-browser set-viewport --preset mobile           # Preset: mobile, tablet, desktop, wide
gsd-browser set-viewport --width 1920 --height 1080  # Custom dimensions
```

### Natural-Language Instruction Action

Use `act-instruction` for short, action-oriented browser instructions when an agent or user has natural language and the page has clear live DOM affordances. It plans against visible fields, typed controls (text, number/spinner, range/slider, date/time/month/week, color), buttons, options, checkboxes/switches, drag targets, revealable panels/tabs, repeated item rows, and simple DOM-visible counts, then dispatches bounded primitive commands. It is generic browser automation, not a benchmark script.

```bash
gsd-browser act-instruction "enter 'alice@example.com' into Email and click Continue"
gsd-browser act-instruction --dry-run "choose California from State"
gsd-browser act-instruction --scope "form#billing" "enter '94107' into ZIP and click Save"
gsd-browser act-instruction --min-confidence 0.7 --dry-run "click the destructive action"
gsd-browser act-instruction --max-steps 3 "check Red, Green, and Blue"
```

MCP clients use `browser_act_instruction` with the same controls: `instruction`, `dry_run`, `scope`, `min_confidence`, and `max_steps`.

Every plan is grounded in an instruction page model: visible DOM/accessibility elements, bounds, labels, grouping context, and inferred affordances such as clickable, fillable, selectable, checkable, slider, and scrollable. Dry runs include this model for inspection. Executed actions include a verification summary comparing before/after page models so agents can tell whether the requested action produced an observable effect.

Best use cases:

- Natural-language tasks like "fill both fields with cat", "select monthly", "drag item A to Done", or "click Submit".
- Typed-control tasks like "select 42 with the slider", "use the spinner to select 7", "set date to 2026-06-04", or "set color to red".
- Discovery tasks like "expand sections to find and click the link", simple repeated-row choices like "buy the shortest duration", and DOM-visible counting tasks like "how many blue letters are there?".
- Ambiguous pages where `--dry-run`, `--scope`, or `--min-confidence` can make the plan inspectable before execution.
- Small compound actions where a bounded sequence is simpler than hand-building a batch.

Prefer refs, `browser_fill_form`, or `browser_batch` for critical flows, long workflows, canvas/image-only reasoning, or cases where exact element identity matters more than interpretation.

### Snapshot & Refs

Refs are versioned (`@v1:e1`, `@v2:e3`). The version increments each snapshot. **Old refs become stale after page changes — always re-snapshot.**

```bash
# Take snapshot
gsd-browser snapshot                               # Snapshot interactive elements, assign refs
gsd-browser snapshot --selector "form"             # Scope to a CSS selector
gsd-browser snapshot --mode <mode>                 # Semantic mode (see below)
gsd-browser snapshot --limit 80                    # Increase element limit (default: 40)

# Use refs — all positional
gsd-browser get-ref <ref>                          # Get metadata for a ref
gsd-browser click-ref <ref>                        # Click element by ref
gsd-browser hover-ref <ref>                        # Hover element by ref
gsd-browser fill-ref <ref> <text>                  # Type into element by ref
```

**Snapshot modes** (`--mode`):

| Mode | What it captures |
|------|-----------------|
| `interactive` | Buttons, inputs, links, selects (default) |
| `form` | Form fields with labels and current values |
| `dialog` | Elements inside open dialogs/modals |
| `navigation` | Links and nav elements |
| `errors` | Error messages, validation warnings |
| `headings` | Heading elements (h1-h6) for page structure |
| `visible_only` | All visible elements regardless of interactivity |

### Inspection

```bash
gsd-browser accessibility-tree                     # Full accessibility tree (roles, names, states)
gsd-browser find --text "Sign In"                  # Find elements by text (case-insensitive)
gsd-browser find --role button                     # Find by ARIA role
gsd-browser find --selector ".my-class"            # Find by CSS selector
gsd-browser find --role link --limit 50            # Increase limit (default: 20)
gsd-browser page-source                            # Get raw HTML of page
gsd-browser page-source --selector "main"          # Scoped HTML source
gsd-browser eval '<js-expression>'                 # Evaluate JavaScript in page context
```

### Assertions

Run explicit pass/fail checks against the current page state. Prefer this over inferring success from output.

```bash
gsd-browser assert --checks '[
  {"kind": "url_contains", "text": "/dashboard"},
  {"kind": "text_visible", "text": "Welcome"},
  {"kind": "selector_visible", "selector": "#user-menu"},
  {"kind": "value_equals", "selector": "input[name=email]", "value": "user@test.com"},
  {"kind": "no_console_errors"},
  {"kind": "no_failed_requests"}
]'
```

**Assertion kinds (18):** `url_contains`, `title_contains`, `text_visible`, `text_hidden`, `selector_visible`, `selector_hidden`, `value_equals`, `checked`, `no_console_errors`, `no_failed_requests`, `request_url_seen`, `response_status`, `console_message_matches`, `network_count`, `console_count`, `element_count`, `no_console_errors_since`, `no_failed_requests_since`.

### Batch Execution

Execute multiple steps in one call to reduce round trips. Stops on first failure by default.

```bash
gsd-browser batch --steps '[
  {"action": "navigate", "url": "https://example.com"},
  {"action": "wait_for", "condition": "network_idle"},
  {"action": "click", "selector": "#login-btn"},
  {"action": "type", "selector": "input[name=email]", "text": "user@test.com"},
  {"action": "type", "selector": "input[name=password]", "text": "secret", "submit": true},
  {"action": "assert", "checks": [{"kind": "url_contains", "text": "/dashboard"}]}
]'
```

# With --summary-only to reduce output
gsd-browser batch --steps '[...]' --summary-only
```

**Batch actions:** `navigate`, `click`, `type`, `key_press`, `wait_for`, `assert`, `click_ref`, `fill_ref`.

(MCP: `browser_batch` — highly recommended for complex agent flows.)

### Wait Conditions

```bash
gsd-browser wait-for --condition selector_visible --value "#content"
gsd-browser wait-for --condition selector_hidden --value ".spinner"
gsd-browser wait-for --condition url_contains --value "/dashboard"
gsd-browser wait-for --condition network_idle
gsd-browser wait-for --condition delay --value 2000
gsd-browser wait-for --condition text_visible --value "Success"
gsd-browser wait-for --condition text_hidden --value "Loading"
gsd-browser wait-for --condition request_completed --value "/api/data"
gsd-browser wait-for --condition console_message --value "ready"
gsd-browser wait-for --condition element_count --value ".item" --threshold ">=5"
gsd-browser wait-for --condition region_stable --value "#content"

# Custom timeout (default: 10000ms)
gsd-browser wait-for --condition selector_visible --value "#slow" --timeout 30000
```

### Forms (Smart Fill)

Analyze forms and fill them by field label, name, placeholder, or aria-label — no selectors needed.

```bash
# Analyze form structure
gsd-browser analyze-form
gsd-browser analyze-form --selector "#signup-form"

# Fill by field identifiers (resolved: label -> name -> placeholder -> aria-label)
gsd-browser fill-form --values '{"Email": "a@b.com", "Password": "secret", "Country": "US"}'
gsd-browser fill-form --values '{"Email": "a@b.com"}' --submit  # Fill and click submit
gsd-browser fill-form --values '{"Email": "a@b.com"}' --selector "#login-form"
```

### Intent-Based Interaction

Find and act on elements by semantic intent — no selectors or refs needed. Intents are predefined categories, not free-form text.

```bash
# Find top candidates for an intent (returns scored matches with selectors)
gsd-browser find-best --intent submit_form
gsd-browser find-best --intent accept_cookies
gsd-browser find-best --intent primary_cta --scope "#modal"

# Act: find best match and click/focus it in one call
gsd-browser act --intent submit_form
gsd-browser act --intent accept_cookies
gsd-browser act --intent fill_email
```

**Intents (15):**

| Intent | Action | Description |
|--------|--------|-------------|
| `submit_form` | click | Submit buttons, form actions |
| `close_dialog` | click | Modal/dialog close buttons |
| `primary_cta` | click | Primary call-to-action elements |
| `search_field` | focus | Search inputs and searchboxes |
| `next_step` | click | Next/continue/proceed buttons |
| `dismiss` | click | Dismiss overlays, banners, toasts |
| `auth_action` | click | Login/signup/register buttons |
| `back_navigation` | click | Back/previous navigation links |
| `fill_email` | focus | Email input fields |
| `fill_password` | focus | Password input fields |
| `fill_username` | focus | Username/login input fields |
| `accept_cookies` | click | Cookie consent accept buttons |
| `main_content` | click | Main content area (`<main>`, `<article>`, semantic markup required) |
| `pagination_next` | click | Next page in pagination |
| `pagination_prev` | click | Previous page in pagination |

(MCP equivalents: `browser_act`, `browser_find_best`, `browser_find_element` for resilience.)

### Pages & Frames

Page and frame IDs are **positional** — do NOT use `--id`.

```bash
gsd-browser list-pages                             # List all open tabs
gsd-browser switch-page <id>                       # Switch to tab by ID (positional)
gsd-browser close-page <id>                        # Close a tab by ID (positional)

gsd-browser list-frames                            # List all frames (main + iframes)
gsd-browser select-frame --name "iframe-name"      # Select frame by name
gsd-browser select-frame --url-pattern "embed"     # Select frame by URL substring
gsd-browser select-frame --index 0                 # Select by index
gsd-browser select-frame --name main               # Return to main frame
```

### Diagnostics

```bash
gsd-browser console                                # Get console log entries (clears buffer)
gsd-browser console --no-clear                     # Read without clearing
gsd-browser network                                # Get network log entries
gsd-browser dialog                                 # Get dialog events (alert, confirm, prompt)
gsd-browser timeline                               # Query the action timeline
gsd-browser session-summary                        # Diagnostic summary of current session
gsd-browser debug-bundle                           # Full debug bundle: screenshot + logs + timeline + a11y tree
```

(MCP: `browser_debug_bundle`, `browser_console`, `browser_network`, etc. — use early when stuck.)

### Live Viewer & Workbench

The live viewer is a localhost screen-sharing and control surface for the active browser session. It prints or opens a tokenized URL bound to the session, viewer id, local origin, expiry, and capabilities. The viewer displays live frames, narrated action history, ref overlays, target rings, click ripples, failure markers, and page-following across navigation or tab changes.

```bash
gsd-browser view                                   # Open the live viewer
gsd-browser view --print-only                      # Print tokenized URL only
gsd-browser view --interactive                     # Interactive local workbench
gsd-browser view --history                         # Open history-focused viewer
gsd-browser view --history --print-only            # Print history URL only

gsd-browser goal "Find the checkout button"        # Set viewer goal banner
gsd-browser goal --clear                           # Clear goal banner

gsd-browser control-state                          # Show shared owner/mode/version
gsd-browser takeover                               # Give page input to the viewer
gsd-browser release-control                        # Return page input to the agent
gsd-browser pause                                  # Pause before next narrated action
gsd-browser resume                                 # Resume actions
gsd-browser step                                   # Allow one action, then pause
gsd-browser abort                                  # Abort next gated action
gsd-browser sensitive-on                           # Local human control with redaction
gsd-browser sensitive-off                          # Leave sensitive mode
```

Use one named session for the whole shared-screen flow:

```bash
gsd-browser --session demo navigate https://example.com
gsd-browser --session demo view --print-only
gsd-browser --session demo click "h1"
```

Viewer controls:

| Control | Effect |
|---------|--------|
| Control | Forwards pointer, wheel, keyboard, text, and paste input to Chrome |
| Annotate | Creates point annotations without forwarding page input |
| Record | Starts or stops a local recording bundle |
| Sensitive | Keeps local viewer control active and applies redaction policy |
| Pause | Blocks agent page input |
| Resume | Allows actions to continue |
| Step | Allows one action, then returns to paused mode |
| Abort | Aborts the next gated action |
| Refs overlay | Shows or hides target boxes/labels |

Keyboard shortcuts: Space pauses/resumes, Right Arrow steps, Escape aborts, `R` toggles refs.

Risky visible targets such as destructive labels, payment actions, OAuth grants, credential entry, file transfer, production/admin surfaces, and cross-origin navigation produce an approval banner. Approval dispatches the exact pending command stored by the daemon.

Annotations:

```bash
gsd-browser annotations
gsd-browser annotation-get <id>
gsd-browser annotation-clear <id>
gsd-browser annotation-clear --all
gsd-browser annotation-resolve <id>
gsd-browser annotation-export --output annotations.json
gsd-browser annotation-request "Select the button to restyle"
```

Recording bundles:

```bash
gsd-browser record-start --name checkout-bug
gsd-browser record-stop
gsd-browser record-pause
gsd-browser record-resume
gsd-browser recordings
gsd-browser recording-get <id>
gsd-browser recording-export <id> --output <path>
gsd-browser recording-discard <id>
gsd-browser recording-validate <id-or-path> --json
```

**Replayable evidence bundles as first-class test artifacts (PR 1-6):** After `record-stop` (or during viewer Record mode), use `recording-export` (or pass recordingId directly) to produce a portable bundle containing enriched events (before/after DOM, full network slices PR5), redacted state snapshots, manifest with replayable:true. Then turn it into a high-quality, commit-ready Playwright regression test:

```js
browser_generate_replayable_test({ "recordingId": "rec_abc123", "name": "checkout-regression", "output": "tests/checkout.spec.ts" })
// or from exported bundle dir:
browser_generate_replayable_test({ "bundlePath": "./evidence/checkout-bug-2026-05", "output": "tests/checkout.spec.ts" })
```

The generated test includes: command replay, rich per-step DOM assertions (counts/text/structural with expected-vs-actual diffs), save_state restoration (redacted *.pwstate.json ready for storageState), full slice network assertions + optional HAR subset. **Safety:** states are redacted on export (sensitive cookies/tokens -> [REDACTED:...]); manifest records redaction policy. **MVP limits:** locators based on ephemeral refs need human review/refinement for robustness; DOM counts are tolerant smoke checks (use the diff comments). Prefer this over legacy `generate-test` for any flow you want as a durable regression artifact.

Viewer annotations and recording bundles are local daemon artifacts. Recording manifests use `BrowserArtifactBundleV1`, ordered JSONL events, redaction metadata, and local artifact directories under the browser state path. Use `recording-validate` on exported bundles to confirm replayable status for CI/audit.

Use `--no-narration-delay` for fast agent-only runs that keep narration events/history without lead-time sleeps:

```bash
gsd-browser --session demo --no-narration-delay click "h1"
```

(MCP agents: These are among the highest-leverage capabilities. See `browser_view`, `browser_takeover`, `browser_annotation_*`, `browser_record_*`, `browser_goal`, `browser_step` etc. in the MCP surface and the best-practices guide.)

### Visual

```bash
gsd-browser screenshot                             # Screenshot to stdout (JPEG base64)
gsd-browser screenshot --output page.png           # Write to file
gsd-browser screenshot --format png                # Force PNG format
gsd-browser screenshot --full-page                 # Full scrollable page
gsd-browser screenshot --selector "#hero"          # Crop to element (always PNG)
gsd-browser screenshot --quality 50                # JPEG quality 1-100 (default: 80)

gsd-browser zoom-region --x 100 --y 200 --width 400 --height 300  # Capture region
gsd-browser zoom-region --x 0 --y 0 --width 200 --height 200 --scale 3  # Upscale

gsd-browser save-pdf                               # Save page as PDF (A4 default)
gsd-browser save-pdf --output report.pdf           # Custom output path
gsd-browser save-pdf --format Letter               # Page format: A4, Letter, Legal, Tabloid
```

### Visual Regression

```bash
# First run: saves baseline screenshot
gsd-browser visual-diff --name "homepage"

# Subsequent runs: compare against baseline, report mismatch
gsd-browser visual-diff --name "homepage"
gsd-browser visual-diff --name "homepage" --threshold 0.05   # Stricter tolerance (0-1)
gsd-browser visual-diff --selector "#hero" --name "hero"     # Scope to element
gsd-browser visual-diff --name "homepage" --update-baseline  # Reset baseline
```

### Structured Data Extraction

```bash
# Single item
gsd-browser extract --schema '{
  "type": "object",
  "properties": {
    "title": {"_selector": "h1", "_attribute": "textContent"},
    "price": {"_selector": ".price", "_attribute": "textContent"},
    "image": {"_selector": "img.product", "_attribute": "src"}
  }
}'

# Array of items
gsd-browser extract --selector ".product-card" --multiple --schema '{
  "type": "object",
  "properties": {
    "name": {"_selector": "h3", "_attribute": "textContent"},
    "price": {"_selector": ".price", "_attribute": "textContent"}
  }
}'
```

### Network Mocking

```bash
gsd-browser mock-route --url "**/api/users*" --body '[{"name":"Alice"}]' --status 200
gsd-browser mock-route --url "**/api/data" --body '{"ok":true}' --delay 3000  # Slow response
gsd-browser block-urls "**/analytics*" "**/ads*"   # Block URL patterns (positional)
gsd-browser clear-routes                           # Remove all mocks and blocks
```

### Device Emulation

```bash
gsd-browser emulate-device <device-name>           # Full device emulation (positional)
gsd-browser emulate-device "iPhone 15"
gsd-browser emulate-device "Pixel 7"
gsd-browser emulate-device "iPad Pro 11"
gsd-browser emulate-device list                    # Show all available presets
```

**Warning:** Device emulation recreates the browser context — current page state and cookies are lost.

### State & Auth

```bash
# Save/restore browser state (cookies, localStorage, sessionStorage)
gsd-browser save-state --name "logged-in"
gsd-browser restore-state --name "logged-in"

# Auth vault (encrypted credentials)
gsd-browser vault-save --profile github --url https://github.com/login \
  --username user --password "secret"
gsd-browser vault-login --profile github
gsd-browser vault-list                             # List profiles (no secrets shown)
```

Vault encryption requires `GSD_BROWSER_VAULT_KEY` env var set **before the daemon starts**. If the daemon is already running, stop it first, set the var, then run your vault command.

### Tracing & Recording

```bash
gsd-browser trace-start                            # Start CDP performance trace
gsd-browser trace-start --name "checkout-flow"     # Named trace
gsd-browser trace-stop                             # Stop and write trace to disk
gsd-browser trace-stop --name "checkout.json"      # Custom output filename

gsd-browser har-export                             # Export network as HAR 1.2 JSON
gsd-browser har-export --filename "session.har"    # Custom output path

# Legacy (timeline only — limited assertions):
gsd-browser generate-test --name "login-flow" --output tests/login.spec.ts

# Recommended (PR5+): full replayable evidence bundle workflow for rich, safe, stateful regression tests
# (record flow → export/validate → browser_generate_replayable_test). See "Recording bundles" section above and AGENT-BEST-PRACTICES.md.
# MCP tool call:
# browser_generate_replayable_test({ "bundlePath": "./my-evidence-bundle", "name": "login-regression", "output": "tests/login.spec.ts" })
```

### Security

```bash
gsd-browser check-injection                        # Scan for prompt injection in page content
gsd-browser check-injection --include-hidden       # Include hidden/invisible text (default: true)
```

### Action Cache

Reduce repeated element lookups by caching intent-to-selector mappings (especially powerful for long-running MCP agent sessions with named sessions).

```bash
gsd-browser action-cache --action stats            # Show cache metrics
gsd-browser action-cache --action get --intent submit_form  # Look up cached selector
gsd-browser action-cache --action put --intent submit_form --selector "#submit-btn" --score 0.95
gsd-browser action-cache --action clear            # Flush cache
```

(MCP: `browser_action_cache` — use for self-healing across agent runs.)

### Daemon Management

The daemon auto-starts on browser commands. These are for explicit lifecycle control.

```bash
gsd-browser daemon stop                            # Stop daemon (idempotent — safe on dead processes)
gsd-browser daemon health                          # Health check (read-only, does not auto-start)
gsd-browser daemon start                           # Explicit start (pre-warm browser before commands)
gsd-browser mcp                                    # Run MCP server over stdio
gsd-browser cloud-methods                          # Print the cloud browser method manifest
gsd-browser update                                 # Install the current release
```

---

## Global Options

Available on all commands:

| Flag | Description |
|------|-------------|
| `--json` | Output as JSON (use when parsing output programmatically) |
| `--browser-path <path>` | Path to Chrome/Chromium binary |
| `--cdp-url <url>` | Attach to an already-running Chrome (e.g. `http://localhost:9222`) |
| `--session <name>` | Named session for parallel browser instances |
| `--no-narration-delay` | Skip narration lead-time sleeps while keeping history/events |

For MCP: pass `session` as a top-level argument to most tools; configure env vars in your MCP client config.

---

## Error Recovery

(See also `gsd-browser-skill/references/error-recovery.md` for the curated agent skill version.)

### Stale refs

```
Error: resolve_ref: JS evaluation failed: ref @v1:e3 not found
```

Refs become stale after page changes. Fix: re-snapshot and use the new version.

```bash
gsd-browser snapshot        # Get fresh refs (@v2:eN)
gsd-browser click-ref @v2:e1
```

(MCP agents: read `gsd-browser://latest-snapshot` resource or call `browser_snapshot`.)

### Click/type timeouts

```
Error: click timed out after 10s for: #submit-btn
```

The element may not be visible, may be behind an overlay, or may not exist. Try:

```bash
gsd-browser find --selector "#submit-btn"          # Verify element exists
gsd-browser scroll --direction down                # Scroll it into view
gsd-browser wait-for --condition selector_visible --value "#submit-btn"  # Wait for it
gsd-browser click "#submit-btn"                    # Retry
```

### Empty console/network logs

Console and network buffers start fresh each navigation. If you need logs from a specific action, check them **before** navigating away:

```bash
gsd-browser navigate https://example.com
gsd-browser eval "fetch('/api/data')"
gsd-browser network                                # Check network BEFORE navigating away
```

### Cookie banners / overlays blocking interaction

Many sites show consent banners that block clicks. Dismiss them first:

```bash
gsd-browser act --intent accept_cookies            # Auto-find and click accept button
gsd-browser act --intent dismiss                   # Or dismiss generic overlays
```

### Session is stopped, unhealthy, or opens a fresh blank page

If `daemon health` reports `stopped` or `unhealthy`, or a named session no longer has the page you expected, that session does not currently map to a live daemon/browser pair.

```bash
gsd-browser --session site1 daemon health
gsd-browser --session site1 daemon stop
gsd-browser --session site1 navigate https://example.com
```

Use the same `--session` value on every follow-up command. `batch` is still useful for atomic flows, but separate invocations are supported when the session is healthy.

### Daemon won't start

```
Error: daemon did not start within 10s
```

Usually the session is unhealthy, startup exited early, or browser launch state is stale. Fix:

```bash
gsd-browser daemon health                          # Inspect current state
gsd-browser daemon stop                            # Clear the current session state
gsd-browser daemon start                           # Retry explicit startup
```

---

## Common Patterns

(See the MCP best-practices doc for agent-native versions of these flows using tools/resources/prompts.)

### Form Submission

```bash
gsd-browser navigate https://example.com/signup
gsd-browser analyze-form                           # Discover field labels and types
gsd-browser fill-form --values '{"Full Name": "Jane Doe", "Email": "jane@example.com", "State": "California"}' --submit
gsd-browser wait-for --condition network_idle
gsd-browser assert --checks '[{"kind": "text_visible", "text": "Welcome"}]'
```

### Login Flow (Refs)

```bash
gsd-browser navigate https://app.example.com/login
gsd-browser act --intent accept_cookies            # Dismiss cookie banner if present
gsd-browser snapshot
# Read snapshot output to find email, password, and submit refs
gsd-browser fill-ref @v1:e1 "$USERNAME"
gsd-browser fill-ref @v1:e2 "$PASSWORD"
gsd-browser click-ref @v1:e3
gsd-browser wait-for --condition url_contains --value "/dashboard"
gsd-browser save-state --name "myapp-auth"         # Save for reuse
```

### Login Flow (Vault)

```bash
# Save credentials once (encrypted at rest)
gsd-browser vault-save --profile myapp \
  --url https://app.example.com/login \
  --username user@example.com \
  --password "$PASSWORD"

# Login in any future session
gsd-browser vault-login --profile myapp
gsd-browser wait-for --condition url_contains --value "/dashboard"
```

### Reuse Saved Auth

```bash
gsd-browser restore-state --name "myapp-auth"
gsd-browser navigate https://app.example.com/dashboard  # Already logged in
```

### Data Scraping

```bash
gsd-browser navigate https://example.com/products
gsd-browser extract --selector ".product" --multiple --schema '{
  "type": "object",
  "properties": {
    "name": {"_selector": ".title", "_attribute": "textContent"},
    "price": {"_selector": ".price", "_attribute": "textContent"},
    "link": {"_selector": "a", "_attribute": "href"}
  }
}'
```

### Visual Regression Testing

```bash
# Establish baseline (first run)
gsd-browser navigate https://example.com
gsd-browser visual-diff --name "home-page"

# Later: compare current state
gsd-browser navigate https://example.com
gsd-browser visual-diff --name "home-page"
# Output: similarity %, diff pixel count, diff image path
```

### Network Mocking for Testing

```bash
gsd-browser mock-route --url "**/api/users" --body '{"error":"server error"}' --status 500
gsd-browser navigate https://app.example.com
gsd-browser assert --checks '[{"kind": "text_visible", "text": "Something went wrong"}]'
gsd-browser clear-routes                           # Clean up mocks
```

### Parallel Sessions

```bash
gsd-browser --session site1 navigate https://site-a.com
gsd-browser --session site2 navigate https://site-b.com

gsd-browser --session site1 snapshot
gsd-browser --session site2 snapshot

# Clean up both
gsd-browser --session site1 daemon stop
gsd-browser --session site2 daemon stop
```

### Performance Audit

```bash
gsd-browser navigate https://example.com
gsd-browser trace-start --name "perf-audit"
# ... interact with the page ...
gsd-browser trace-stop --name "perf-audit.json"
gsd-browser har-export --filename "network.har"
```

### Prompt Injection Scanning

```bash
gsd-browser navigate https://untrusted-page.com
gsd-browser check-injection
# Returns severity-rated findings for visible and hidden injection patterns
```

---

## Configuration

### Config Files (TOML)

gsd-browser loads config with 5-layer merge precedence:

1. Compiled defaults
2. User config: `~/.gsd-browser/config.toml`
3. Project config: `./gsd-browser.toml`
4. Environment variables: `GSD_BROWSER_*`
5. CLI flags (highest priority)

Example `gsd-browser.toml`:

```toml
[browser]
path = "/usr/bin/chromium"

[daemon]
port = 9222
host = "127.0.0.1"

[screenshot]
quality = 90
format = "png"
full_page = false

[settle]
timeout_ms = 500
poll_ms = 40
quiet_window_ms = 100

[logs]
max_buffer_size = 1000

[artifacts]
dir = "./browser-artifacts"

[timeline]
max_entries = 500
```

### Environment Variables

Supported config overrides use `GSD_BROWSER_<SECTION>_<FIELD>` naming:

```bash
GSD_BROWSER_BROWSER_PATH=/usr/bin/chromium
GSD_BROWSER_DAEMON_PORT=9223
GSD_BROWSER_SCREENSHOT_QUALITY=90
GSD_BROWSER_SETTLE_TIMEOUT_MS=1000
GSD_BROWSER_VAULT_KEY=your-encryption-key
```

For MCP clients, set these in the `env` block of your mcpServer definition (especially `GSD_BROWSER_VAULT_KEY` and browser path).

---

## Session Cleanup

Always stop the daemon when done to avoid leaked Chrome processes:

```bash
gsd-browser daemon stop
```

For parallel sessions:

```bash
gsd-browser --session agent1 daemon stop
gsd-browser --session agent2 daemon stop
```

---

## Additional Resources for Agents

- **MCP-first experience**: `docs/mcp.md`, `docs/AGENT-BEST-PRACTICES.md`, `./scripts/mcp-quickstart.sh`
- **Curated skill pack for coding agents**: `gsd-browser-skill/SKILL.md` + `references/` + `workflows/` (install via the main installer)
- **Illustrative replayable test artifact examples** (pedagogical approximations only): `docs/examples/replayable-test-artifact/` (manifest.json, events.jsonl, redacted pwstate, generated .spec.ts) — see file banners + AGENT-BEST-PRACTICES.md for ground-truth pointers to viewer.rs + codegen.rs. Produce live bundles for real use.
- **AGENTS.md** (repo root) — high-level pointer
- **README.md** — highlights and install instructions

The MCP server makes gsd-browser a first-class, extremely powerful browser platform for agents. The content in this SKILL.md remains the complete reference for every capability exposed via MCP.

