Repository navigation
v2.3.0
Drive focus-gated pages on a background tab without stealing OS window focus. Some sites gate a button behind document.hasFocus()/visibilitychange — the canonical case is Anthropic's Claude Code OAuth page (claude.ai/oauth/*), whose Authorize button stays disabled on a background tab, forcing an agent driving claude -p login to keep a human clicking. Two new Chrome-only tools port the mechanism of the danbuhler/claude-code-auto-authorize extension: Emulation.setFocusEmulationEnabled makes the page believe it is focused (hasFocus→true, visibility stays visible, focus events fire) while the real window stays put, and Input.dispatchMouseEvent delivers the trusted click (isTrusted:true) that a content script's synthesized events can never produce.
Added
focus_emulation { enabled }— the raw toggle: a tab reports focused/visible with no OS focus change. Call withenabled:falseto restore.click_focus_gated { selector|text, timeoutMs, pollMs, keepFocus }— the one-call compose: enable focus emulation, poll until the button (CSS selector or exact visible-text, e.g."Authorize") exists and is enabled, trusted-click it, restore emulation (always, unlesskeepFocus, even on throw). Timeout error names the failure mode ("never located" vs "found but stayed disabled").- New capability
emulate.focus(Chrome declares it; BiDi's emulation module has no focus primitive, so both tools are absent fromtools/listunder--browser firefox, per ADR-001). - New live harness
test/focus-emulation-smoke.ts(bun run focus:smoke): a real headless Chrome serves a focus-gated Authorize fixture (disabled untilhasFocus()), proves the gate is closed in a background tab (control), thenclick_focus_gatedopens it and lands a trusted click — page log showsgate:unlocked+CLICKED trusted=truewith the tab never activated. Plus unit teststest/focus-emulation.test.ts(16) pinning validation, capability gating, and manifest/docs/group registration.