Skip to content

Commit 2d97ab9

Browse files
garrytanclaude
andauthored
feat: browse handoff — headless-to-headed browser switching (v0.7.4) (garrytan#201)
* feat: browse handoff — headless-to-headed browser switching Add `handoff` and `resume` commands that let users take over a visible Chrome when the headless browser gets stuck (CAPTCHAs, auth walls, MFA). Architecture: launch-first-close-second for safe rollback. State transfer via extracted saveState()/restoreState() helpers (DRY with recreateContext). Auto-handoff hint after 3 consecutive command failures. * test: handoff unit + integration tests (15 tests) Covers saveState/restoreState, failure tracking, edge cases (already headed, resume without handoff), and full integration flow with cookie and tab preservation across headless-to-headed switch. * docs: handoff section in browse template + TODOS update Add User Handoff section to browse/SKILL.md.tmpl with usage examples. Update State Persistence TODO noting saveState/restoreState reusability. * chore: bump version and changelog (v0.7.4) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d961188 commit 2d97ab9

11 files changed

Lines changed: 552 additions & 71 deletions

File tree

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## [0.8.2] - 2026-03-19
4+
5+
### Added
6+
7+
- **Hand off to a real Chrome when the headless browser gets stuck.** Hit a CAPTCHA, auth wall, or MFA prompt? Run `$B handoff "reason"` and a visible Chrome opens at the exact same page with all your cookies and tabs intact. Solve the problem, tell Claude you're done, and `$B resume` picks up right where you left off with a fresh snapshot.
8+
- **Auto-handoff hint after 3 consecutive failures.** If the browse tool fails 3 times in a row, it suggests using `handoff` — so you don't waste time watching the AI retry a CAPTCHA.
9+
- **15 new tests for the handoff feature.** Unit tests for state save/restore, failure tracking, edge cases, plus integration tests for the full headless-to-headed flow with cookie and tab preservation.
10+
11+
### Changed
12+
13+
- `recreateContext()` refactored to use shared `saveState()`/`restoreState()` helpers — same behavior, less code, ready for future state persistence features.
14+
- `browser.close()` now has a 5-second timeout to prevent hangs when closing headed browsers on macOS.
15+
316
## [0.8.1] - 2026-03-19
417

518
### Fixed

SKILL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,9 @@ Refs are invalidated on navigation — run `snapshot` again after `goto`.
529529
### Server
530530
| Command | Description |
531531
|---------|-------------|
532+
| `handoff [message]` | Open visible Chrome at current page for user takeover |
532533
| `restart` | Restart server |
534+
| `resume` | Re-snapshot after user takeover, return control to AI |
533535
| `status` | Health check |
534536
| `stop` | Shutdown server |
535537

TODOS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252

5353
**Why:** Enables "resume where I left off" for QA sessions and repeatable auth states.
5454

55-
**Effort:** M
55+
**Context:** The `saveState()`/`restoreState()` helpers from the handoff feature (browser-manager.ts) already capture cookies + localStorage + sessionStorage + URLs. Adding file I/O on top is ~20 lines.
56+
57+
**Effort:** S
5658
**Priority:** P3
5759
**Depends on:** Sessions
5860

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.8.1
1+
0.8.2

browse/SKILL.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,32 @@ $B diff https://staging.app.com https://prod.app.com
259259
### 11. Show screenshots to the user
260260
After `$B screenshot`, `$B snapshot -a -o`, or `$B responsive`, always use the Read tool on the output PNG(s) so the user can see them. Without this, screenshots are invisible.
261261

262+
## User Handoff
263+
264+
When you hit something you can't handle in headless mode (CAPTCHA, complex auth, multi-factor
265+
login), hand off to the user:
266+
267+
```bash
268+
# 1. Open a visible Chrome at the current page
269+
$B handoff "Stuck on CAPTCHA at login page"
270+
271+
# 2. Tell the user what happened (via AskUserQuestion)
272+
# "I've opened Chrome at the login page. Please solve the CAPTCHA
273+
# and let me know when you're done."
274+
275+
# 3. When user says "done", re-snapshot and continue
276+
$B resume
277+
```
278+
279+
**When to use handoff:**
280+
- CAPTCHAs or bot detection
281+
- Multi-factor authentication (SMS, authenticator app)
282+
- OAuth flows that require user interaction
283+
- Complex interactions the AI can't handle after 3 attempts
284+
285+
The browser preserves all state (cookies, localStorage, tabs) across the handoff.
286+
After `resume`, you get a fresh snapshot of wherever the user left off.
287+
262288
## Snapshot Flags
263289

264290
The snapshot is your primary tool for understanding and interacting with pages.
@@ -381,6 +407,8 @@ Refs are invalidated on navigation — run `snapshot` again after `goto`.
381407
### Server
382408
| Command | Description |
383409
|---------|-------------|
410+
| `handoff [message]` | Open visible Chrome at current page for user takeover |
384411
| `restart` | Restart server |
412+
| `resume` | Re-snapshot after user takeover, return control to AI |
385413
| `status` | Health check |
386414
| `stop` | Shutdown server |

browse/SKILL.md.tmpl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ $B diff https://staging.app.com https://prod.app.com
106106
### 11. Show screenshots to the user
107107
After `$B screenshot`, `$B snapshot -a -o`, or `$B responsive`, always use the Read tool on the output PNG(s) so the user can see them. Without this, screenshots are invisible.
108108

109+
## User Handoff
110+
111+
When you hit something you can't handle in headless mode (CAPTCHA, complex auth, multi-factor
112+
login), hand off to the user:
113+
114+
```bash
115+
# 1. Open a visible Chrome at the current page
116+
$B handoff "Stuck on CAPTCHA at login page"
117+
118+
# 2. Tell the user what happened (via AskUserQuestion)
119+
# "I've opened Chrome at the login page. Please solve the CAPTCHA
120+
# and let me know when you're done."
121+
122+
# 3. When user says "done", re-snapshot and continue
123+
$B resume
124+
```
125+
126+
**When to use handoff:**
127+
- CAPTCHAs or bot detection
128+
- Multi-factor authentication (SMS, authenticator app)
129+
- OAuth flows that require user interaction
130+
- Complex interactions the AI can't handle after 3 attempts
131+
132+
The browser preserves all state (cookies, localStorage, tabs) across the handoff.
133+
After `resume`, you get a fresh snapshot of wherever the user left off.
134+
109135
## Snapshot Flags
110136

111137
{{SNAPSHOT_FLAGS}}

0 commit comments

Comments
 (0)