Files
claudetools/.claude/memory/reference_ff_firefox_driver.md
Mike Swanson 8a9759789f feat(scripts): add Firefox driver (ff.py) via Playwright; disable claude-in-chrome
Add .claude/scripts/ff.py, a Firefox browser driver built on Playwright and
the Firefox sibling of the existing cdp.py Chrome driver. It runs a small
background daemon holding one Playwright Firefox page on a persistent profile,
controlled over localhost:9333, with subcommands launch/status/nav/shot/click/
type/eval/console/network/stop. Verified end-to-end (real screenshot, network
and console capture). This is now the preferred browser-automation path because
Mike dislikes Chrome and the claude-in-chrome extension (that connector was
disabled in ~/.claude.json this session - not a repo change).

Add memory reference_ff_firefox_driver.md documenting the driver and an index
line in MEMORY.md. The MEMORY.md change also unavoidably includes a pre-existing
adjacent index line for reference_antigravity_agy_not_headless.md, so that memory
file is bundled in to keep the index consistent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 18:50:45 -07:00

2.5 KiB

name, description, metadata
name description metadata
reference_ff_firefox_driver Drive Firefox via Playwright (.claude/scripts/ff.py) — Mike's preferred browser; replaces the disliked claude-in-chrome extension
type
reference

.claude/scripts/ff.py drives Firefox over Playwright — the Firefox sibling of reference_cdp_chrome_driver. Mike dislikes Chrome and the claude-in-chrome MCP extension, so when he asks to "look at a website / interact / collect the logs", use this, not Chrome. (The Chrome connector was disabled 2026-06-06: keys claudeInChromeDefaultEnabled, cachedChromeExtensionInstalled set false and chromeExtension pairing removed in ~/.claude.json; backup at ~/.claude.json.bak-prechrome. Re-toggle in the connectors UI if it reappears.)

Why a daemon, not stateless like cdp.py: Firefox dropped most CDP support, so cdp.py's "new WS per command" trick doesn't port. ff.py launch spawns a background daemon holding ONE Playwright Firefox page on a persistent profile (~/.claude/ff-profile, logins survive); every other subcommand is a thin HTTP client to it on localhost:9333 (env FF_PORT). The page persists between calls (nav now, shot later) and the daemon accumulates console + network logs.

Commands: launch [url] [--headless] · status · nav <url> · shot <out.png> (real PNG to disk → feed to agy image-analyze/Grok) · click <x> <y> · type <text> · key <Key> · eval <js> · console [--clear] · network [--clear] · stop. Default headed (visible) so Mike can log into authenticated apps once; Claude still must NOT type passwords.

Gotchas (both bit during build, 2026-06-06):

  • py honors a script's shebang. ff.py's #!/usr/bin/env python makes py ff.py resolve python via PATH → Python 3.12, while bare py -c uses the default 3.14. Playwright is installed in BOTH now (<py312>\python.exe -m pip install playwright + ... -m playwright install firefox), so it's interpreter-agnostic. If ModuleNotFoundError: playwright recurs after a Python upgrade, install playwright into whatever py .claude/scripts/ff.py status actually runs.
  • The detached daemon's stdio is redirected to ~/.claude/ff-daemon.log (NOT inherited) — otherwise launch never returns control and startup crashes are invisible. Check that log if launch hangs.

Verified end-to-end 2026-06-06: launch→status→eval→shot (26KB real render of example.com)→network (200 captured)→console (caught an injected log). See reference_cdp_chrome_driver.