The problem with reviewing code you did not write
An AI coding agent can produce a working feature in minutes. The bottleneck moved: the constraint is no longer how fast code gets written, it is how confidently anyone can say the code does what it was supposed to do. Reading a large diff carefully takes longer than generating it did.
Type checks and unit tests confirm the code does what it was written to do. They cannot tell you whether the deployed application still works, because they never open one. That gap is where AI-generated regressions actually live.
commands in the verification loop: create, run, fix
The loop, in three commands
Install the open-source TestSprite CLI — free, Apache-2.0, Node 20.19+, 22.13+, or 24+:
npm install -g @testsprite/testsprite-cli
testsprite setup
Then the loop. Describe the behaviour you want guaranteed, run it against a real browser, and read the verdict from the exit code:
# 1 — create the test and run it
testsprite test create --project prj_abc123 --type frontend \
--plan-from ./checkout-flow.plan.json --run --wait --output json
# → exit 1: the run failed
# 2 — pull ONE self-consistent failure bundle
testsprite test failure get test_3a9f21c7 --out ./.testsprite/failure
# 3 — fix the code, then replay the same test
testsprite test rerun test_3a9f21c7 --wait --output json
# → exit 0: passed
The bundle in step two is the part that matters. It contains the failing step, its neighbouring steps, screenshots, DOM snapshots, the test source, a root-cause hypothesis, and a recommended fix target — all sharing a single snapshot id. The CLI refuses to combine data from two different runs, so an agent is never reasoning over a context assembled from two different states of the application.
Why a durable suite beats a bigger context window
Every test that passes is banked. The next time the agent touches the codebase, that requirement is still being checked — whether or not it is anywhere in the current conversation.
This is the structural argument for external verification. A context window holds what the agent is thinking about right now. A test suite holds every requirement the project has ever gotten right, and it keeps holding them across sessions, across agents, and across the months when nobody remembers why a particular edge case mattered.
Not yet covered
testsprite test create — describe the new behaviour in plain language and run it. The requirement becomes permanent.
Already covered
testsprite test rerun — replay the existing tests so nothing that used to work breaks silently.
Something failed
testsprite test failure get — one bundle, one snapshot, one root-cause hypothesis. Fix and replay.
Set your agent up to do this itself
You should not have to relay commands between a web page and your coding agent. One setup command installs a skill file into the repository describing the loop in the form an agent actually consumes:
TESTSPRITE_API_KEY=sk-... testsprite setup --from-env --yes --agent claude
Supported harnesses are claude, codex, cursor, cline, antigravity, kiro, windsurf, and copilot. Installation is purely local. After that, the agent knows how to create, run, and triage tests without being told again in every session.
Before spending a turn on a command that will fail for environmental reasons, check the environment:
testsprite doctor # CLI and Node versions, profile, credentials, connectivity
What to verify first
Not everything deserves an end-to-end test. In a codebase changing quickly under an AI agent, the highest-value coverage is narrow:
The flows that produce revenue. Sign-up, checkout, and billing. A regression here costs money immediately and is frequently invisible in unit tests.
Anything involving authentication. Session handling, redirects after login, and permission boundaries are where a plausible-looking refactor does the most damage.
Forms and validation. Cheap to describe, disproportionately likely to break when a component library is upgraded or a field is renamed.
The last three bugs you shipped. A regression test written after a fix is the single highest-yield test in any suite.
If you would rather have the first set proposed for you, exploration can draft them. Proposals are staged for review and nothing is written to your disk until you accept:
testsprite test plan generate --project prj_abc123
testsprite test plan accept --project prj_abc123 # all of them
testsprite test plan accept --project prj_abc123 --only prop_2 prop_5
Making the check mandatory
A verification step that runs only when someone remembers to run it is not verification. Put it in CI:
testsprite ci init github
That scaffolds .github/workflows/testsprite.yml using TestSprite/testsprite-action@v1, which annotates the PR checks tab with one error per failure, appends a results table to the job summary, uploads a JUnit report, and — importantly — fails the job on a partial run rather than reporting it green.
That is the path where your workflow drives the run. TestSprite also installs as a GitHub App that listens for the deployment events your pipeline already produces and comments results back on the pull request, which needs no workflow file and no repository changes at all.
In any other CI system the CLI needs only an API key in the environment:
export TESTSPRITE_API_KEY="$TESTSPRITE_API_KEY"
testsprite test run --all --project prj_abc123 --wait \
--report junit --report-file testsprite-junit.xml \
--summary-file testsprite-summary.json
Exit codes worth branching on
| Exit | Meaning | The right response |
|---|---|---|
0 | Every test passed | Merge |
1 | A test failed | test failure get, fix, test rerun |
3 | Auth error | Key missing or invalid — stop, do not retry |
5 | Validation error | Malformed plan file — run test lint |
7 | Timeout or unsupported | Re-run to re-attach, or raise --timeout |
11 | Rate limited | Retriable — back off |
12 | Insufficient credits | Not retriable — a human needs to act |
14 | Client too old | Upgrade the CLI |
Codes 129, 130, and 143 mean the process was interrupted by a signal (128 plus the signal number), not that a test failed — worth distinguishing before reporting a run as broken.
Frequently asked questions
Is this a replacement for unit tests?
No, and it should not be. Unit tests are the cheapest possible check and an agent should run them constantly. End-to-end verification answers a different question — whether the deployed application works — which unit tests structurally cannot answer.
Does the agent need to write browser automation code?
No. A test is a plain-language plan file with action and assertion steps. Run testsprite test create --plan-template for a schema-correct skeleton pinned to your installed version.
Can I try the commands without spending credits?
Yes. --dry-run exercises the full code path offline with canned data, and test scaffold and test lint never touch the network or your credentials at all.
Is the CLI open source?
Yes — Apache-2.0, on GitHub, and free to install from npm. Test execution runs in the cloud and consumes workspace credits.
How does it know a failure is a real bug and not a flaky test?
The failure bundle includes a root-cause hypothesis and a recommended fix target rather than just a red mark. testsprite test flaky replays a test several times with auto-healing off and reports a stability score when you need to settle the question directly.
Which coding agents are supported?
Claude Code, Codex, Cursor, Cline, Antigravity, Kiro, Windsurf, and Copilot, via testsprite agent install <agent> or the --agent flag on setup.
Generate fast, verify externally.
The speed of AI code generation is only useful if something independent confirms the result. A durable test suite is that independent thing — it outlives the context window, catches the regressions a diff review misses, and turns a red run into a specific fix target instead of a mystery. Install the CLI in one line, read the reference at docs.testsprite.com, and star the open-source CLI on GitHub.