Your agent writes the E2E tests.
You review and commit.
unotest is AI-native end-to-end testing. Your AI agent drives your real app over MCP and writes clean, reviewable tests in your repo — for web and for iOS.
Works with Claude Code · Cursor · Codex
unotest web
E2E for web apps. Playwright-vocabulary DSL on a sandboxed engine, driven by your agent over MCP.
unotest mobile
E2E for iOS apps (React Native + native Swift). The agent drives the Simulator through the accessibility tree.
Full control
AI does the work. You keep control.
The whole point: speed from the agent, ownership stays with you.
Plain .js in your repo
Tests are ordinary JavaScript in unotest/e2e/*.js. Git, code review, CI — no proprietary format, no binary blob.
No silent fixes
agent_fix composes context and a suggestion — it never calls an LLM itself and never applies a patch on its own. You read the diff and commit.
Runs locally
Everything runs on your machine. Your app never leaves it. No cloud, no account to start.
Safe to run blindly
Scenarios execute in a sandboxed AST interpreter — no require, no fetch, no filesystem. AI-generated tests can run without surprises.
What's new
unotest 0.41.0
Released 21 September 2026.
A box rented from the dashboard tells you what to do next
A box created from the CLI arrives with your suite already on it. One rented from the dashboard arrived empty, and the card said nothing about that: an address, a login, a password, and a machine that answers with an empty viewer. The card now carries the three commands that take a project from there to a first run, each copied in one click, with the box's own name already in them. The environment is filled in when the box has exactly one, and left as a placeholder when it has several, because picking one for you would send the run somewhere you did not mean.
The values commands find your box by themselves
Pushing environment values used to answer "no box address" in a project where pushing a suite worked, so two exports were typed in front of every line. The values commands now resolve the box and the token exactly the way the suite push does: a flag, then the environment, then the project's own files, where creating a box or taking its tokens already wrote them. Setting a value takes it as an argument, a dry run prints what the overlays resolved to with the quotes visible, and a secret is still never printed.
Your box installs your suite, and keeps what it downloaded
A suite whose dependency install went quiet for more than five minutes used to kill the install on the 301st second, blame the network, and start the same install again in the second it failed, for as long as the box existed. Silence is no longer a failure, an abandoned install takes its container with it instead of filling the box, and a failed install is followed by a pause that grows rather than a loop. Installs on a box now also share one npm cache, so the second install of the same suite does not download what the first one already fetched. A run never sees that cache: it belongs to the install alone.