Loading...
Loading...
Web browser automation & testing for AI agents — agent-browser CLI (Chrome/CDP, fill forms, click, scrape, screenshot, dev-server verification with page-load + console-error + UI-element checks) plus Playwright toolkit for local web apps (debugging UI behavior, browser logs, screenshots). Use when the user asks for web QA, dev-server verification after `npm run dev`, or any browser automation against a website. For desktop/Electron/Tauri apps, see `desktop-test-agent-tauri`.
npx skill4agent add arthrod/conejo-skills browser-test-agent| Engine | When |
|---|---|
| agent-browser (Rust CLI, Chrome via CDP) | Default. Fast, accessibility-tree snapshots, |
| Playwright (webapp-testing toolkit) | When you need Playwright-specific features (multi-context isolation, codegen, video traces) |
"I'll start with the default workflow and assess what stage we're at, then continue from there. If everything is done, I'll come back and ask for your decisions. I can also do A/B/C alternatives — let me know if you want me to lay out capabilities and trade-offs."
curl http://localhost:3000agent-browser open <url># Use the /loop slash-command (Claude Code built-in)
/loop 10m "check for new comments on PR #<N> via gh CLI; if none, re-ping reviewers"
# OR use /schedule for a single delayed wake-up
/schedule "in 20 minutes, re-check comments and continue"| Path | Capability | Trade-off |
|---|---|---|
| A — agent-browser only | Fast Rust CLI, minimal deps | No multi-context, no codegen |
| B — Playwright (webapp-testing) | Codegen, multi-context, video trace, network mocking | Heavier; Node dep; slower startup |
| C — Hybrid (agent-browser for the happy path + Playwright for adversarial / multi-tab tests) | Best of both | Two installs, two mental models |
@eNnpm i -g agent-browser && agent-browser installagent-browseragent-browser skills get core # start here — workflows, common patterns, troubleshooting
agent-browser skills get core --full # include full command reference and templatesskills get coreagent-browser skills get electron # Electron desktop apps (VS Code, Slack, Discord, Figma, ...)
agent-browser skills get slack # Slack workspace automation
agent-browser skills get dogfood # Exploratory testing / QA / bug hunts
agent-browser skills get vercel-sandbox # agent-browser inside Vercel Sandbox microVMs
agent-browser skills get agentcore # AWS Bedrock AgentCore cloud browsersagent-browser skills list# 1. Open the dev server
agent-browser open http://localhost:3000
agent-browser wait --load networkidle
# 2. Screenshot for visual check
agent-browser screenshot --annotate
# 3. Check for errors
agent-browser eval 'JSON.stringify(window.__consoleErrors || [])'
# 4. Snapshot interactive elements
agent-browser snapshot -iagent-browser opendocument.querySelectorAll('[data-nextjs-dialog]')-i# Check for framework error overlays
agent-browser eval 'document.querySelector("[data-nextjs-dialog], .vite-error-overlay, #webpack-dev-server-client-overlay") ? "ERROR_OVERLAY" : "OK"'
# Check page isn't blank
agent-browser eval 'document.body.innerText.trim().length > 0 ? "HAS_CONTENT" : "BLANK"'agent-browser screenshot error-state.pngagent-browser close# Screenshot the stuck state
agent-browser screenshot stuck-state.png
# Check for pending network requests (XHR/fetch that never resolved)
agent-browser eval 'JSON.stringify(performance.getEntriesByType("resource").filter(r => r.duration === 0).map(r => r.name))'
# Check console for errors or warnings
agent-browser eval 'JSON.stringify(window.__consoleErrors || [])'
# Look for fetch calls to workflow/API routes that are pending
agent-browser eval 'document.querySelector("[data-nextjs-dialog]") ? "ERROR_OVERLAY" : "OK"'# Stream Vercel runtime logs for the deployment
vercel logs --follow
# If using Workflow DevKit, check run status
npx workflow inspect runs
npx workflow inspect run <run_id>
# Check workflow health
npx workflow health| Browser Shows | Server Shows | Likely Issue |
|---|---|---|
| Spinner / loading forever | No recent function invocations | API route not being called — check fetch URL in client code |
| Spinner / loading forever | Function started but no step logs | Workflow step is stuck — add |
| Blank page, no errors | Build succeeded, no runtime errors | Hydration issue or missing data — check SSR vs client rendering |
| Network request pending | 504 Gateway Timeout in logs | Function timeout — increase |
| Console: "Failed to fetch" | OIDC/credential error in logs | Missing |
| Error overlay visible | Stack trace in runtime logs | Read the server error — it usually has more detail than the client |
# Re-open and verify the fix
agent-browser open http://localhost:3000
agent-browser wait --load networkidle
agent-browser screenshot after-fix.png
agent-browser eval 'document.body.innerText.trim().length > 0 ? "HAS_CONTENT" : "BLANK"'
agent-browser closeagent-browser closewebapp-testingdogfooddogfood-quirksscripts/with_server.py--helpUser task → Is it static HTML?
├─ Yes → Read HTML file directly to identify selectors
│ ├─ Success → Write Playwright script using selectors
│ └─ Fails/Incomplete → Treat as dynamic (below)
│
└─ No (dynamic webapp) → Is the server already running?
├─ No → Run: python scripts/with_server.py --help
│ Then use the helper + write simplified Playwright script
│
└─ Yes → Reconnaissance-then-action:
1. Navigate and wait for networkidle
2. Take screenshot or inspect DOM
3. Identify selectors from rendered state
4. Execute actions with discovered selectors--helppython scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.pypython scripts/with_server.py \
--server "cd backend && python server.py" --port 3000 \
--server "cd frontend && npm run dev" --port 5173 \
-- python your_automation.pyfrom playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode
page = browser.new_page()
page.goto('http://localhost:5173') # Server already running and ready
page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute
# ... your automation logic
browser.close()page.screenshot(path='/tmp/inspect.png', full_page=True)
content = page.content()
page.locator('button').all()networkidlepage.wait_for_load_state('networkidle')scripts/--helpsync_playwright()text=role=page.wait_for_selector()page.wait_for_timeout()element_discovery.pystatic_html_automation.pyconsole_logging.pyagent-browserdogfooddogfood-quirks