* add security hardening features
- Add authentication vault (`auth save/login/list/show/delete`) so credentials are stored locally and never exposed to the LLM (fixes Snyk W007)
- Add `--content-boundaries` flag to wrap page-sourced output in structural markers, helping LLMs distinguish tool output from untrusted page content (fixes Snyk W011)
- Add `--allowed-domains` flag to restrict browser navigation to trusted domains
- Add `--action-policy` for static allow/deny gating of action categories, with opt-in `--confirm-actions`/`--confirm-interactive` for orchestrator or human-in-the-loop confirmation
- Add `--max-output` flag to truncate large page outputs, preventing context flooding
- New docs page at /security, updated README, SKILL.md, CLI help text, and templates
* fixes
* fixes
* fixes
* fixes
* fixes
* fixes
* fixes
* docs
* feat: add --download-path option
Adds a `--download-path` flag (and `AGENT_BROWSER_DOWNLOAD_PATH` env / `downloadPath` config key) to set a default download directory for browser downloads.
Without this, Playwright stores downloads in a temp directory that is deleted when the browser closes. The new option passes through to Playwright's `downloadsPath` on `launch()` and `launchPersistentContext()`.
Fixes#507
* improvements
* fixes
* fixes
Adds `keyboard type` and `keyboard insertText` subcommands that
operate on the currently focused element without requiring a selector.
Essential for contenteditable editors (Lexical, ProseMirror, CodeMirror,
Monaco) where `type <selector>` doesn't trigger the editor's internal
event pipeline (beforeinput/DOM mutation).
- `keyboard type <text>` — page.keyboard.type() with real keystrokes
- `keyboard insertText <text>` — page.keyboard.insertText()
Note: `keyboard press` intentionally omitted — the existing top-level
`press` command already operates on current focus.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes#519. Playwright defaults `colorScheme` to `light` on all new contexts, overriding the browser/OS dark mode setting. This is especially disruptive in CDP mode, where every reconnection resets the scheme. The `set media dark` command also didn't persist its choice to new tabs or pages.
- Add `--color-scheme <dark|light|no-preference>` flag, config key (`colorScheme`), and env var (`AGENT_BROWSER_COLOR_SCHEME`)
- Store the preference in `BrowserManager` and automatically apply it to all new contexts (via Playwright's context option) and all new pages (via `page.emulateMedia` in `setupPageTracking`)
- `set media dark/light` now also persists its choice for subsequent pages and tabs
* feat: Enable capture of profiling data
Adding a new set of commands:
```
agent-browser profiler start
agent-browser profiler stop trace.json
```
With this, agents can start a profiling trace, perform a set of actions, and then extract the profiling data for analysis.
**Note:** I was originally going to call it `agent-browser profile` but I realized that might cause confusion with the `--profile` flag
CDP supports a couple commands for starting/stopping a trace.
When a trace is running, it emits events that need to be picked up.
We store these locally in the daemon until the trace is completed.
When the final event is received, we dump all of them into an output file.
That file can be loaded directly into chrome devtools or another analysis tool to visualize what happened during the agentic run.
Added some basic rust tests for parsing the commands (since they have some optional / required args)
TS daemon adds ~6 tests to make sure the profiling lifecycle (including saving the output file) works as intended
* add docs
* fixes
* fixes
---------
Co-authored-by: Chris Tate <chris@ctate.dev>
Fixes#491
When `--start-maximized` or `--window-size` is passed as a browser arg, Playwright's default viewport (1280x720) overrides the browser's own window sizing, making those flags have no effect on the page content.
This change auto-detects those args and sets `viewport: null` so Playwright defers to the browser's window size. Explicit viewport values still take priority.
Also allows `viewport: null` in the launch protocol for agents that want to disable viewport emulation directly.
## Summary
- Fix `allowFileAccess` being silently stripped from launch commands by adding it to the Zod schema in `protocol.ts` (the `--allow-file-access` CLI flag was not reaching the browser)
- Fix `trace stop` requiring a path argument despite help text documenting it as optional -- now works with or without a path
- Fix `addscript`/`addstyle` silently succeeding when neither `content` nor `url` is provided -- now returns a validation error
- Replace hardcoded ANSI escape code with `color::error_indicator()` in `main.rs` to respect `NO_COLOR`
- Fix double-parse pattern and add descriptive expect messages in `commands.rs`
- Fix incomplete string escaping in `snapshot.ts` `buildSelector` (use `JSON.stringify` instead of manual quote escaping)
- Simplify redundant ternary in `snapshot.ts` cursor-interactive role assignment
- Sync docs changelog with CHANGELOG.md (v0.8.1 through v0.10.0)
Rebased and fixed implementation of PR #184 features on current main:
Session persistence:
- --session-name flag and AGENT_BROWSER_SESSION_NAME env var auto-save/restore
cookies and localStorage across browser restarts
- State files stored in ~/.agent-browser/sessions/ with owner-only permissions
- AES-256-GCM encryption via AGENT_BROWSER_ENCRYPTION_KEY env var
- Auto-expiration of old state files (AGENT_BROWSER_STATE_EXPIRE_DAYS, default 30)
State management commands:
- state list: list saved state files with metadata
- state show <file>: display state summary (cookies, origins, domains)
- state rename <old> <new>: rename state files
- state clear [name] [--all]: clear saved states
- state clean --older-than <days>: delete expired states
New --new-tab flag for click command:
- Opens link href in a new tab instead of navigating the current tab
Security hardening:
- Session name validation prevents path traversal (CLI + daemon)
- safeHeaderMerge prevents prototype pollution in header merging
- WebSocket stream server binds to 127.0.0.1 only
- State files written with 0o600 permissions
Fixes applied over the original PR:
- Use color.rs module instead of hardcoded ANSI escape codes
- Align CLI output field names with daemon response format
- Add CLI-level --session-name validation (not just daemon-side)
- Avoid adding "DOM" to tsconfig.json lib (use proper typing in evaluate)
- Keep version at 0.9.3 (matches current main)
- Centralize session name validation in daemon.ts helper
- Update all documentation (README, SKILL.md, docs site, --help output)
Co-authored-by: Chris Tate <chris@ctate.dev>
Summary
- The `--exact` flag on `find role`, `find label`, and `find placeholder` was accepted by the CLI but silently dropped by the server. The Zod validation schema, TypeScript types, and action handlers all lacked the `exact` field, so it was stripped before reaching Playwright's `getByRole`, `getByLabel`, and `getByPlaceholder` calls.
- Added `exact` to the schema, types, and handler for all three locators so the flag is forwarded to Playwright as intended.
- Added tests confirming `exact: true` survives protocol parsing for `getbyrole`, `getbylabel`, and `getbyplaceholder`.
Fixes#402
* feat: add --allow-file-access flag for file:// URL support
Adds the ability to open and interact with local files using file:// URLs.
This enables use cases like viewing local PDFs, testing local HTML files,
and allowing JavaScript to access other local files via XHR.
The flag adds Chromium's --allow-file-access-from-files and --allow-file-access
launch arguments. Only supported in Chromium browsers.
Fixes#345
* fix: add cli_allow_file_access tracking to prevent spurious warning
When --allow-file-access is set via AGENT_BROWSER_ALLOW_FILE_ACCESS env var
(not CLI), don't warn about the flag being ignored when daemon is already running.
* feat: add support for ignoring HTTPS certificate errors
* fix: update warning message for already running daemon to include ignore HTTPS errors option
* docs: add documentation for --ignore-https-errors option in README and SKILL.md
* feat: initialize ignore_https_errors flag in command context
* fix: change launch_cmd to mutable for cdp value handling
* Add --profile flag for persistent browser profiles
Adds support for persistent browser profiles that preserve cookies,
localStorage, and login sessions across browser restarts.
Changes:
- Add --profile <path> CLI flag (flags.rs)
- Add AGENT_BROWSER_PROFILE environment variable support
- Add profile field to LaunchCommand type (types.ts)
- Use launchPersistentContext when profile is specified (browser.ts)
- Update help text and README with documentation
Usage:
agent-browser --profile ~/.myapp-profile open myapp.com
This enables AI agents to maintain authenticated sessions across
browser restarts without re-authenticating each time.
* Expand tilde in profile path to home directory
* fix: add missing profile field to test Flags struct
---------
Co-authored-by: Chris Tate <chris@ctate.dev>
Previously, the --cdp flag only accepted a port number and connected via
http://localhost:{port}. This made it impossible to connect to remote
browser services like Kernel, Browserless, etc. that provide WebSocket URLs.
The --cdp flag now accepts either:
- A port number (e.g., 9222) for local connections
- A full WebSocket URL (e.g., wss://...) for remote browser services
Changes:
- Added cdpUrl field to LaunchCommand type
- Updated protocol validation to accept URL format with scheme validation
- Modified connectViaCDP to detect and handle both formats
- Handle numeric strings for JSON serialization edge cases
- Updated CLI to send cdpUrl or cdpPort based on input format
- Updated README with examples for remote connections
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add Browser Use cloud browser
integration
* feat: enhance Browser Use integration with provider flag support
- Updated README to reflect new usage instructions for enabling Browser Use with the `-p` flag.
- Modified CLI to parse and handle the `-p` flag for specifying the provider.
- Implemented logic in the main application to launch with the specified cloud provider.
- Adjusted BrowserManager to connect to Browser Use based on the provider flag or environment variable.
- Updated types and protocol schemas to include provider information.
* feat: add validation for mutually exclusive CLI options
- Implemented checks to prevent the use of both --cdp and --provider flags simultaneously.
- Added validation to ensure --extension cannot be used with the --provider flag.
- Enhanced error handling to provide clear feedback in both JSON and console output formats.
* fix: support URL parameter in tab new command
The CLI was correctly sending the URL parameter when running
`agent-browser tab new <url>`, but the TypeScript daemon was
ignoring it because:
1. The schema didn't include the url field (stripped during validation)
2. The TabNewCommand type didn't have a url property
3. The handler didn't pass the URL to browser.newTab()
4. browser.newTab() didn't accept or use a URL parameter
This fix adds URL support throughout the chain so that
`agent-browser tab new https://example.com` now correctly
opens a new tab and navigates to the specified URL.
Fixes#62
* fix: omit url field when not provided in tab new command
Previously, the CLI always sent "url": null when no URL was provided,
which caused Zod validation to fail with "Expected string, received null".
Now the url field is only included when a URL is actually provided.
Fixes issue reported by @ctate in PR review.
* refactor: move navigation logic from BrowserManager to handleTabNew
Address review feedback:
- Add .min(1) to URL validation for consistency with navigateSchema
- Keep BrowserManager.newTab() simple (single responsibility)
- Handle navigation in handleTabNew following same pattern as handleNavigate
* feat: add video recording with Playwright native video
Adds `record start/stop` commands using Playwright's built-in video
recording. No external dependencies required (no FFmpeg).
Usage:
agent-browser record start ./demo.webm https://example.com
agent-browser click @e1
agent-browser record stop
Recording creates a fresh browser context with video enabled. For smooth
demos, explore the page first to plan actions, then start recording.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: auto-capture URL and transfer state for recording
When starting a recording without a URL:
- Automatically captures current page URL
- Preserves cookies and localStorage from current session
This enables a seamless workflow:
agent-browser open https://app.example.com
agent-browser snapshot -i # explore, plan
agent-browser record start ./demo.webm # picks up URL + auth state
agent-browser click @e3
agent-browser record stop
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: error on non-webm recording path instead of silent coercion
Previously, specifying a non-.webm path like ./demo.mp4 would silently
change it to ./demo.webm. Now it throws a clear error telling the user
that Playwright native recording only supports WebM format.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: clean up recording temp directory after stopRecording
Previously the temp directory was created but never deleted, relying on
OS cleanup. Now we explicitly remove it after saving the video, in both
success and error paths.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: add record restart command
Adds `record restart` command that stops the current recording (if any)
and starts a new one. Also improves the error message when trying to
start recording while already recording.
Changes:
- Add restartRecording method to BrowserManager
- Add recording_restart action to protocol, types, and actions
- Add CLI parsing for `record restart <path> [url]`
- Update help text and skill documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add CLI tests for record restart command
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Chris Tate <chris@ctate.dev>
* feat: add --proxy flag for browser proxy support
Add CLI flag to configure HTTP/SOCKS proxy for Playwright browser context.
Supports URL format with optional credentials: http://user:pass@host:port
* fix: improve proxy parsing error handling
- Handle malformed credentials (@ without :) by ignoring incomplete creds
- Replace unwrap() with expect() for better error messages
- Addresses Vercel bot code review suggestions
* Restaura cambios locales: soporte AGENT_BROWSER_HOME y timeout aumentado
- Agrega soporte para variable de entorno AGENT_BROWSER_HOME en connection.rs
- Aumenta timeout por defecto de 10s a 60s para conexiones más lentas
* feat: add --proxy flag for browser proxy configuration
Implements proxy support based on PR #16 with reviewer feedback:
Features:
- Parse proxy URLs: http://[user:pass@]host:port
- Support for HTTP, HTTPS, and SOCKS5 protocols
- Handle username-only auth (preserves username with empty password)
- Apply proxy to both standard and persistent contexts
Changes:
- cli/src/flags.rs: Add proxy flag parsing
- cli/src/main.rs: Add parse_proxy() with comprehensive tests
- cli/src/output.rs: Add --proxy to help output
- cli/src/commands.rs: Fix test helper to include proxy field
- src/types.ts: Add proxy to LaunchCommand interface
- src/protocol.ts: Add proxy validation schema
- src/browser.ts: Apply proxy to context creation
Tests:
- 7 unit tests for parse_proxy() covering all edge cases
- All Rust tests passing (69 tests)
- All TypeScript tests passing (168 tests)
- TypeScript typecheck passing
Resolves feedback from PR #16:
- Fixed username-only proxy handling (issue #2681046975)
- Added comprehensive unit tests
- Added --proxy to help documentation
- Used expect() instead of unwrap() for better error messages
* refactor: simplify parse_proxy function
- Remove redundant comments
- Extract server variable to reduce duplication
- Inline trivial username/password variables
All 7 proxy tests still passing.
2026-01-16 11:56:35 -06:00
Chris TateandVercel <vercel[bot]@users.noreply.github.com>
* feat: add CDP connection support for external browsers
Add --cdp flag to connect to browsers via Chrome DevTools Protocol.
This enables control of Electron apps, Chrome instances, or any browser
exposing a CDP endpoint.
- Add cdpPort option to launch command schema
- Implement connectViaCDP() using chromium.connectOverCDP()
- Track browser connection type for proper reconnection handling
- Collect all pages from all contexts for CDP connections
Usage: agent-browser --cdp 9222 snapshot
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat: enhance CDP connection handling and improve page tracking
* main.rs update
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
* fix: verify CDP connection is alive before early return in launch()
Prevents misleading errors when the remote browser crashes by checking
isConnected() before reusing an existing browser reference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: reconnect when CDP port changes instead of reusing existing browser
Ensures --cdp flag is respected even when a browser session already exists.
Adds tests for launch() reconnection behavior.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update src/browser.ts
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
* fix: improve CDP connection handling and validation
* feat: add CDP connection validation to ensure browser context accessibility
* Update src/browser.ts
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
* feat: enhance CDP connection handling and add reconnect logic
* fix: improve CDP connection handling during browser closure
* fix: reset cdpPort to null during browser initialization
* feat: enhance browser launch logic to handle CDP connection switching
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>