🔭 Your coding agent, turned into a QA tester for any web app. Finds what is broken and shows you the proof: pictures, replays, journey videos and test reports.
Overview
Works with Claude Code · Cursor · VS Code (Copilot) · Codex CLI · Gemini CLI · Copilot CLI · Windsurf · any MCP client Scripted end-to-end tests answer one question: does this exact flow still work? They say nothing about the rest of the app. SceneScout lets the agent you already use explore a running web app like a curious, thorough tester. It clicks, fills forms, switches roles and calls the API behind a hidden button, then writes a report of what is and what could be , with a picture and evidence for every line. Try it on any app you are allowed to test. No account, no API key, no setup: A real run against the small demo app in this repository, which has bugs planted on purpose. The two you can see are outlined: It filed twelve findings. A few from the report: 2× click fired the same state-changing request 2× (POST /api/orders) POST /api/orders/1037/approve 200 as clerk: the button was hidden, the server did not agree. GET /api/orders?
README
Scripted end-to-end tests answer one question: does this exact flow still work? They say nothing about the rest of the app. SceneScout lets the agent you already use explore a running web app like a curious, thorough tester. It clicks, fills forms, switches roles and calls the API behind a hidden button, then writes a report of what is broken and what could be better, with a picture and evidence for every line.
Try it on any app you are allowed to test. No account, no API key, no setup:
npx -y scenescout http://localhost:3000
flowchart LR
A["🧠 Your coding agentClaude Code, Cursor, Copilot…"] -- MCP --> S["🔭 SceneScoutbrowser · checks · memory"]
S --> App["🌐 Your running app"]
S --> R["📋 Reportplain words + pictures"]
S --> E["🎬 Evidencereplay, videos, test report"]
👥 Who it’s for
| 🛠️ Developers | 🧑💼 QA, product and non-technical teams |
|---|---|
Findings with the request that failed (GET /api/orders?status=archived → 500), the steps, and a Playwright regression-test skeleton |
Each problem in plain words first: what was done, what was expected, what happened, and a picture of the page |
| Next to the source, the file behind the bug and a likely fix | Visible problems shown, not described: a covered button, a broken image, text too faint to read |
| A deterministic gate for pull requests, with SARIF for code scanning | Journeys recorded step by step, as frames and video, so a pass is something you can watch |
| Runs from your editor’s agent, or unattended in CI | A test report laid out by your template, with expected and actual results, deviations and blank sign-off rows |
🐛 What it catches
A real run against the small demo app in this repository, which has bugs planted on purpose. The two you can see are outlined:
It filed twelve findings. A few from the report:
🔴 [HIGH] A double-click on Create order creates two orders
2× click fired the same state-changing request 2× (POST /api/orders)🔴 [HIGH] A clerk can approve an order by calling the endpoint the page hides from them
POST /api/orders/1037/approve 200 as clerk: the button was hidden, the server did not agree.🔴 [HIGH] Filtering orders by Archived fails, and the page shows an empty table instead of an error
GET /api/orders?status=archived → HTTP 500🟠 [MEDIUM] The “New: bulk import” badge sits on top of the All orders button (callout 1)
"All orders" overlaps "New: bulk import" (81%), measured from layout boxes, no screenshot needed.
What it looks for, on every page, after every action:
- 📐 Broken layout, from geometry: controls that overlap, sit off-screen, hide under a sticky bar or can never be scrolled into view. The CSS bugs a person spots at a glance, found without one.
- 🧨 Real breakage: console errors, crashes, failed requests, 4xx and 5xx responses, broken images, dead-end pages.
- 🔓 Permission leaks: it calls the app’s own API as each role, so “the button is hidden” becomes “the server refuses it”, or doesn’t.
- 🤥 Pages that lie: “Saved!” after the server refused the save, or an empty table after the request failed.
- 👆 Impatient users: a double-click that sends the same order twice.
- ♿ Accessibility and craft: contrast, focus, labels, target sizes, spacing and type, with a 0 to 100 score per page.
- 🧭 Friction: how many steps a task takes, and where a user had to go back.
- 💉 Security smells: typed markup that comes back as an element, and tokens posted to any window.
🎬 Automated QA with evidence
Save the journeys that matter, the happy paths and the ones that must fail politely, and scenescout check replays them on every pull request with no model involved. Recorded, each run leaves proof you can watch and hand to someone who never opens a terminal.
flowchart LR
PR["🔀 Pull request"] --> C["🚦 scenescout check--record --video --template"]
F["📝 Saved journeys.scenescout/flows/*.json"] --> C
C --> G["✅ / ❌ A gate on the pull request"]
C --> RP["🖼️ replay.htmlevery step, with frames"]
C --> V["🎞️ A video per journey"]
C --> TR["📄 Test reportyour template, SHA-256 manifest,blank sign-off rows"]
A journey is a few lines of JSON, written by hand or kept from a flow your agent just walked. This is the demo’s happy path:
{
"name": "place an order",
"id": "TC-01",
"requirements": ["REQ-ORD-1", "REQ-ORD-2"],
"steps": [
{ "action": "navigate", "target": "/orders-new.html", "expected": "The new-order form is shown" },
{ "action": "type", "target": "testid=new-order-customer", "value": "Harbour Bakery", "expected": "The customer is filled in" },
{ "action": "type", "target": "testid=new-order-items", "value": "4", "replace": true, "expected": "The item count is 4" },
{ "action": "click", "target": "testid=new-order-submit", "expected": "The order is created" },
{ "action": "expect-request", "request": "POST /api/orders", "status": "2xx" },
{ "action": "expect-element", "target": "testid=new-order-created-link", "state": "visible", "expected": "A link to the new order is shown" }
]
}
Against the demo app, with the three journeys in examples/flows (one creates an order, so the check is allowed to send it):
npx scenescout check http://127.0.0.1:4173 --flows examples/flows --mode read-only --flow-writes allow \
--record --video --template examples/report-template.json
The journey, as it ran (one of the videos it filmed):
The replay page: each journey with a pass or fail badge. A journey that broke opens at the step that broke, with the page as it was after every step:
The test report, laid out by a template you write once: test IDs, the requirements each covers, expected and actual results, a screenshot per step, every deviation listed again for the reviewer, and the SHA-256 of each piece of evidence. SceneScout signs nothing; the sign-off rows are for your people.
Everything is one self-contained HTML page per report, with no scripts, nothing loaded from the network, and a layout that prints. Recording a check and a test report from a template have the details, including what to keep out of the pictures.
📺 Watch it work
Each exploratory run opens a live view on your machine, with one card per agent: what it is doing, the page it is on, and a feed of every action. Three agents are testing the demo app in parallel here:
You can read the report while the agents are still working, and scrub back through any session’s timeline. Beside report.md, every run writes report.html, the whole run as one self-contained page; ask for a recorded run and it also keeps a frame after every action.
✨ Why it’s different
- 🧠 Your agent is the brain, so no extra API key. The engine contains no model. It gives the agent you already pay for deterministic tools and the testing method to use them.
- 📐 It reads structure, not pixels. The agent sees every element with its role, state and layout box, so overlap and broken images are measured, not guessed from a screenshot.
- 🛡️ Safety is enforced on the network, not requested in a prompt. Nothing existing is changed unless you allow it, and a blocked write never reaches your server.
- ✅ “Done” is a contract. The report lists everything not tested, and at the
extensivelevel refuses to finish while any known page is unvisited. - 🧠 It remembers. Each run starts from what the last one learned, and re-tests the bugs earlier runs left open.
- 📊 It is measured, not asserted. Every change to how it explores is scored against an app with planted bugs and a held-out app it is never tuned on (the log):
xychart-beta
title "Planted defects found per run, demo app (13 planted)"
x-axis "Run" ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
y-axis "Found" 0 --> 13
bar [11, 12, 9, 10, 11, 11, 10, 10, 11, 13, 11, 11, 12]
Each bar is one run of eight parallel agents, re-scored against today’s answer key. One run is noisy: read the trend across runs, not a single bar.
🚀 Get started
1. Install for your agent (Node 20 or newer):
npx -y scenescout install # Claude Code: skill, MCP server and the test browser
npx -y scenescout install --client cursor # or vscode, codex, gemini, copilot, windsurf
npx -y scenescout doctor # every line should be a ✓
2. Start your app, then a fresh session of your agent, and ask:
Use SceneScout to test http://localhost:3000
In Claude Code there is a command too: /scenescout --url http://localhost:3000 --level medium. On its own, /scenescout asks instead: where your client can show a form, one guided form (the address, what to check, how you sign in, how careful to be and how thorough), and otherwise four plain questions in chat. A care level that writes on a site that is not on your computer, or that creates test data, asks you to confirm it in a second form the agent cannot answer (care levels). While it runs, scout_status follows the check in plain words, says what went wrong in one sentence with one thing to do (the site does not open, the sign-in ran out, the check ran out of time), and at the end the problems come back as cards you can mark “not a bug”. Is it safe to run on my live site? Rather press buttons than write prompts? The optional mod’s /scenescout-guided panel does the same from a form in the Claude Code CLI or the desktop Code tab (the mod).
3. Read the report in .scenescout/report.md. It opens in plain words (each problem, its steps, what was expected and what happened), with the technical detail one click away. A complete example. To hand it round, ask for a team report (scout_team_report, or Make a team report in the chat’s menu or the guided panel): .scenescout/team-report.html has a cover, each problem as a card with its picture, what was not checked and blank sign-off lines, with an evidence folder beside it holding the pictures and a manifest of every file’s SHA-256.
No app handy? Clone this repository and run npm run demo:serve: the demo app starts on http://127.0.0.1:4173, and its README lists every planted bug.
Behind a sign-in? Sign in once yourself, SSO and MFA included, and every session reuses it:
npx -y scenescout login http://localhost:3000 --role admin # then: /scenescout --role admin
Signing in covers roles, expiry and scripted sign-in for CI.
🚦 In CI
| What it does | Needs a model? | |
|---|---|---|
scenescout check |
A deterministic gate: measures every page, replays your saved journeys and visual baselines, fails only on what it can prove; recorded, it leaves the evidence above | No |
scenescout ci |
An unattended exploratory run, driven by the Anthropic or OpenAI API. It reports and never fails the build | An API key |
/scenescout qa |
A comment on a pull request that tests its preview deploy and replies with the results; /scenescout qa check runs your own check instead |
An API key (qa check: none) |
scenescout export |
Files the findings as GitHub or Jira issues, each once | No |
A gate on every pull request that keeps its evidence, as a GitHub Action:
- uses: brunoboto96/SceneScout@v3
with:
url: http://127.0.0.1:3000
record: on
video: on
template: tests/report-template.json
docs/ci.md has complete workflows, every option, and the same check on GitLab CI, CircleCI or any shell.
Ask for it on a pull request
Type a command in a pull request comment and SceneScout answers in the thread, with pictures taken by a real browser:
| Comment | Reply |
|---|---|
/scenescout qa |
Explores the pull request’s preview and replies with what it found |
/scenescout qa show the Save button |
A picture of that element |
/scenescout qa compare the Save button |
The element on the base and on the pull request, with the changed pixels highlighted |
/scenescout qa check |
Runs your saved journeys on the branch and replies with each one’s result; the video of every journey is in the run’s files |
The preview commands test a deployed preview, so the pull request’s code never runs beside the model’s key; qa check runs your own workflow and uses no key. Setting it up.
🔒 Safe by default
| Mode | What may leave the page |
|---|---|
🔵 observe |
Reads only. The default for a first look, for scenescout check, and for an agent’s run on a remote site with no source |
🟢 read-only |
Reads and ordinary form posts; nothing existing is changed or deleted. The default for an agent’s run on a local app |
🟡 safe-write |
Creates records, and edits or deletes only the ones it created |
🔴 destructive |
Everything. Only when you say the data is disposable; the agent never picks it |
A team can commit .scenescout/config.json to cap what any agent may choose, for example {"preset": "strict"} to keep every run to reads only (the config file).
The policy sits on the network, so a blocked request never reaches your server. The page gets a refusal instead, which is how SceneScout catches a page that claims success anyway. A saved journey that creates something, like the order above, runs only when the check is told --flow-writes allow, against a test environment. Findings, memory and reports stay in a .scenescout/ folder that keeps itself out of git.
[!IMPORTANT] Only test sites you own or are allowed to test. Safety model.
📚 Documentation
| Start here | A first look, install, a first run, reading the report, the live view |
| Ways to use it | Interactive runs, parallel agents, CI, pull-request QA, filing issues |
| What it checks | Every check and every scout_* tool |
| Signing in · Safety model | Roles and saved logins; what each mode refuses and why |
| Recipes | Setups for seven kinds of project |
| Configuration reference | Every option, environment variable and action input |
| Troubleshooting | Symptoms and fixes, upgrading and uninstalling |
| Running it in CI | Saved journeys, recording, test reports from templates, every workflow |
| How it works | Diagrams of a run, an action, the write policy, lanes |
| Benchmark · Validation | How runs are scored against answer keys, and runs on public apps |
| Design decisions | Why the rules are what they are |
🔧 Contributing
Start with VISION.md (what is in scope) and CONTRIBUTING.md (local setup and how changes land). AGENTS.md holds the house rules for people and coding agents alike.
Found a way past the write policy, or another security problem? Report it privately: SECURITY.md.
MIT licensed.
Install
npx -y scenescout http://localhost:3000