Commit Graph
473 Commits
Author SHA1 Message Date
Chris Tate 05018b309a prepare v0.16.0 (#596) 2026-03-03 16:09:39 -06:00
Chris Tate 9d0454d229 fix: switch from native-tls to rustls for cross-compilation (#595)
The native PR introduced tokio-tungstenite and reqwest with native-tls,
which depends on openssl-sys (C library). This breaks the release
workflow's cargo-zigbuild cross-compilation on Linux because zig's C
compiler can't find the system OpenSSL headers.

Switch to rustls (pure Rust TLS) which has zero C dependencies and
cross-compiles trivially. Also shrinks the dependency tree.
2026-03-03 15:45:20 -06:00
Chris Tate 51f5fa484c native (#594)
* Native Rust rewrite of agent-browser daemon

Single-binary Rust implementation replacing the Node.js/Playwright daemon
with direct CDP (Chrome DevTools Protocol) communication. Includes full
command parity, WebDriver/Safari/iOS backend routing, request tracking,
frame context management, CDP protocol codegen, and comprehensive tests.

* improvements

* fix ci

* fixes

* faster builds
2026-03-03 15:15:57 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 857c0b25df chore: version packages (#591)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-03 08:21:58 -06:00
Chris Tate 62241b50e9 chore: add patch changeset for release (#589) 2026-03-03 08:08:02 -06:00
Chris Tate c6a33b6338 fix(windows): resolve daemon startup failures and Git Bash compatibility (#582)
* fix(windows): resolve daemon startup failures and Git Bash compatibility

Three root causes behind 27 open Windows issues:

1. Path::canonicalize() returns \\?\ prefixed paths on Windows that
   Node.js cannot parse, preventing daemon startup. Strip the prefix
   before passing to Node. (fixes #522, #390, #56, #25, #37, #89)

2. Git Bash/MSYS2 translates Unix-style paths and resolves node to
   a shell wrapper script. Use node.exe explicitly and set
   MSYS_NO_PATHCONV/MSYS2_ARG_CONV_EXCL to prevent argument mangling.
   (fixes #148, #108, #171)

3. postinstall fixWindowsShims() hardcoded x64 arch and did not verify
   the native binary exists before rewriting shims. Now detects arch
   dynamically and validates the binary path. (fixes #262)

Also:
- Error messages now show TCP port on Windows instead of Unix socket path
- Windows CI expanded to test full daemon lifecycle (open, snapshot, close)

* fix(windows): strip \\?\ prefix in auth-cli path (fixes #579)

Same canonicalize() issue as the daemon spawn path, but in
run_auth_cli() which passes the script path to Node.js.
2026-03-03 08:00:14 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> d97e2016f5 chore: version packages (#585)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-02 17:16:52 -06:00
Chris Tate 6aea316c82 chore: add patch changeset for release (#583) 2026-03-02 17:10:32 -06:00
Chris Tate c7fa10cb1b remove skill creator (#581) 2026-03-02 16:26:19 -06:00
Giulio Leone b304a4188c fix: correct misleading output for cookies clear and tab close (#556) (#563)
Bug 1: `cookies clear` printed 'Request log cleared' instead of 'Cookies cleared'
because the output handler matched the generic `{ cleared: true }` response shape
without checking the action context. Now uses the `action` parameter to distinguish
`cookies_clear` from `requests --clear`.

Bug 2: `tab close` printed 'Browser closed' instead of 'Tab closed' because the
output handler matched the generic `{ closed: ... }` response shape without checking
the action context. Now uses the `action` parameter to distinguish `tab_close` from
`close` (full browser close).

Closes #556
2026-03-01 12:23:23 -06:00
neilmixandClaude Opus 4.6 e912f541f2 fix: treat EPERM from kill(pid, 0) as "process exists" in daemon liveness checks (#564)
Per POSIX, kill(pid, 0) returns EPERM when the process exists but the
caller lacks permission to signal it, and ESRCH when it does not exist.
The daemon liveness checks in both the Rust CLI and TypeScript daemon
treated any kill failure as "not running", which is incorrect when
running inside a macOS sandbox that restricts signal delivery to
(target self). This caused the CLI to delete the real daemon's socket
and PID files, then spawn a duplicate daemon.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:12:37 -06:00
7238b7da4c fix: resolve unnamed element refs matching multiple elements (#573)
* fix: resolve unnamed element refs matching multiple elements (#500)

When a page has one unnamed button among several named buttons,
clicking its ref fails with "matched N elements" because the
locator `getByRole('button')` matches all buttons on the page.

Normalize unnamed interactive elements to `name: ""` so the
selector becomes `getByRole('button', { name: "", exact: true })`
which matches only buttons with empty accessible names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove dead code branch in buildSelector

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: make RefMap.name required string, remove dead code branches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: hyunjinee <leehj0110@kakao.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:42:05 -06:00
Chris Tate 79d8dfe34c add skills to docs (#576) 2026-03-01 09:02:06 -06:00
Chris Tate 14ec5b5ffa add slack skill (#571) 2026-02-28 12:03:50 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 79b05877a8 chore: version packages (#548)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-26 11:45:22 -06:00
Chris Tate 7bd8ce937b chore: add patch changeset for release (#546) 2026-02-26 11:36:47 -06:00
Ryan Siddle b455a58aa2 fix: preserve chrome-extension:// and chrome:// URL schemes in CLI (#410)
The CLI's URL normalization was auto-prepending https:// to any URL
whose scheme wasn't in the allowlist (http, https, about, data, file).
This caused chrome-extension:// URLs to become
https://chrome-extension//... which fails with ERR_NAME_NOT_RESOLVED,
preventing navigation to extension pages (popup, side panel, options).

Add chrome-extension:// and chrome:// to the open command's scheme
allowlist, and update the record start/restart commands to preserve
any URL that already contains :// instead of only checking for http.

Fixes #409
2026-02-26 11:30:02 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> b59dc4c82c chore: version packages (#545)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-25 15:57:43 -06:00
Chris Tate 2e38882664 prepare v0.15 (#544)
* 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

* prepare v0.15
2026-02-25 15:47:26 -06:00
Chris Tate bc1e917e87 add security hardening features (#543)
* 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
2026-02-25 15:33:20 -06:00
Chris Tate c0e2b80f8c add dogfood skill for agent-driven exploratory qa (#538)
* dogfood skill

* evals

* haiku

* fixes

* caching

* fixes

* don't use npx
2026-02-24 11:35:50 -06:00
Chris Tate f319195974 add --selector flag to scroll command (#537)
* add --selector flag to scroll command

The `scroll` command uses `window.scrollBy()`, which has no effect on apps
that use custom scrollable containers (e.g. a nested div with overflow-y: auto).

The backend `handleScroll` already supports a `selector` parameter, but the CLI
never exposed it. This adds `-s` / `--selector` to the `scroll` command so users
can target a specific scrollable element:

    agent-browser scroll down 500 --selector "div.scroll-container"

Also fixes the backend to apply `direction`/`amount` when a selector is present
(previously those fields were only used in the no-selector branch).

Closes #501

* fixes
2026-02-24 07:40:46 -06:00
Chris Tate 77f2caa1bc feat: add --download-path option (#536)
* 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
2026-02-24 07:22:55 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2fe7394dbe chore: version packages (#535)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-23 11:03:57 -06:00
Chris Tate b7665e52b6 v0.14.0 changeset (#534)
* v0.14.0 changeset

* fixes

* improvements
2026-02-23 10:48:07 -06:00
shohuandshohu 16c4ef2da6 fix(daemon): add backpressure control and command serialization to prevent IPC EAGAIN (#529)
- Add AGENT_BROWSER_DEFAULT_TIMEOUT env var to override Playwright's
  default 60s timeout (CDP/recording 10s timeouts unaffected)
- Add backpressure-aware safeWrite() that waits for drain when socket
  buffer is full, preventing data loss under load
- Serialize command execution per socket via queue to prevent concurrent
  writes that cause buffer contention

These daemon-side fixes complement #329 (CLI-side EAGAIN retry) by
addressing the root causes: Playwright operations that outlast the
CLI's IPC timeout, and concurrent socket.write() calls that overflow
the kernel buffer.

Tested with heavy React app (1000+ DOM nodes) — 10 consecutive
snapshot commands complete without os error 35/11.

Refs #322

Co-authored-by: shohu <shohu@users.noreply.github.com>
2026-02-23 10:06:06 -06:00
ProviandClaude Opus 4.6 ad6e206a90 feat: add keyboard command for raw keyboard input (#521)
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>
2026-02-23 09:44:08 -06:00
Lukas Malkmus f10f3f6425 cli: only warn about --annotate when explicitly passed via CLI (#531)
The warning "⚠ --annotate only applies to the screenshot command" fires
on every non-screenshot command when annotate is set in config. This is
noisy for users who set it as a persistent default.

Add cli_annotate tracking (matching the existing cli_* pattern) so the
warning only fires when --annotate is passed as a CLI flag.
2026-02-23 09:24:19 -06:00
Chris Tate c0f8f32a55 fix remote debugging (#533)
* fix remote debugging

* debug log
2026-02-23 09:19:21 -06:00
Chris Tate 12d79e4428 add --color-scheme flag for persistent dark/light mode (#528)
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
2026-02-23 01:50:17 -06:00
Chris Tate 467b830974 fix state load failing when no browser is running (#527)
`state load` always fails with "Cannot load state while browser is running" even when no browser is running, making the command completely unusable (#526).

The daemon's auto-launch logic starts a browser before `state_load` gets to handle the command. This adds `state_load` to the exclusion list alongside `launch` and `close`, so `handleStateLoad` can perform its own launch with the state file.
2026-02-23 00:56:48 -06:00
Chris Tate 4412899379 update header/og font (#524) 2026-02-22 16:09:37 -06:00
Chris Tate fca9d7ab5d fix og (#515) 2026-02-20 08:49:53 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 2b8a51b9a6 chore: version packages (#513)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-20 00:14:32 -06:00
Chris Tate ebd87173e4 chore: add minor changeset for release (#512) 2026-02-20 00:06:52 -06:00
Chris Tate d5a667ea2d diff (#510)
* diff

* fixes

* fixes

* fixes

* fixes

* fixes

* better docs
2026-02-19 23:51:09 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 9732031087 chore: version packages (#505)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-18 22:41:17 -06:00
Chris Tate 69ffad0f04 chore: add minor changeset for release (#504) 2026-02-18 22:31:37 -06:00
Chris Tate e2e259f1e2 annotated screenshots (#503)
* screenshot annotation

* fixes

* fix CI checks

* fixes

* fixes

* fixes

* fixes

* fixes
2026-02-18 22:20:01 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 06a32f4191 chore: version packages (#499)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-18 00:40:56 -06:00
Chris Tate c6fc7df443 chore: add patch changeset for release (#498) 2026-02-18 00:34:52 -06:00
Chris Tate 98f49da196 chaining (#497) 2026-02-18 00:24:59 -06:00
github-actions[bot]andgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 85340cb432 chore: version packages (#496)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-17 23:33:44 -06:00
Chris Tate 5dc40b4ea4 chore: add minor changeset for release (#495) 2026-02-17 23:28:34 -06:00
Andrew ImmandChris Tate 59fa36b6e2 feat: Enable capture of profiling data (#290)
* 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>
2026-02-17 23:11:11 -06:00
Chris Tate 9ca182a4df add config (#494)
* add config

* improvements

* cleaner flags

* fixes

* fixes
2026-02-17 22:27:44 -06:00
Chris Tate 76df589aea update docs (#493) 2026-02-17 21:37:41 -06:00
Chris Tate 19dd2d0c0b fix(#491): auto-disable viewport for --start-maximized and --window-size args (#492)
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.
2026-02-17 20:27:38 -06:00
Chris Tate f9b33ac23d fix: reject invalid --headers JSON, empty frame commands, and --cdp + --extension combo (#488)
## Summary

- Return a `ParseError` when `--headers` receives invalid JSON instead of silently dropping the headers and proceeding
- Reject `frame` commands that provide no `selector`, `name`, or `url` (previously returned `{ switched: true }` without doing anything)
- Add missing mutual exclusion check for `--cdp` + `--extension` (extensions require a local browser, not a CDP connection)
2026-02-16 23:55:40 -06:00
Chris Tate 01efe418af fix: resolve 3 protocol bugs, improve CLI and snapshot code quality (#487)
## 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)
2026-02-16 22:47:31 -06:00