Open source CLI + MCP server for people and AI agents

Test your website the way a person uses it.

Say what a visitor wants in plain words. Jev, a small, fast model, clicks through a real Chrome to do it, on desktop and on a phone. QAJev judges the result from the page itself, never from the model's opinion.

$ uv tool install git+https://github.com/joseairosa/qajev

Example: QAJev checks that a visitor can find the Pro plan price on a desktop browser and on a phone. Jev clicks Pricing on desktop, and on the phone opens the menu and then clicks Pricing. Both runs show "$29 per month" and pass; the gate is PASS.

~0.25 s per decisiona fraction of a cent per stepsmoke crawl: freedesktop + phone, every testread-only on real sites15 MCP toolsno selectors to maintainiOS Simulator + Android emulatorGodot & Electron games
How it works

Plain words in. A verdict out.

No selectors, no recorded clicks to fix after every redesign. A test says what a visitor wants and how you'll know they got it.

01

You say what a visitor wants

One intention per scenario, ending with "Stop when…", plus what the page must show.

goal: Find what the Pro plan costs per month. Stop when that price is visible. expect: visible: ["$29 per month"] url: /pricing
02

Jev uses a real Chrome

Jev reads the page as text and picks one action at a time, in about a quarter of a second each. It types, scrolls and follows links like a person.

click 'Pricing'p 0.94 · 0.21 s
scroll downp 0.88 · 0.19 s
donep 0.97 · 0.23 s
03

The page decides

Jev saying "done" is only a hint. Your expectations are checked against the real page, then written up in a report you can read.

  • on screen: '$29 per month'
  • url contains '/pricing'
  • page lacks 'Something went wrong'
  • findings: script errors, failed requests, broken images
Verdicts you can trust

A broken product is never mixed up with a lost visitor.

Every scenario ends with one outcome, and each one tells you whose problem it is. These reasons come from real reports.

pass

Every expectation held.

Nothing to do.

all 2 check(s) passed
fail

The product is wrong.

A check failed or the page didn't load. Here the test expected $25 and the page said $29: Jev's "done" didn't fool anyone.

Jev reported DONE but: page shows '$25 per month' (Pricing Starter $9 per month Pro $29 per month …)
stuck

A visitor got lost.

Jev found no way forward. That's often a real usability problem worth a look.

the expected text is in the page but 1 screen(s) of scrolling did not bring it on screen
harness

QAJev's problem, not yours.

A time or cost budget ran out, or the page never stopped changing. It says nothing about your product.

3 of Jev's moves went stale before they ran (the page kept changing)

Each run ends with one gate, PASS, FAIL or INCOMPLETE, and an exit code your CI understands. Extra problems seen along the way (script errors, failed requests, broken images) are listed separately as findings, from S1 (worst) to S3.

Desktop and phone. Always.

Every test runs twice. You don't have to ask.

Each website scenario also runs in a phone view: a phone-sized screen, touch and an iPhone user agent, like your browser's device mode. A failure that only shows on the phone is a real mobile bug, and the report says so.

desktopa visitor finds the Pro pricepass
phonea visitor finds the Pro price (phone)pass
iOS Safari… (iOS Safari) · opt-in--real-devices

Real phone browsers opt-in

Some bugs only show on the device itself. Add --real-devices ios,android and the same scenarios also run in Safari on the iOS Simulator and Chrome on an Android emulator, on devices QAJev starts for the run and leaves untouched: a throwaway iPhone clone, a read-only Android emulator.

Reports people read

One page that says what happened, and why.

Every run writes a self-contained report.html (light and dark), plus Markdown and JSON for programs. Projects remember the previous run and show what changed.

qajev-runs/demo-shop/report.html
A QAJev report: Gate FAIL with 3 pass, 1 fail and 1 stuck; a table of scenarios with the reason for each outcome; one newly failing scenario since the previous run; and findings such as a script error and two 404s.
report.htmlreport.mdreport.jsonscreenshots/exit codes for CI
Built for AI agents

Let your agent prove it works before it says so.

QAJev is an MCP server too. Your coding agent can crawl a site, check a change the way a user would, read the report and look at the screenshots, then tell you what it found.

