Deep UI verification for agents nobody is watching

Your agent says done. Nobody looked.

Agents that run alone, in CI or a cloud sandbox, have no screen and no one to click through the app. So the dialog behind a click, the error after a failed save and the empty list go unchecked. One Abbox command finds the way there from the code, fakes the answers, reports what is on screen, and exits 0 or 1.

Free. No signup, no account, no token. The CLI runs where the agent runs.

$ npx @abbox/cli@latest verify --all

[abbox] Started abbox watch in the background (app http://localhost:5200, backend ../backend)
[abbox] Nothing answered at http://localhost:5200: started npm run dev in the background
[abbox] Signing in as buggy…
PASS  Action added: Close and refresh   [answer PUT /api/bugs/:param=404]
  Abbox: showing "Close and refresh". On screen now.
  page: /board   heading: "BuggyBoard"
  alert: "This bug was deleted by someone else."
  element: <button> "Close and refresh" visible, 148x38
  console errors: 0   failed requests: 0
  then: clicked "Close and refresh": the dialog closed; sent GET /api/bugs

From a run on BuggyBoard, an open-source bug tracker, started by the agent with nothing running beforehand and an empty database. The message only shows when someone else deleted the bug while its edit dialog was open. Abbox opened the dialog, edited a field so Save turned on, answered the save with a 404, then clicked the new button to show what it does.

Built for agents that work alone.

A background agent edits the code, type-checks it and opens a pull request saying it’s done. The reviewer then pulls the branch, signs in and clicks through to check. Abbox moves that check into the agent’s own run.

No screen needed

It runs headless in the agent's sandbox or a CI job. It starts abbox watch and the app's dev server itself when they aren't running.

A signal an agent can act on

verify --all exits 0 when every deep change passed and 1 when one failed. On a failure the agent fixes the code and runs it again before it opens the pull request.

Driven by the diff

changes reads the working copy and says, per change, what to check and how. The agent doesn't have to guess which states its edit touched.

Evidence on the pull request

Each result is a few lines of text and a screenshot: the element, the page, the alert, what clicking a new button did. The reviewer reads evidence instead of a claim.

Deep means something has to happen first.

A deep UI change isn’t on screen when the page opens. That is the only kind Abbox is for.

Behind clicks and forms

A dialog, the second step of a wizard, a row's edit modal, the page after a form is sent.

Behind a backend answer

A 404, a 409, a server error, a slow or failed request, a status that changes from Pending to Paid.

Behind data you don't have

The empty list, the list with one item, the record with the badge, the third party that declines the card.

A change that is on screen as soon as the page opens (a heading, a colour, a margin) is shallow. Your agent's own browser checks it in one step, and Abbox says so instead of pretending to be faster.

Change. List. Verify.

  1. 1

    List what changed

    npx @abbox/cli@latest changes

    Each changed element with its page, file and line, what shows it (clicks, a form, an answer such as PUT /api/bugs/:id=404), and a check: line saying whether Abbox or a browser should check it.

  2. 2

    Verify the deep ones

    npx @abbox/cli@latest verify --all

    Abbox signs in with a test user, does the clicks, fills the forms and answers the backend's requests itself, fakes the list it needs, and reports what is on screen. A new button gets clicked too, to show what it does. Exit code 1 if anything fails.

  3. 3

    Try the other outcomes

    npx @abbox/cli@latest verify <id> --answers "PUT /api/bugs/:id=500"

    Any answer the backend's code can send, or any server can: 500, offline, a hang. Nothing is written to your data.

For coding agents

If you are an AI agent working on this kind of app, this is the short version. The full reference is in the agent docs and llms.txt.

When to use it
After a frontend change whose result only shows after clicks, a form, a backend answer or data you don't have. Run changes first: its check: line says, per change, whether to run verify or to look in your own browser.
What it needs
Nothing to start by hand. changes and verify start abbox watch and the app's dev server in the background when they aren't running. Signing in needs a test user in .abbox/test-accounts.json.
What comes back
Per change: PASS or FAIL, the page and heading it ended on, the element's tag, text, size and colours, alerts, console errors, failed requests and a screenshot path. For a new control, what clicking it did: a dialog closing or opening, the requests it sent, the page it led to. The app's own confirm() is answered and reported, and anything drawn over the element is named. A few hundred tokens, no browser tool of your own.
What it can't do
It reaches what the code proves: clicks, forms, store dialogs, requests to an Express backend and to third parties. It shows the page handling an answer it fakes, not that the real backend sends it. Typing, hovering, dragging and timers are left to your browser, and it says so.

No signup. An agent can set it up.

There is no Abbox account to create and no token to paste. One command adds the inspector to the app; a test user comes from the environment variables your CI already has, so the file with its name can be committed. Both write a short note in AGENTS.md and CLAUDE.md, so every later agent in the repo knows when to verify.

npx @abbox/cli@latest init npx @abbox/cli@latest accounts import npx @abbox/cli@latest verify --all

Questions

Do I need to sign up?
No. There is no Abbox account, token or login for the CLI. It runs where the agent runs: your laptop, a CI job or a cloud sandbox.
What is a deep UI change?
One whose result isn't on screen when the page opens. Something has to happen first: clicks or a form, a backend answer (an error, an empty list, a declined payment), or data your database doesn't have right now. Those are the states agents skip, because reaching them by hand means signing in, creating test data or editing code to force an error.
Why not just let the agent use its own browser?
For shallow changes, it should. For deep ones, the browser has to find the way there, create the data and somehow make the backend fail. Abbox reads that from the code and does it in one command, so the agent spends a few hundred tokens instead of a long browser session.
Does it check what a new button does, not just that it's there?
Yes. When a change adds a control, verify clicks it once it's shown and reports what followed: the dialog closed, a dialog opened, the requests it sent (GET /api/bugs, so the board reloads), the page it went to, any new alert. Writes it sends are faked or blocked like the rest.
Does verifying a change write to my database?
No. Requests on the way to the change are answered by Abbox inside the browser, and any other request that could change data is blocked. Reads still go to your backend, unless the walk needs data it doesn't have, such as a list with an item to click.
What about Stripe, email and other third parties?
The page only sees your backend's answer, so Abbox fakes that answer, and changes names the third party behind it: “the backend sends 402 when Stripe (payments), stripe.paymentIntents.create fails”. Requests the page sends to another host itself can fail on purpose too: 500, offline or a hang.
How do test users work in CI or a cloud sandbox?
Store them as secrets, as you would for any end-to-end test. An entry in .abbox/test-accounts.json names the environment variables (emailEnv, passwordEnv) instead of holding the password, and accounts import finds the ones your env and CI files already use. Local and test hosts only, never a live site.
Which apps does it work with?
Next.js, and React with React Router, Remix or TanStack Router on Vite, with Express backends for faked answers. The CLI is free and runs on your machine.

Don’t open the pull request before you’ve seen it.