{
  "markdown": "# agent-browser\n\nBrowser automation CLI for AI agents. Fast native Rust CLI.\n\n[![skills.sh](https://skills.sh/b/vercel-labs/agent-browser)](https://skills.sh/vercel-labs/agent-browser)\n\n## Installation\n\n### Global Installation (recommended)\n\nInstalls the native Rust binary:\n\n```bash\nnpm install -g agent-browser\nagent-browser install  # Download Chrome from Chrome for Testing (first time only)\n```\n\n### Project Installation (local dependency)\n\nFor projects that want to pin the version in `package.json`:\n\n```bash\nnpm install agent-browser\nagent-browser install\n```\n\nThen use via `package.json` scripts or by invoking `agent-browser` directly.\n\n### Homebrew (macOS)\n\n```bash\nbrew install agent-browser\nagent-browser install  # Download Chrome from Chrome for Testing (first time only)\n```\n\n### Cargo (Rust)\n\n```bash\ncargo install agent-browser\nagent-browser install  # Download Chrome from Chrome for Testing (first time only)\n```\n\n### From Source\n\nRequires Node.js 24+, pnpm 11+, and Rust.\n\n```bash\ngit clone https://github.com/vercel-labs/agent-browser\ncd agent-browser\npnpm install\npnpm build\npnpm build:native   # Requires Rust (https://rustup.rs)\npnpm link --global  # Makes agent-browser available globally\nagent-browser install\n```\n\n### Linux Dependencies\n\nOn Linux, install system dependencies:\n\n```bash\nagent-browser install --with-deps\n```\n\nThis exits nonzero if the package manager cannot install every required browser library.\n\n### Updating\n\nUpgrade to the latest version:\n\n```bash\nagent-browser upgrade\n```\n\nDetects your installation method (npm, Homebrew, or Cargo) and runs the appropriate update command automatically.\n\n### Requirements\n\n- **Chrome** - Run `agent-browser install` to download Chrome from [Chrome for Testing](https://developer.chrome.com/blog/chrome-for-testing/) (Google's official automation channel). Existing Chrome, Brave, Playwright, and Puppeteer installations are detected automatically. No Playwright or Node.js required for the daemon.\n- **Node.js 24+ and pnpm 11+** - Only needed when building from source.\n- **Rust** - Only needed when building from source (see From Source above).\n\n## Quick Start\n\n```bash\nagent-browser open example.com\nagent-browser snapshot                    # Get accessibility tree with refs\nagent-browser click @e2                   # Click by ref from snapshot\nagent-browser fill @e3 \"test@example.com\" # Fill by ref\nagent-browser get text @e1                # Get text by ref\nagent-browser screenshot page.png\nagent-browser close\n```\n\nClicks fail early when another element covers the target's click point, for example a consent banner or modal. Dismiss or interact with the reported covering element, then take a fresh snapshot before retrying the original ref.\n\nHeadless Chromium screenshots hide native scrollbars for consistent image output. Pass `--hide-scrollbars false` when launching to keep native scrollbars visible.\n\n### Traditional Selectors (also supported)\n\n```bash\nagent-browser click \"#submit\"\nagent-browser fill \"#email\" \"test@example.com\"\nagent-browser find role button click --name \"Submit\"\n```\n\n## Commands\n\n### Core Commands\n\n```bash\nagent-browser open                    # Launch browser (no navigation); stays on about:blank\nagent-browser open <url>              # Launch + navigate to URL (aliases: goto, navigate)\nagent-browser read [url]              # Fetch agent-readable text, or read rendered active-tab DOM\nagent-browser click <sel>             # Click element (--new-tab to open in new tab)\nagent-browser dblclick <sel>          # Double-click element\nagent-browser focus <sel>             # Focus element\nagent-browser type <sel> <text>       # Type into element\nagent-browser fill <sel> <text>       # Clear and fill\nagent-browser press <key>             # Press key (Enter, Tab, Control+a) (alias: key)\nagent-browser keyboard type <text>    # Type with real keystrokes (no selector, current focus)\nagent-browser keyboard inserttext <text>  # Insert text without key events (no selector)\nagent-browser keydown <key>           # Hold key down\nagent-browser keyup <key>             # Release key\nagent-browser hover <sel>             # Hover element\nagent-browser select <sel> <val>      # Select dropdown option\nagent-browser check <sel>             # Check checkbox\nagent-browser uncheck <sel>           # Uncheck checkbox\nagent-browser scroll <dir> [px]       # Scroll (up/down/left/right, --selector <sel>)\nagent-browser scrollintoview <sel>    # Scroll element into view (alias: scrollinto)\nagent-browser drag <src> <tgt>        # Drag and drop\nagent-browser upload <sel> <files>    # Upload files\nagent-browser screenshot [path]       # Take screenshot (--full for full page, saves to a temporary directory if no path)\nagent-browser screenshot --annotate   # Annotated screenshot with numbered element labels\nagent-browser screenshot --screenshot-dir ./shots    # Save to custom directory\nagent-browser screenshot --screenshot-format jpeg --screenshot-quality 80\nagent-browser pdf <path>              # Save as PDF\nagent-browser snapshot                # Accessibility tree with refs (best for AI)\nagent-browser eval <js>               # Run JavaScript (-b for base64, --stdin for piped input)\nagent-browser connect <port>          # Connect to browser via CDP\nagent-browser stream enable [--port <port>]  # Start runtime WebSocket streaming\nagent-browser webmcp list                     # List experimental page tools\nagent-browser webmcp invoke <tool> --params @input.json\nagent-browser stream status           # Show runtime streaming state and bound port\nagent-browser stream disable          # Stop runtime WebSocket streaming\nagent-browser close                   # Close browser (aliases: quit, exit)\nagent-browser close --all             # Close all active sessions\nagent-browser chat \"<instruction>\"    # AI chat: natural language browser control (single-shot)\nagent-browser chat                    # AI chat: interactive REPL mode\n```\n\n### WebMCP (experimental)\n\nWebMCP tools are ready by default in agent-browser-managed Chrome. Use `--no-webmcp` to disable the launch features. After a successful navigation, text output advertises when tools are available. JSON output includes `data.webmcp` with `experimental`, `available`, and `toolCount`.\n\n```bash\nagent-browser open https://example.com\nagent-browser webmcp list\nagent-browser webmcp invoke search --params '{\"query\":\"browser agents\"}'\nagent-browser webmcp invoke slow_tool --params @input.json --detach\nagent-browser webmcp result <invocation-id>\nagent-browser webmcp cancel <invocation-id>\n```\n\nUse `--frame <frame-id>` when duplicate tool names are registered in multiple frames. Page-provided descriptions, schemas, annotations, and results are untrusted. Page JavaScript registers `readOnlyHint` and `untrustedContentHint`; CDP exposes those claims as `readOnly` and `untrustedContent`. The page tool executor owns authorization, and the agent host must confirm consequential actions.\n\nThe optional MCP profile keeps these generic tools out of the default profile:\n\n```bash\nagent-browser mcp --tools core,webmcp\n```\n\nFor sites without WebMCP tools, load the generation and validation workflow with `agent-browser skills get webmcp-gen`.\n\n### Get Info\n\n```bash\nagent-browser get text <sel>          # Get text content\nagent-browser get html <sel>          # Get innerHTML\nagent-browser get value <sel>         # Get input value\nagent-browser get attr <sel> <attr>   # Get attribute\nagent-browser get title               # Get page title\nagent-browser get url                 # Get current URL\nagent-browser get cdp-url             # Get CDP WebSocket URL (for DevTools, debugging)\nagent-browser get count <sel>         # Count matching elements\nagent-browser get box <sel>           # Get bounding box\nagent-browser get styles <sel>        # Get computed styles\n```\n\n### Read Agent-Friendly Text\n\n```bash\nagent-browser read\nagent-browser read https://example.com/article\nagent-browser read https://example.com/article --filter overview\nagent-browser read https://example.com/article --outline\nagent-browser read https://docs.example.com --llms index --filter auth\nagent-browser read https://docs.example.com --llms full --filter auth\nagent-browser read example.com/article --require-md\nagent-browser read https://example.com/article --json\n```\n\n`read` fetches a URL without launching Chrome. Omit the URL to read the rendered DOM of the active tab in the current browser session, including browser auth state and client-side updates. Explicit URL reads send `Accept: text/markdown` by default, try the same URL with `.md` appended when the first response is not markdown, walk ancestor paths toward `/` to find the nearest `llms.txt` for a matching docs link, print markdown or plain text when available, and fall back to readable text extracted from HTML. `--llms` and `--require-md` with no URL use the active tab URL because they depend on HTTP resources. `read` does not read `llms-full.txt` unless you ask for it.\n\nOptions: `--raw` prints the response body without HTML extraction, `--require-md` fails unless the server returns `Content-Type: text/markdown`, `--outline` prints a compact heading outline for one page, `--llms index` prints a compact nearest-ancestor `llms.txt` link list, `--llms full` reads the nearest-ancestor `llms-full.txt`, `--filter <text>` narrows page sections, llms links/sections, or outline headings, and `--timeout <ms>` changes the request timeout. Global safeguards such as `--allowed-domains`, `--content-boundaries`, and `--max-output` also apply to read fetches and output.\n\n### Check State\n\n```bash\nagent-browser is visible <sel>        # Check if visible\nagent-browser is enabled <sel>        # Check if enabled\nagent-browser is checked <sel>        # Check if checked\n```\n\n### Find Elements (Semantic Locators)\n\n```bash\nagent-browser find role <role> <action> [value]       # By ARIA role\nagent-browser find text <text> <action> [value]       # By text content\nagent-browser find label <label> <action> [value]     # By label\nagent-browser find placeholder <ph> <action> [value]  # By placeholder\nagent-browser find alt <text> <action> [value]        # By alt text\nagent-browser find title <text> <action> [value]      # By title attr\nagent-browser find testid <id> <action> [value]       # By data-testid\nagent-browser find first <sel> <action> [value]       # First match\nagent-browser find last <sel> <action> [value]        # Last match\nagent-browser find nth <n> <sel> <action> [value]     # Nth match\n```\n\n**Actions:** `click`, `fill`, `check`, `hover`, `text`\n\n**Options:** `--name <name>` (filter role by accessible name), `--exact` (exact, case-sensitive match; for `role` it applies to the accessible name, whose default is a case-insensitive substring)\n\n**Examples:**\n\n```bash\nagent-browser find role button click --name \"Submit\"\nagent-browser find role heading text --name \"Skills\"     # implicit roles work: <h2>=heading, <ul>=list, top-level <header>=banner\nagent-browser find text \"Sign In\" click\nagent-browser find label \"Email\" fill \"test@test.com\"\nagent-browser find first \".item\" click\nagent-browser find nth 2 \"a\" text\n```\n\n### Wait\n\n```bash\nagent-browser wait <selector>         # Wait for element to be visible\nagent-browser wait <ms>               # Wait for time (milliseconds)\nagent-browser wait --text \"Welcome\"   # Wait for text to appear (substring match)\nagent-browser wait --url \"**/dash\"    # Wait for URL pattern\nagent-browser wait --load networkidle # Wait for load state\nagent-browser wait --fn \"window.ready === true\"  # Wait for JS condition\n\n# Wait for text/element to disappear\nagent-browser wait --fn \"!document.body.innerText.includes('Loading...')\"\nagent-browser wait \"#spinner\" --state hidden\n```\n\n**Load states:** `load`, `domcontentloaded`, `networkidle`\n\n### Batch Execution\n\nExecute multiple commands in a single invocation. Commands can be passed as quoted arguments or piped as JSON via stdin. This avoids per-command process startup overhead when running multi-step workflows.\n\n```bash\n# Argument mode: each quoted argument is a full command\nagent-browser batch \"open https://example.com\" \"snapshot -i\" \"screenshot\"\n\n# With --bail to stop on first error\nagent-browser batch --bail \"open https://example.com\" \"click @e1\" \"screenshot\"\n\n# Stdin mode: pipe commands as JSON\necho '[\n  [\"open\", \"https://example.com\"],\n  [\"snapshot\", \"-i\"],\n  [\"click\", \"@e1\"],\n  [\"screenshot\", \"result.png\"]\n]' | agent-browser batch --json\n```\n\n### Clipboard\n\n```bash\nagent-browser clipboard read                      # Read text from clipboard\nagent-browser clipboard write \"Hello, World!\"     # Write text to clipboard\nagent-browser clipboard copy                      # Copy current selection (Ctrl+C)\nagent-browser clipboard paste                     # Paste from clipboard (Ctrl+V)\n```\n\n### Mouse Control\n\n```bash\nagent-browser mouse move <x> <y>      # Move mouse\nagent-browser mouse down [button]     # Press button (left/right/middle)\nagent-browser mouse up [button]       # Release button\nagent-browser mouse wheel <dy> [dx]   # Scroll wheel\n```\n\n### Browser Settings\n\n```bash\nagent-browser set viewport <w> <h> [scale]  # Set viewport size (scale for retina, e.g. 2)\nagent-browser set device <name>       # Emulate device (\"iPhone 14\")\nagent-browser set geo <lat> <lng>     # Set geolocation\nagent-browser set offline [on|off]    # Toggle offline mode\nagent-browser set headers <json>      # Extra HTTP headers\nagent-browser set credentials <u> <p> # HTTP basic auth for current and future tabs\nagent-browser set media [dark|light]  # Emulate color scheme\n```\n\n`set credentials` applies HTTP Basic Authentication to the current tab and tabs opened later. `set offline off` and `set headers '{}'` restore the default setup for future tabs.\n\n### Cookies & Storage\n\n```bash\nagent-browser cookies                 # Get all cookies\nagent-browser cookies set <name> <val> # Set cookie\nagent-browser cookies set --curl <file> # Import cookies from a Copy-as-cURL dump,\n                                        # JSON array, or bare Cookie header (auto-detected)\nagent-browser cookies clear           # Clear cookies\n\nagent-browser storage local           # Get all localStorage\nagent-browser storage local <key>     # Get specific key\nagent-browser storage local set <k> <v>  # Set value\nagent-browser storage local clear     # Clear all\n\nagent-browser storage session         # Same for sessionStorage\n```\n\n### Network\n\n```bash\nagent-browser network route <url>              # Intercept requests\nagent-browser network route <url> --abort      # Block requests\nagent-browser network route <url> --body <json>  # Mock response\nagent-browser network route '*' --abort --resource-type script  # Block scripts only\nagent-browser network unroute [url]            # Remove routes\nagent-browser network requests                 # View tracked requests\nagent-browser network requests --filter api    # Filter requests\nagent-browser network requests --type xhr,fetch  # Filter by resource type\nagent-browser network requests --method POST   # Filter by HTTP method\nagent-browser network requests --status 2xx    # Filter by status (200, 2xx, 400-499)\nagent-browser network request <requestId>      # View full request/response detail\nagent-browser network har start                # Start HAR recording (embeds text response bodies)\nagent-browser network har start --content all  # Embed all response bodies (binary as base64)\nagent-browser network har start --content none # Metadata only, no bodies\nagent-browser network har stop [output.har]    # Stop and save HAR (temp path if omitted)\n```\n\n### Tabs & Windows\n\n```bash\nagent-browser tab                              # List tabs (shows `tabId` and optional label)\nagent-browser tab new [url]                    # New tab (optionally with URL)\nagent-browser tab new --label docs [url]       # New tab with a user-assigned label\nagent-browser tab <t<N>|label>                 # Switch to a tab by id or label\nagent-browser tab close [t<N>|label]           # Close a tab (defaults to active)\nagent-browser window new                       # New window\n```\n\nTab ids are stable strings of the form `t1`, `t2`, `t3`. They're never reused within a session, so scripts and agents can keep referring to the same tab even after other tabs are opened or closed. Positional integers like `tab 2` are **not** accepted; the `t` prefix disambiguates handles from indices and mirrors the `@e1` convention used for element refs.\n\nYou can also assign a memorable label (`docs`, `app`, `admin`) and use it interchangeably with the id. Labels are never auto-generated and never rewritten on navigation — they're yours to name and keep:\n\n```bash\nagent-browser tab new --label docs https://docs.example.com\nagent-browser tab docs               # switch to the docs tab\nagent-browser snapshot               # populate refs for docs\nagent-browser click @e3              # click uses docs's refs\nagent-browser tab close docs         # close by label\n```\n\nTabs opened through `tab new` or `click --new-tab` inherit the session's user agent, headers, HTTP credentials, init scripts, routes, and emulation overrides before their first document loads.\n\n`tab list --json` also reports each tab's CDP `targetId`, and target ids are accepted anywhere a tab ref is accepted (`tab <targetId>`, `tab close <targetId>`). Unlike `t<N>` ids, which are per-daemon counters, target ids stay stable across daemon restarts, so they're the right handle for scripts coordinating multiple sessions on one browser.\n\nSwitching to a tab discarded by Chrome's Memory Saver reactivates it, since a discarded tab has no renderer to drive. Reactivation reloads the discarded page and resets its unsaved state, and the switch result reports `\"revived\": true`. A tab whose page is paused by a JavaScript dialog is alive rather than discarded, so the switch leaves it untouched and reports `\"dialogBlocked\": true`; resolve the dialog with `dialog accept` or `dialog dismiss` before interacting. Closing the active tab onto a discarded successor revives it the same way and reports `\"activeTabRevived\": true`.\n\n### Frames\n\n```bash\nagent-browser frame <sel>             # Switch to iframe\nagent-browser frame main              # Back to main frame\n```\n\n### Dialogs\n\n```bash\nagent-browser dialog accept [text]    # Accept (with optional prompt text)\nagent-browser dialog dismiss          # Dismiss\nagent-browser dialog status           # Check if a dialog is currently open\n```\n\nBy default, `alert` and `beforeunload` dialogs are automatically accepted so they never block the agent. `confirm` and `prompt` dialogs still require explicit handling. Use `--no-auto-dialog` (or `AGENT_BROWSER_NO_AUTO_DIALOG=1`) to disable automatic handling.\n\nWhen a JavaScript dialog is pending, all command responses include a `warning` field with the dialog type and message.\n\n### Diff\n\n```bash\nagent-browser diff snapshot                              # Compare current vs last snapshot\nagent-browser diff snapshot --baseline before.txt        # Compare current vs saved snapshot file\nagent-browser diff snapshot --selector \"#main\" --compact # Scoped snapshot diff\nagent-browser diff screenshot --baseline before.png      # Visual pixel diff against baseline\nagent-browser diff screenshot --baseline b.png -o d.png  # Save diff image to custom path\nagent-browser diff screenshot --baseline b.png -t 0.2    # Adjust color threshold (0-1)\nagent-browser diff url https://v1.com https://v2.com     # Compare two URLs (snapshot diff)\nagent-browser diff url https://v1.com https://v2.com --screenshot  # Also visual diff\nagent-browser diff url https://v1.com https://v2.com --wait-until networkidle  # Custom wait strategy\nagent-browser diff url https://v1.com https://v2.com --selector \"#main\"  # Scope to element\n```\n\n### Debug\n\n```bash\nagent-browser trace start             # Start recording trace\nagent-browser trace stop [path]       # Stop and save trace\nagent-browser profiler start          # Start Chrome DevTools profiling\nagent-browser profiler stop [path]    # Stop and save profile (.json)\nagent-browser record start ./demo.webm           # Start video recording at 30 fps\nagent-browser record start ./demo.webm --fps 60  # 60 fps for motion-heavy takes (1-60 allowed)\nagent-browser record stop                        # Stop and save the video\nagent-browser record restart ./take2.webm        # Stop the current recording, start a new one\nagent-browser console                 # View console messages (log, error, warn, info)\nagent-browser console --json          # JSON output with raw CDP args for programmatic access\nagent-browser console --clear         # Clear console\nagent-browser errors                  # View page errors (uncaught JavaScript exceptions)\nagent-browser errors --clear          # Clear errors\nagent-browser highlight <sel>         # Highlight element\nagent-browser inspect                 # Open Chrome DevTools for the active page\nagent-browser state save <path>       # Save auth state\nagent-browser state load <path>       # Load auth state\nagent-browser state list              # List saved state files\nagent-browser state show <file>       # Show state summary\nagent-browser state rename <old> <new> # Rename state file\nagent-browser state clear [name]      # Clear states for session\nagent-browser state clear --all       # Clear all saved states\nagent-browser state clean --older-than <days>  # Delete old states\n```\n\n### Navigation\n\n```bash\nagent-browser back                    # Go back\nagent-browser forward                 # Go forward\nagent-browser reload                  # Reload page\nagent-browser pushstate <url>         # SPA client-side nav; auto-detects window.next.router.push,\n                                      # falls back to history.pushState + popstate\n```\n\n### Pre-navigation setup\n\nSome flows (SSR debug, auth cookies for protected origins, init scripts) need state set up *before* the first navigation. Use `open` with no URL to launch the browser, then stage cookies / routes / init scripts, then navigate. `batch` sends it all in one CLI call:\n\n```bash\nagent-browser batch \\\n  '[\"open\"]' \\\n  '[\"network\",\"route\",\"*\",\"--abort\",\"--resource-type\",\"script\"]' \\\n  '[\"cookies\",\"set\",\"--curl\",\"cookies.curl\",\"--domain\",\"localhost\"]' \\\n  '[\"navigate\",\"http://localhost:3000/target\"]'\n```\n\nWithout `batch` the same sequence is three commands that all reuse the same daemon (fast, but not one turn).\n\n### React / Web Vitals\n\nAgent-browser ships with first-class React introspection and universal Web Vitals metrics. The React commands need the React DevTools hook installed at launch; Web Vitals and pushstate are framework-agnostic.\n\n```bash\nagent-browser open --enable react-devtools <url>   # Launch with React hook installed\nagent-browser react tree                           # Full component tree\nagent-browser react inspect <fiberId>              # props, hooks, state, source\nagent-browser react renders start                  # Begin fiber render recording\nagent-browser react renders stop [--json]          # Stop and print profile (--json for raw data)\nagent-browser react suspense [--only-dynamic] [--json]  # Suspense boundaries + classifier\n                                                         # --only-dynamic hides the \"static\" list\nagent-browser vitals [url] [--json]                # LCP/CLS/TTFB/FCP/INP + hydration summary\n```\n\nEach `react ...` subcommand requires `--enable react-devtools` to have been passed at launch (the React DevTools `installHook.js` is embedded in the binary). Without it the commands error with `React DevTools hook not installed\n- relaunch with --enable react-devtools`.\n\nWorks on any React app — Next.js, Remix, Vite+React, CRA, TanStack Start, React Native Web, etc. `vitals` and `pushstate` are framework-agnostic. `vitals` prints a summary by default; pass `--json` for the full structured payload.\n\n### Accessibility audits\n\nRun an [axe-core](https://github.com/dequelabs/axe-core) accessibility audit against the current page or a URL. The axe-core engine is embedded in the binary, so it works offline and under strict CSP. It runs private partial audits across the page's frame tree and merges serialized results without page messaging, so page-provided `window.axe` values remain intact and iframe violations retain their frame selector paths. Accessibility audits require a CDP browser and are not available with Safari or iOS WebDriver sessions.\n\n```bash\nagent-browser a11y                                 # Audit the current page\nagent-browser a11y https://example.com             # Navigate, then audit\nagent-browser a11y --tags wcag2a,wcag2aa           # Only rules with these axe tags\nagent-browser a11y --selector \"#main\"              # Scope the audit to a subtree\nagent-browser a11y example.com --json              # Full structured results\n```\n\nThe default output lists each violation with its impact, rule id, fix guidance URL, and the CSS selectors of failing nodes:\n\n```\nurl: https://example.com/\naxe-core: 4.12.1  violations: 2  incomplete: 0  passes: 24\n\n[critical] image-alt: Images must have alternative text (3 nodes)\n  https://dequeuniversity.com/rules/axe/4.12/image-alt\n  - img.hero\n  - #logo > img\n  - footer img\n[serious] color-contrast: Elements must meet minimum color contrast ratio thresholds (1 node)\n  https://dequeuniversity.com/rules/axe/4.12/color-contrast\n  - .nav a.muted\n```\n\n`--json` returns the same data structured for automation (`counts`, `violations`, `incomplete`, each violation's `nodes` with `target`, `html`, and `failureSummary`). Each `target` preserves axe's selector path arrays, including nested arrays for shadow DOM boundaries. Rules that axe could not evaluate automatically are reported under `incomplete` for manual review.\n\n### Init scripts\n\n```bash\nagent-browser open --init-script <path>           # Register page init script before first navigation\n                                                  # (repeatable; also AGENT_BROWSER_INIT_SCRIPTS env)\nagent-browser addinitscript <js>                  # Register at runtime (returns identifier)\nagent-browser removeinitscript <identifier>       # Remove from every tab in the session\n```\n\nRuntime init-script identifiers are session-wide. `removeinitscript` removes the script from every open tab where it was registered and prevents it from being replayed into tabs opened later.\n\n### Setup\n\n```bash\nagent-browser install                 # Download Chrome from Chrome for Testing (Google's official automation channel)\nagent-browser install --with-deps     # Also install system deps (Linux)\nagent-browser upgrade                 # Upgrade agent-browser to the latest version\nagent-browser doctor                  # Diagnose the install and auto-clean stale daemon files\nagent-browser doctor --fix            # Also run destructive repairs (reinstall Chrome, purge old state, ...)\nagent-browser doctor --offline --quick  # Skip network probes and the live launch test\nagent-browser mcp                     # Start an MCP stdio server\n```\n\n`doctor` checks your environment, Chrome install, daemon state, config files, encryption key, providers, network reachability, and runs a live headless browser launch test. Stale socket/pid sidecar files are auto-cleaned. Output is also available as `--json` for agents.\n\n### Skills\n\n```bash\nagent-browser skills                  # List available skills\nagent-browser skills list             # Same as above\nagent-browser skills get <name>       # Output a skill's full content\nagent-browser skills get <name> --full  # Include references and templates\nagent-browser skills get protected-vercel-deployments  # Access protected Vercel deployments\nagent-browser skills get --all        # Output every skill\nagent-browser skills path [name]      # Print skill directory path\n```\n\nServes bundled skill content that always matches the installed CLI version. AI agents use this to get current instructions rather than relying on cached copies. Set `AGENT_BROWSER_SKILLS_DIR` to override the skills directory path.\n\n### MCP Server\n\n```bash\nagent-browser mcp\nagent-browser mcp --tools all\nagent-browser mcp --tools core,network,react\n```\n\nStarts a Model Context Protocol server over stdio. MCP clients launch this command as a subprocess and exchange newline-delimited JSON-RPC on stdin and stdout. The server defaults to MCP protocol 2025-11-25 and accepts older supported client protocol versions during initialization.\n\nThe default tools profile is `core`, which keeps MCP context small for everyday browser automation. Use `--tools all` for the full typed CLI parity surface, or combine profiles with commas, such as `--tools core,network,react`.\n\nProfiles:\n\n- `core` — Default. Navigation, snapshots, interaction, waits, reads, screenshots, JavaScript eval, close, tab basics, and profile discovery\n- `network` — Network routes, request inspection, HAR, headers, credentials, offline\n- `state` — Cookies, storage, auth, saved state, sessions, profiles, skills\n- `debug` — Console/errors, tracing, profiling, recording, a11y audit, clipboard, plugins, doctor, dashboard, install, upgrade, chat, diff, batch, confirm/deny\n- `tabs` — Back/forward/reload, tabs, windows, frames, dialogs\n- `react` — React tree/inspect/renders/suspense, vitals, pushstate\n- `mobile` — Viewport/device/geolocation/media, touch, swipe, mouse, keyboard\n- `all` — Every MCP tool, including the full typed CLI parity surface\n\nCommon tools include:\n\n- `agent_browser_tools_profiles`\n- `agent_browser_open`\n- `agent_browser_snapshot`\n- `agent_browser_click`\n- `agent_browser_fill`\n- `agent_browser_type`\n- `agent_browser_press`\n- `agent_browser_wait_for_selector`\n- `agent_browser_screenshot`\n- `agent_browser_get_url`\n- `agent_browser_eval`\n- `agent_browser_close`\n\nEach tool has typed fields such as `url`, `selector`, `text`, `key`, `session`, and `allowedDomains`, so MCP clients show meaningful approval prompts instead of raw command arrays. The common `allowedDomains` array maps to `--allowed-domains` and activates the same WebRTC containment and launch-mode restrictions. Each tool also accepts `extraArgs` for advanced CLI flags and exact CLI parity. Tool discovery is paginated and includes read-only/open-world annotations so modern MCP clients can load the large typed surface incrementally.\n\nExample MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"agent-browser\": {\n      \"command\": \"agent-browser\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\nFull parity MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"agent-browser\": {\n      \"command\": \"agent-browser\",\n      \"args\": [\"mcp\", \"--tools\", \"all\"]\n    }\n  }\n}\n```\n\nTool invocations use the same config files and environment variables as the CLI. Use `session` in the tool arguments, or set `AGENT_BROWSER_SESSION`, to isolate browser state.\n\n## Authentication\n\nagent-browser provides multiple ways to persist login sessions so you don't re-authenticate every run.\n\n### Quick summary\n\n| Approach | Best for | Flag / Env |\n|----------|----------|------------|\n| **Chrome profile reuse** | Reuse your existing Chrome login state (cookies, sessions) with zero setup | `--profile <name>` / `AGENT_BROWSER_PROFILE` |\n| **Persistent profile** | Full browser state (cookies, IndexedDB, service workers, cache) across restarts | `--profile <path>` / `AGENT_BROWSER_PROFILE` |\n| **Session persistence** | Auto-save/restore cookies + localStorage from a stable session key | `--session <id> --restore` / `AGENT_BROWSER_RESTORE` |\n| **Import from your browser** | Grab auth from a Chrome session you already logged into | `--auto-connect` + `state save` |\n| **State file** | Load a previously saved state JSON on launch | `--state <path>` / `AGENT_BROWSER_STATE` |\n| **Auth vault** | Store credentials locally (encrypted), login by name | `auth save` / `auth login` |\n\n### Import auth from your browser\n\nIf you are already logged in to a site in Chrome, you can grab that auth state and reuse it:\n\n```bash\n# 1. Launch Chrome with remote debugging enabled\n#    macOS:\n\"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\" --remote-debugging-port=9222\n#    Or use --auto-connect to discover an already-running Chrome\n\n# 2. Connect and save the authenticated state\nagent-browser --auto-connect state save ./my-auth.json\n\n# 3. Use the saved auth in future sessions\nagent-browser --state ./my-auth.json open https://app.example.com/dashboard\n\n# 4. Or use --restore for automatic persistence\nSESSION=\"$(agent-browser session id --scope worktree --prefix myapp)\"\nagent-browser --session \"$SESSION\" --restore --state ./my-auth.json open https://app.example.com/dashboard\n# From now on, --session \"$SESSION\" --restore auto-saves/restores this state\n```\n\n> **Security notes:**\n> - `--remote-debugging-port` exposes full browser control on localhost. Any local process can connect. Only use on trusted machines and close Chrome when done.\n> - State files contain session tokens in plaintext. Add them to `.gitignore` and delete when no longer needed. For encryption at rest, set `AGENT_BROWSER_ENCRYPTION_KEY` (see [State Encryption](#state-encryption)).\n\nFor full details on login flows, OAuth, 2FA, cookie-based auth, and the auth vault, see the [Authentication](docs/src/app/sessions/page.mdx) docs.\n\n## Sessions\n\nRun multiple isolated browser instances:\n\n```bash\n# Different sessions\nagent-browser --session agent1 open site-a.com\nagent-browser --session agent2 open site-b.com\n\n# Or via environment variable\nAGENT_BROWSER_SESSION=agent1 agent-browser click \"#btn\"\n\n# List active sessions\nagent-browser session list\n# Output:\n# Active sessions:\n# -> default\n#    agent1\n\n# Show current session\nagent-browser session\n\n# Generate a stable worktree-scoped session id\nagent-browser session id --scope worktree --prefix next-dev-loop\n\n# Inspect daemon, launch, and restore status\nagent-browser session info --json\n```\n\nEach session has its own:\n\n- Browser instance\n- Cookies and storage\n- Navigation history\n- Authentication state\n\n### Tab pinning\n\nWhen several sessions share one Chrome over `--cdp`, each session remembers which tab it is bound to (by CDP target id, persisted across daemon restarts). A restarted daemon reattaches to the session's own tab instead of adopting whatever tab happens to be active, which is usually another session's.\n\nBy default, if the bound tab is closed the session falls back to a neighboring tab (legacy behavior). Pass `--pin-tab` (or set `AGENT_BROWSER_PIN_TAB=1`) to make the binding strict:\n\n```bash\n# Two agents sharing one Chrome, each pinned to its own tab\nagent-browser --session agent1 --cdp 9222 --pin-tab open site-a.com\nagent-browser --session agent2 --cdp 9222 --pin-tab open site-b.com\n```\n\nWith `--pin-tab`:\n\n- Attaching with no binding opens a fresh tab instead of adopting an existing one\n- If the bound tab is closed, commands fail with a `tab_gone` error (exit code 1) instead of silently acting on another tab. JSON responses carry `\"code\": \"tab_gone\"` and recovery metadata in `data.targetId` plus optional `data.lastUrl`\n- `tab list`, `tab new`, and `tab <ref>` still work in that state, so an agent can recover by binding a new tab\n- Tabs opened by other sessions or the user never steal the pinned session's active tab\n\nThe flag is sticky per session: pass it once and later commands and daemon restarts keep the strict semantics. Pass `--no-pin-tab` to explicitly turn the pin off again.\n\n`data.lastUrl` is emitted only for sanitized HTTP(S) URLs and `about:blank`. HTTP(S) credentials, query strings, and fragments are removed, and opaque URLs such as `data:` are omitted. Batch output exposes the same object as `result`.\n\nWhen re-running a shared-tab script such as the repro from #1530, add `--pin-tab` to the first command for every session. Without it, `open` intentionally preserves the legacy behavior and navigates the shared active tab, so the original script still collides. The same rule applies when sessions attach with `--auto-connect` instead of `--cdp`.\n\n## Chrome Profile Reuse\n\nThe fastest way to use your existing login state: pass a Chrome profile name to `--profile`:\n\n```bash\n# List available Chrome profiles\nagent-browser profiles\n\n# Reuse your default Chrome profile's login state\nagent-browser --profile Default open https://gmail.com\n\n# Use a named profile (by display name or directory name)\nagent-browser --profile \"Work\" open https://app.example.com\n\n# Or via environment variable\nAGENT_BROWSER_PROFILE=Default agent-browser open https://gmail.com\n```\n\nThis copies your Chrome profile to a temp directory (read-only snapshot, no changes to your original profile), so the browser launches with your existing cookies and sessions.\n\n> **Note:** On Windows, close Chrome before using `--profile <name>` if Chrome is running, as some profile files may be locked.\n\n## Persistent Profiles\n\nFor a persistent custom profile directory that stores state across browser restarts, pass a path to `--profile`:\n\n```bash\n# Use a persistent profile directory\nagent-browser --profile ~/.myapp-profile open myapp.com\n\n# Login once, then reuse the authenticated session\nagent-browser --profile ~/.myapp-profile open myapp.com/dashboard\n\n# Or via environment variable\nAGENT_BROWSER_PROFILE=~/.myapp-profile agent-browser open myapp.com\n```\n\nThe profile directory stores:\n\n- Cookies and localStorage\n- IndexedDB data\n- Service workers\n- Browser cache\n- Login sessions\n\n**Tip**: Use different profile paths for different projects to keep their browser state isolated.\n\n## Session Persistence\n\nUse `--restore` with a stable `--session` to automatically save and restore cookies and localStorage across browser restarts:\n\n```bash\n# Generate a stable id for this worktree and auto-save/load state\nSESSION=\"$(agent-browser session id --scope worktree --prefix twitter)\"\nagent-browser --session \"$SESSION\" --restore open twitter.com\n\n# Login once, then state persists automatically\n# State files stored in ~/.agent-browser/sessions/\n\n# Optional: validate restored state before auto-saving again\nagent-browser --session \"$SESSION\" --restore --restore-check-text Dashboard open twitter.com\n```\n\nState is saved when the browser closes (explicit `close`, idle timeout, or daemon shutdown) and also periodically while the browser is open, so a browser window you close by hand still leaves a recent save behind. Periodic autosave waits for commands to settle, then saves at most once per `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` (default 30000; set to `0` to save only on close). Idle sessions keep saving on the same interval, so changes the page makes on its own (token refreshes, background requests) are captured too. It respects the `--restore-save` policy.\n\n### State Encryption\n\nEncrypt saved session data at rest with AES-256-GCM:\n\n```bash\n# Generate key: openssl rand -hex 32\nexport AGENT_BROWSER_ENCRYPTION_KEY=<64-char-hex-key>\n\n# State files are now encrypted automatically\nagent-browser --session secure --restore open example.com\n```\n\n| Variable                          | Description                                        |\n| --------------------------------- | -------------------------------------------------- |\n| `AGENT_BROWSER_RESTORE`           | Auto-save/load state persistence name              |\n| `AGENT_BROWSER_RESTORE_SAVE`      | Restore save policy: `auto`, `always`, or `never`  |\n| `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` | Min ms between periodic autosaves (default: 30000, 0 disables) |\n| `AGENT_BROWSER_NAMESPACE`         | Namespace for daemon sockets and restore state     |\n| `AGENT_BROWSER_SESSION_NAME`      | Legacy auto-save/load state persistence name       |\n| `AGENT_BROWSER_ENCRYPTION_KEY`    | 64-char hex key for AES-256-GCM encryption         |\n| `AGENT_BROWSER_STATE_EXPIRE_DAYS` | Auto-delete states older than N days (default: 30) |\n\n## Security\n\nagent-browser includes security features for safe AI agent deployments. All features are opt-in, and existing workflows are unaffected until you explicitly enable a feature:\n\n- **Authentication Vault**: Store credentials locally (always encrypted), reference by name. The LLM never sees passwords. `auth login` navigates with `load` and then waits for login form selectors to appear (SPA-friendly, timeout follows the default action timeout). A key is auto-generated at `~/.agent-browser/.encryption-key` if `AGENT_BROWSER_ENCRYPTION_KEY` is not set: `echo \"pass\" | agent-browser auth save github --url https://github.com/login --username user --password-stdin` then `agent-browser auth login github`\n- **Plugin System**: Extend agent-browser with external executable plugins. Plugins run out-of-process over the `agent-browser.plugin.v1` stdio JSON protocol and declare capabilities such as `credential.read`, `browser.provider`, `launch.mutate`, or `command.run`.\n- **Content Boundary Markers**: Wrap page output in delimiters so LLMs can distinguish tool output from untrusted content: `--content-boundaries`\n- **Domain Allowlist**: Restrict navigation to trusted domains (wildcards like `*.example.com` also match the bare domain): `--allowed-domains \"example.com,*.example.com\"`. Sub-resource requests (scripts, images, fetch), WebSocket/EventSource connections, and `sendBeacon` calls to non-allowed domains are blocked. WebRTC peer connections are disabled in supported Chromium sessions while the allowlist is active to prevent STUN, TURN, and DNS traffic from bypassing HTTP interception. Dedicated and shared workers are guarded with a bootstrap wrapper; if a page CSP forbids that wrapper, the worker fails closed rather than running without the allowlist guard. Pre-existing CDP sessions, auto-connect, Chrome profiles, direct-page provider plugins, agent-browser restore or state-file replay, raw Chrome args that select profiles, restore sessions, or open startup pages, iOS, and Safari reject this option because agent-browser cannot install equivalent containment before page scripts run. Include any CDN domains your target pages depend on (e.g., `*.cdn.example.com`).\n- **Action Policy**: Gate destructive actions with a static policy file: `--action-policy ./policy.json`\n- **Action Confirmation**: Require explicit approval for sensitive action categories: `--confirm-actions eval,download`\n- **Output Length Limits**: Prevent context flooding: `--max-output 50000`\n\n| Variable                            | Description                              |\n| ----------------------------------- | ---------------------------------------- |\n| `AGENT_BROWSER_CONTENT_BOUNDARIES`  | Wrap page output in boundary markers     |\n| `AGENT_BROWSER_MAX_OUTPUT`          | Max characters for page output           |\n| `AGENT_BROWSER_ALLOWED_DOMAINS`     | Comma-separated allowed domain patterns; requires a fresh controllable browser context without profile/session startup args, restore/state replay, or direct-page provider plugins |\n| `AGENT_BROWSER_ACTION_POLICY`       | Path to action policy JSON file          |\n| `AGENT_BROWSER_CONFIRM_ACTIONS`     | Action categories requiring confirmation |\n| `AGENT_BROWSER_CONFIRM_INTERACTIVE` | Enable interactive confirmation prompts  |\n| `AGENT_BROWSER_PLUGINS`             | JSON plugin registry override            |\n\nSee [Security documentation](https://agent-browser.dev/security) for details.\n\n### Plugin System\n\nPlugins let third-party tools integrate without becoming built-in agent-browser dependencies. Add a plugin from npm or GitHub:\n\n```bash\nagent-browser plugin add agent-browser-plugin-captcha\nagent-browser plugin add @company/agent-browser-plugin-vault --name vault\nagent-browser plugin add org/agent-browser-plugin-cloud-browser\n```\n\nReferences are resolved by shape: `name` uses npm, `@scope/name` uses npm, and `owner/repo` uses GitHub. `plugin add` writes `./agent-browser.json` by default; use `--global` for `~/.agent-browser/config.json`.\n\nPlugin packages should support `plugin.manifest` so `plugin add` can discover their name and capabilities automatically. If a plugin does not support manifests, pass `--capability <name>` during add.\n\nPlugins can also be configured manually in `agent-browser.json`:\n\n```json\n{\n  \"plugins\": [\n    {\n      \"name\": \"vault\",\n      \"command\": \"agent-browser-plugin-vault\",\n      \"capabilities\": [\"credential.read\"]\n    },\n    {\n      \"name\": \"cloud-browser\",\n      \"command\": \"agent-browser-plugin-cloud-browser\",\n      \"capabilities\": [\"browser.provider\"]\n    },\n    {\n      \"name\": \"stealth\",\n      \"command\": \"agent-browser-plugin-stealth\",\n      \"capabilities\": [\"launch.mutate\"]\n    },\n    {\n      \"name\": \"captcha\",\n      \"command\": \"agent-browser-plugin-captcha\",\n      \"capabilities\": [\"command.run\", \"captcha.solve\"]\n    }\n  ]\n}\n```\n\nInspect configured plugins:\n\n```bash\nagent-browser plugin list\nagent-browser plugin show vault\n```\n\nUse a credential provider plugin for one login:\n\n```bash\nagent-browser auth login my-app --credential-provider vault --item \"My App\"\nagent-browser auth login my-app --credential-provider vault --item \"My App\" --url https://app.example.com/login --username-selector \"#email\" --password-selector \"#password\" --submit-selector \"button[type=submit]\"\n```\n\nUse a browser provider plugin:\n\n```bash\nagent-browser --provider cloud-browser open https://example.com\n```\n\nUse a launch mutator plugin for stealth or local launch customization. The plugin can append Chrome args, extensions, and init scripts before the browser starts:\n\n```bash\nagent-browser open https://example.com\n```\n\nUse a generic plugin command for domain-specific tools such as CAPTCHA solvers:\n\n```bash\nagent-browser plugin run captcha captcha.solve --payload '{\"siteKey\":\"...\",\"url\":\"https://example.com\"}'\n```\n\nThe protocol request always includes `protocol`, `type`, `capability`, and `request`. A credential plugin receives `credential.resolve`, a browser provider receives `browser.launch`, a launch mutator receives `launch.mutate`, and generic commands receive the supplied request type. `plugin run` is for `command.run` and custom capabilities; core capabilities and protocol request types use their dedicated command paths. agent-browser keeps browser automation, redaction-sensitive output, and policy enforcement in core.\n\nGate plugin access by capability action:\n\n```bash\nagent-browser --confirm-actions plugin:vault:credential.read auth login my-app --credential-provider vault --item \"My App\"\nagent-browser --confirm-actions plugin:cloud-browser:browser.provider --provider cloud-browser open https://example.com\nagent-browser --confirm-actions plugin:stealth:launch.mutate open https://example.com\n```\n\nDo not put vault tokens or passwords in plugin command args. Use the vault vendor's own login/session mechanism or environment outside agent-browser config.\n\n## Snapshot Options\n\nThe `snapshot` command supports filtering to reduce output size:\n\n```bash\nagent-browser snapshot                    # Full accessibility tree\nagent-browser snapshot -i                 # Interactive elements only (buttons, inputs, links)\nagent-browser snapshot -i --urls          # Interactive elements with link URLs\nagent-browser snapshot -c                 # Compact (remove empty structural elements)\nagent-browser snapshot -d 3               # Limit depth to 3 levels\nagent-browser snapshot -s \"#main\"         # Scope to CSS selector\nagent-browser snapshot -i -c -d 5         # Combine options\n```\n\n| Option                 | Description                                                             |\n| ---------------------- | ----------------------------------------------------------------------- |\n| `-i, --interactive`    | Only show interactive elements (buttons, links, inputs)                 |\n| `-u, --urls`           | Include href URLs for link elements                                     |\n| `-c, --compact`        | Remove empty structural elements                                        |\n| `-d, --depth <n>`      | Limit tree depth                                                        |\n| `-s, --selector <sel>` | Scope to CSS selector                                                   |\n\n## Annotated Screenshots\n\nThe `--annotate` flag overlays numbered labels on interactive elements in the screenshot. Each label `[N]` corresponds to ref `@eN`, so the same refs work for both visual and text-based workflows.\n\nAnnotated screenshots are supported on the CDP-backed browser path (Chrome/Lightpanda). The Safari/WebDriver backend does not yet support `--annotate`.\n\n```bash\nagent-browser screenshot --annotate\n# -> Screenshot saved to /tmp/screenshot-2026-02-17T12-00-00-abc123.png\n#    [1] @e1 button \"Submit\"\n#    [2] @e2 link \"Home\"\n#    [3] @e3 textbox \"Email\"\n```\n\nAfter an annotated screenshot, refs are cached so you can immediately interact with elements:\n\n```bash\nagent-browser screenshot --annotate ./page.png\nagent-browser click @e2     # Click the \"Home\" link labeled [2]\n```\n\nThis is useful for multimodal AI models that can reason about visual layout, unlabeled icon buttons, canvas elements, or visual state that the text accessibility tree cannot capture.\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `--session <name>` | Use isolated session (or `AGENT_BROWSER_SESSION` env) |\n| `--restore [name]` | Auto-save/restore session state. Bare `--restore` uses `--session` as the key |\n| `--restore-save <policy>` | Restore save policy: `auto`, `always`, or `never` |\n| `--restore-check-url <glob>` | Validate restored state against a URL pattern |\n| `--restore-check-text <text>` | Validate restored state against page text |\n| `--restore-check-fn <js>` | Validate restored state against a truthy JavaScript expression |\n| `--namespace <name>` | Isolate daemon sockets and restore-state directories |\n| `--session-name <name>` | Legacy alias for restore persistence key |\n| `--profile <name\\|path>` | Chrome profile name or persistent directory path (or `AGENT_BROWSER_PROFILE` env) |\n| `--state <path>` | Load storage state from JSON file (or `AGENT_BROWSER_STATE` env) |\n| `--headers <json>` | Set HTTP headers scoped to the URL's origin |\n| `--executable-path <path>` | Custom browser executable (or `AGENT_BROWSER_EXECUTABLE_PATH` env) |\n| `--extension <path>` | Load browser extension (repeatable; or `AGENT_BROWSER_EXTENSIONS` env) |\n| `--init-script <path>` | Register a page init script before the first navigation (repeatable; or `AGENT_BROWSER_INIT_SCRIPTS` env) |\n| `--enable <feature>` | Built-in init scripts: `react-devtools` (repeatable or comma-list; or `AGENT_BROWSER_ENABLE` env) |\n| `--args <args>` | Browser launch args, comma or newline separated (or `AGENT_BROWSER_ARGS` env) |\n| `--user-agent <ua>` | Custom User-Agent string (or `AGENT_BROWSER_USER_AGENT` env) |\n| `--proxy <url>` | Proxy server URL with optional auth (or `AGENT_BROWSER_PROXY` env) |\n| `--proxy-bypass <hosts>` | Hosts to bypass proxy (or `AGENT_BROWSER_PROXY_BYPASS` env) |\n| `--ignore-https-errors` | Ignore HTTPS certificate errors (useful for self-signed certs) |\n| `--ca-cert <path>` | Trust a CA certificate or PEM bundle for locally launched Chromium on Linux; later commands in the same running session retain it when omitted (or `AGENT_BROWSER_CA_CERT` env) |\n| `--no-ca-cert` | Clear CA trust retained by the running browser session (or `AGENT_BROWSER_CLEAR_CA_CERT`) |\n| `--allow-file-access` | Allow file:// URLs to access local files (Chromium only) |\n| `--hide-scrollbars <bool>` | Hide native scrollbars in headless Chromium screenshots, enabled by default (or `AGENT_BROWSER_HIDE_SCROLLBARS` env) |\n| `-p, --provider <name>` | Browser provider, including configured `browser.provider` plugins (or `AGENT_BROWSER_PROVIDER` env) |\n| `--device <name>` | iOS device name, e.g. \"iPhone 15 Pro\" (or `AGENT_BROWSER_IOS_DEVICE` env) |\n| `--json` | JSON output (for agents) |\n| `--annotate` | Annotated screenshot with numbered element labels (or `AGENT_BROWSER_ANNOTATE` env) |\n| `--screenshot-dir <path>` | Default screenshot output directory (or `AGENT_BROWSER_SCREENSHOT_DIR` env) |\n| `--screenshot-quality <n>` | JPEG quality 0-100 (or `AGENT_BROWSER_SCREENSHOT_QUALITY` env) |\n| `--screenshot-format <fmt>` | Screenshot format: `png`, `jpeg` (or `AGENT_BROWSER_SCREENSHOT_FORMAT` env) |\n| `--headed` | Show browser window (not headless) (or `AGENT_BROWSER_HEADED` env) |\n| `--webgpu` | Enable WebGPU; SwiftShader software Vulkan on Linux, no GPU required (or `AGENT_BROWSER_WEBGPU` env) |\n| `--no-webmcp` | Disable experimental WebMCP support, which is enabled by default for locally launched Chrome (or `AGENT_BROWSER_NO_WEBMCP` env) |\n| `--cdp <port\\|url>` | Connect via Chrome DevTools Protocol (port or WebSocket URL) |\n| `--auto-connect` | Auto-discover and connect to running Chrome (or `AGENT_BROWSER_AUTO_CONNECT` env) |\n| `--pin-tab` | Pin the session to its bound tab; fail with `tab_gone` instead of falling back to another tab (or `AGENT_BROWSER_PIN_TAB` env) |\n| `--no-pin-tab` | Disable a sticky pin previously enabled with `--pin-tab` |\n| `--color-scheme <scheme>` | Color scheme: `dark`, `light`, `no-preference` (or `AGENT_BROWSER_COLOR_SCHEME` env) |\n| `--download-path <path>` | Default download directory (or `AGENT_BROWSER_DOWNLOAD_PATH` env) |\n| `--content-boundaries` | Wrap page output in boundary markers for LLM safety (or `AGENT_BROWSER_CONTENT_BOUNDARIES` env) |\n| `--max-output <chars>` | Truncate page output to N characters (or `AGENT_BROWSER_MAX_OUTPUT` env) |\n| `--allowed-domains <list>` | Comma-separated allowed domain patterns; also disables WebRTC peer connections in supported Chromium sessions and rejects CDP, auto-connect, Chrome profiles, restore/state replay, direct-page provider plugins, unsafe startup `--args`, iOS, and Safari (or `AGENT_BROWSER_ALLOWED_DOMAINS` env) |\n| `--action-policy <path>` | Path to action policy JSON file (or `AGENT_BROWSER_ACTION_POLICY` env) |\n| `--confirm-actions <list>` | Action categories requiring confirmation (or `AGENT_BROWSER_CONFIRM_ACTIONS` env) |\n| `--confirm-interactive` | Interactive confirmation prompts; auto-denies if stdin is not a TTY (or `AGENT_BROWSER_CONFIRM_INTERACTIVE` env) |\n| `--engine <name>` | Browser engine: `chrome` (default), `lightpanda` (or `AGENT_BROWSER_ENGINE` env) |\n| `--idle-timeout <time>` | Shut down the daemon after inactivity (`10s`, `3m`, `1h`, or raw ms). Defaults to `1h`; use `0` to disable (or `AGENT_BROWSER_IDLE_TIMEOUT_MS` env) |\n| `--no-auto-dialog` | Disable automatic dismissal of `alert`/`beforeunload` dialogs (or `AGENT_BROWSER_NO_AUTO_DIALOG` env) |\n| `--model <name>` | AI model for chat command (or `AI_GATEWAY_MODEL` env) |\n| `-v`, `--verbose` | Show tool commands and their raw output (chat) |\n| `-q`, `--quiet` | Show only AI text responses, hide tool calls (chat) |\n| `--config <path>` | Use a custom config file (or `AGENT_BROWSER_CONFIG` env) |\n| `--debug` | Debug output |\n\n## Observability Dashboard\n\nMonitor agent-browser sessions in real time with a local web dashboard showing a live viewport and command activity feed.\n\n```bash\n# Start the dashboard server (runs in background on port 4848)\nagent-browser dashboard start\nagent-browser dashboard start --port 8080   # Custom port\n\n# All sessions are automatically visible in the dashboard\nagent-browser open example.com\n\n# Stop the dashboard\nagent-browser dashboard stop\n```\n\n| Option | Description |\n|--------|-------------|\n| `--port <n>` | Dashboard port from 1 to 65535. The default is 4848. |\n| `--allowed-origins <origins>` | Comma-separated exact HTTPS origins allowed to access a reverse-proxied dashboard. Every entry must be valid. Without this option, only loopback origins are accepted. |\n\nThe dashboard runs as a standalone background process on port 4848, independent of browser sessions. It stays available even when no sessions are running. Local dashboard origins (`localhost`, `127.0.0.1`, and `[::1]`) work without configuration. If you expose it through a reverse proxy or forwarded URL, explicitly allow the browser origin so the server can reject cross-origin requests and DNS-rebinding attacks:\n\n```bash\nagent-browser dashboard start --allowed-origins https://dashboard.example.com\n# Or: AGENT_BROWSER_DASHBOARD_ALLOWED_ORIGINS=https://dashboard.example.com agent-browser dashboard start\n```\n\nThe command prints private access URLs only for the allowed external origins. Open the matching URL once to establish the browser session; it includes an unguessable access token in its fragment. The browser stores it in a Secure, host-bound, same-site cookie for dashboard API and stream requests. Keep these URLs private and configure your reverse proxy to redact cookies from logs. Loopback URLs do not require or receive this token, so open `http://localhost:<port>` directly for local access. The browser stays on the dashboard origin; session-specific tabs, status, and stream traffic are proxied internally, so session ports do not need to be exposed.\n\nRepeated starts with the same settings reuse the running dashboard. To change the port or allowed origins, run `agent-browser dashboard stop` before starting it with the new settings.\n\nDashboard options are validated strictly. Unknown options, invalid ports, missing values, and malformed allowed origins fail without starting the server.\n\nThe dashboard displays:\n- **Live viewport**: real-time JPEG frames from the browser\n- **Activity feed**: chronological command/result stream with timing and expandable details\n- **Console output**: browser console messages (log, warn, error)\n- **Session creation**: create new sessions from the UI with local engines (Chrome, Lightpanda) or cloud providers (AgentCore, Browserbase, Browserless, Browser Use, Kernel)\n- **AI Chat**: chat with an AI assistant directly in the dashboard (requires Vercel AI Gateway configuration)\n\n### AI Chat\n\nThe dashboard includes an optional AI chat panel powered by the Vercel AI Gateway. The same functionality is available directly from the CLI via the `chat` command. Set these environment variables to enable AI chat:\n\n```bash\nexport AI_GATEWAY_API_KEY=gw_your_key_here\nexport AI_GATEWAY_MODEL=anthropic/claude-sonnet-4.6           # optional, this is the default\nexport AI_GATEWAY_URL=https://ai-gateway.vercel.sh           # optional, this is the default\n```\n\n**CLI usage:**\n\n```bash\nagent-browser chat \"open google.com and search for cats\"     # Single-shot\nagent-browser chat                                           # Interactive REPL\nagent-browser -q chat \"summarize this page\"                  # Quiet mode (text only)\nagent-browser -v chat \"fill in the login form\"               # Verbose (show command output)\nagent-browser --model openai/gpt-4o chat \"take a screenshot\" # Override model\n```\n\nThe `chat` command translates natural language instructions into agent-browser commands, executes them, and streams the AI response. In interactive mode, type `quit` to exit. Use `--json` for structured output suitable for agent consumption.\n\n**Dashboard usage:**\n\nThe Chat tab is always visible in the dashboard. When `AI_GATEWAY_API_KEY` is set, the Rust server proxies requests to the gateway and streams responses back using the Vercel AI SDK's UI Message Stream protocol. Without the key, sending a message shows an error inline.\n\n## Configuration\n\nCreate an `agent-browser.json` file to set persistent defaults instead of repeating flags on every command.\n\n**Locations (lowest to highest priority):**\n\n1. `~/.agent-browser/config.json`: user-level defaults\n2. `./agent-browser.json`: project-level overrides (in working directory)\n3. `AGENT_BROWSER_*` environment variables override config file values\n4. CLI flags override everything\n\n**Example `agent-browser.json`:**\n\n```json\n{\n  \"headed\": true,\n  \"proxy\": \"http://localhost:8080\",\n  \"profile\": \"./browser-data\",\n  \"userAgent\": \"my-agent/1.0\",\n  \"hideScrollbars\": false,\n  \"ignoreHttpsErrors\": true,\n  \"plugins\": [\n    {\n      \"name\": \"vault\",\n      \"command\": \"agent-browser-plugin-vault\",\n      \"capabilities\": [\"credential.read\"]\n    }\n  ]\n}\n``",
  "bytes": 60000,
  "sha": "1d659e96fea2392aa0db2ce911eab2a25f75edc8b9675a961798035a6c38e259",
  "repo_slug": "vercel-labs/agent-browser",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/skl_vercel_labs_agent_browser_agent_browser_aeab925a/readme"
}