# one line, then give it the agent prompt
claude mcp add -s user qajev -- qajev mcp
qa_smokeqa_checkqa_run_suiteqa_project_runqa_playqa_reportqa_screenshotqa_jobqa_jobsqa_stopqa_projectsqa_reportsqa_nightlyqa_browserqa_doctor
  • A ready-made agent prompt

    Paste AGENT_PROMPT.md into your agent's instructions. It knows which tool to use, how to write a good check and how to report the result honestly.

  • Jobs anyone can follow or stop

    Long runs return a job id at once. Any agent, or you, can see progress, what Jev is doing right now and the money spent, and stop it cleanly.

  • One queue per machine

    Many agents can share a laptop. Browser runs take turns and say what they're waiting for, so nobody starts a second copy by accident.

  • Headless and throwaway by default

    Agent runs use QAJev's own invisible Chrome with a fresh profile. Nothing pops up on your screen and nothing is left behind.

See every run, live.

qajev top shows what's queued and running on the machine, what Jev is doing at this moment, and what each run costs, down to a hundredth of a cent.

qajev top in a terminal: a queued smoke crawl, a running project with Jev typing a name into a field, finished runs with PASS, FAIL and INCOMPLETE gates and their costs, the Chrome QAJev started, and recent reports.
Beyond the browser

Mobile apps and games, too.

The same plain-language steps work in a native app on a simulator, or in a game's menus while its own bot plays in real time.

Mobile apps

Native apps and mobile websites on the iOS Simulator and an Android emulator. QAJev boots a throwaway iPhone clone (deleted afterwards) or a read-only Android emulator, and installs your build if you give it one. The microphone stays deaf.

It also catches what screen readers miss, like tab bars that VoiceOver doesn't announce as buttons.

qajev play ios:com.example.app --suite onboarding.yaml
throwaway devices.app / .apk installsystem dialogs handledaccessibility findings
A Godot horde-survival game mid-run with score, level and kill counters, under QAJev's watch.

Games

Godot and Electron games through a small bridge. Jev works the menus and picks the upgrades; the game's own pilot plays in real time; QAJev watches frame rate, memory, soft-locks and errors.

qajev play path/to/game --goal "Start a new run. Stop when the game is playing." --min-fps 30
Godot 4Electronfps & memorysoft-lock detection
Safe by default

Point it at production. Sleep fine.

Read-only on real sites

Form posts and deletes are blocked inside the page. Tests that change data only run on your own machine.

Dangerous buttons hidden

Sign out, delete, pay, billing, "close all"… Jev never sees them, so it can't press them.

No passwords, no cards

Secret and payment fields are disabled. For signed-in areas, you sign in once yourself in QAJev's own browser.

A hard cost cap

Every run has one ($1 unless you say otherwise), checked before every paid call.

A deaf microphone

Pages that listen hear only what your test says. On simulators, microphone prompts are refused.

No downloads

Every download is refused. The smoke crawl checks download links without fetching the file.

Its own browser

QAJev runs its own Chrome with its own profiles. Your everyday browser and accounts are never touched.

Polite crawling

The smoke crawl reads robots.txt and waits between pages. QAJev is not a load tester.

~0.25 sfor each of Jev's decisions
$0.0046for a five-scenario run, in a real report
$0for the smoke crawl: no model calls at all
0CSS selectors to keep up to date
Get started

Five minutes to your first report.

You need a Mac or Linux machine, Chrome, and one key for Jev from TypeSafe or OpenRouter. The smoke crawl doesn't even need the key.

  • Python 3.12+ (uv installs it for you)
  • Google Chrome or Chromium
  • Optional: Xcode or Android Studio for mobile, Godot 4 for games
installuv tool install git+https://github.com/joseairosa/qajev
add a key for Jevmkdir -p ~/.qajev && echo 'OPENROUTER_API_KEY=sk-or-...' >> ~/.qajev/.env
check your setupqajev doctor
free crawl: errors, broken links, missing basicsqajev smoke http://localhost:3000
your first check, on desktop and phoneqajev check http://localhost:3000 --goal "Open the pricing page. Stop when the prices are visible." --expect-url /pricing
Open source · MIT

Stop guessing.
Let Jev click.