← the whole session plugin/skills/agentic-chrome-testing/SKILL.md
Drive the person's own already-open, already-logged-in Chrome window via AppleScript — navigate, click, screenshot, read the DOM. macOS only. Use when verifying UX in the browser identity the person actually uses (their real cookies, their real logged-in state), not a separate automation profile.
Agent Chrome Testing
Control a real, visible Chrome window — the person's own, with their own cookies and logged-in session — via AppleScript. No debug port, no CDP, no Puppeteer. Screenshots are PNGs that Claude can read natively (multimodal).
Why this one instead of a separate automation browser: some UX only shows up when you're
really signed in as yourself (personalized state, a real subscription, real history). A separate
automation profile (see /alignment-harness:devtools-site-testing, which uses the
chrome-devtools MCP and works on every platform) can't see that. This skill drives the browser
window the person is actually looking at, at the cost of being macOS-only.
Prerequisites
- macOS only. AppleScript has no equivalent on Linux or Windows. On those platforms, or if
this isn't macOS, use
/alignment-harness:devtools-site-testinginstead — say so plainly rather than silently failing. - One-time Chrome setting: Chrome → View → Developer → "Allow JavaScript from Apple Events". Without this, every command below fails with an Apple-Events permission error. If you hit that error, tell the person exactly this menu path — don't guess at another fix.
- Your app running locally. This skill needs the URL and start command for whatever you're
testing. If you ran
/alignment-harness:harness-setup, it recorded these; otherwise ask once and remember the answer for the session (e.g. "what command starts your dev server, and what URL does it serve?" — commonly something likenpm startonhttp://localhost:3000).
There is no separate "debug port" step — this script talks to Chrome directly through AppleScript, not through Chrome's remote-debugging port. If you've read an older doc that mentions a debug script, ignore it; it belongs to a different mechanism than this one.
The script
A ready-to-use driver ships with this skill: scripts/agent-chrome.js (Node, no dependencies
beyond what ships with Node itself). Run it with node:
node <path-to-this-skill>/scripts/agent-chrome.js <command> [args...]
If the project already has its own copy of an equivalent script, use that instead — the commands below are the same either way.
Commands
# Navigation — replace with the URL recorded at setup
node agent-chrome.js navigate http://localhost:3000/
# Screenshots (Claude reads these with the Read tool)
node agent-chrome.js screenshot /tmp/page.png
# Interactions
node agent-chrome.js click "#start-btn"
node agent-chrome.js click "text=Start Session"
node agent-chrome.js type "#email" test@example.com
# Inspect page state
node agent-chrome.js eval "document.title"
node agent-chrome.js eval "JSON.stringify([...document.querySelectorAll('button')].map(b => b.textContent.trim()))"
# Wait for element before acting
node agent-chrome.js wait ".loaded" 5000
# Console errors (listens for N ms, prints anything logged via console.error)
node agent-chrome.js console-errors 3000
# Tab management
node agent-chrome.js tabs
Typical Agent Workflow
1. [one-time] Chrome → View → Developer → Allow JavaScript from Apple Events
2. node agent-chrome.js navigate <your-app-url>
3. node agent-chrome.js screenshot /tmp/check.png
4. [Read /tmp/check.png — "see" the page]
5. node agent-chrome.js click "text=Some Button"
6. node agent-chrome.js screenshot /tmp/after.png
7. [Read /tmp/after.png — verify the result]
Using with a user-state simulator
If your app has an admin tool that lets you set up specific user states via URL (logged in, subscribed, a given plan, etc.), navigate to it the same way:
node agent-chrome.js navigate "http://localhost:3000/your-admin-simulator-path?auth=logged_in&subscription=trialing&redirect=/&clear=true"
# Wait for redirect to complete
sleep 2
node agent-chrome.js screenshot /tmp/simulated.png
The exact params depend entirely on your own app — this pattern only applies if you've built (or have) such a tool.
Selectors
| Type | Example | Notes |
|---|---|---|
| CSS | "#my-id", ".my-class", "button[type=submit]" |
Standard CSS selectors |
| Text | "text=Start Session" |
Matches element containing that text |
Discover selectors when you don't know what's on the page:
node agent-chrome.js eval "JSON.stringify([...document.querySelectorAll('button')].map(b => b.textContent.trim()))"
node agent-chrome.js eval "JSON.stringify([...document.querySelectorAll('a')].map(a => ({text: a.textContent.trim(), href: a.href})))"
node agent-chrome.js eval "JSON.stringify([...document.querySelectorAll('input')].map(i => ({id: i.id, name: i.name, placeholder: i.placeholder})))"
Troubleshooting
| Error | Fix |
|---|---|
| "not allowed" / Apple-Events error | Chrome → View → Developer → "Allow JavaScript from Apple Events" |
| "Element not found" | Use screenshot to see the page, or eval to inspect DOM |
| Navigate does nothing / times out | Your dev server may not be running — check its start command |
| Blank screenshot | Page may need more time to render — use wait before screenshot |
| Any command at all, on Linux/Windows | Not supported here — use /alignment-harness:devtools-site-testing |
Recording what you found
Before testing, check whether anything is already known about this flow. If memory search is
configured (see /alignment-harness:harness-setup), search it. Otherwise grep the project's own
docs/notes and git log for the page or feature you're about to test, and say plainly if nothing
turned up.
After testing, record findings as a file rather than losing them at the end of the session:
alignment-harness records ux-findings prints the folder — write a short markdown or JSON note
there (what you tested, what you saw, win/loss/pattern/blocker) and show the person the path.