Nobody writes the tests.
End-to-end tests are the ones everybody agrees they should have and nobody keeps. You write them, a button moves, forty of them go red for no reason, and within a month the suite is muted and the next regression ships to customers instead.
So write a sentence instead. An agent uses your app in a real browser on every pull request, checks what you asked it to check, and tells you what broke — and when your UI changes it works it out again rather than going red.
Point it at anything reachable — staging, a deploy preview, localhost through a tunnel. No signup, no GitHub app, no preview environment to build, and nothing written to your repo.
The run that passes is recorded, so every run after it replays that recording and calls no model at all. The published run below is one of those: one step, 2.8 seconds, nothing billed. The agent comes back only when the recording stops fitting your app.
Open a real run — this product testing its own pricing page, published with --share. No account, and you can check the claim it makes on that page yourself.
Silent, so it reads with the sound off. The browser in it is a real recording of the run this page publishes, and every number on screen is one this site states elsewhere.
one sentence now → an agent using your app on every pull request
you write a sentence
"A returning customer can check out with a saved card." No selectors, no page objects, no fixtures. Plain English in a markdown file. An agent works out how to do it in a real browser, so there is no selector to update when a button moves — which is the reason end-to-end suites get muted and then deleted.
--- title: "Checkout completes with a saved card" criticality: critical --- Open the cart, go to checkout, pick the saved Visa ending in 4242, place the order, and confirm the order number appears.
The first run uses the agent and takes as long as a person would. It records what worked, so every run after it is the line above. The agent comes back only when the recording stops fitting your app.
one comment on the pull request, edited in place
This is what the product actually produces. A failure is a bug report — the page, the control, and what the page said instead — with the changed file most likely responsible and the evidence connecting it to the test. A recording that stopped fitting sits in its own row and is never counted as a failure, because a replay cannot tell a rename from a removal, and a suite that cries wolf about copy changes is a suite nobody reads by month two. That panel is the real comment, transcribed from the function that writes it: the headline, the rows and the reasons word for word, with the closing note shortened.
| fail | A shopper can check out with a saved card | agent | 12.5s |
| stale | A new customer can sign up | recording stopped fitting | 10.2s |
| pass | A visitor can search the catalogue | replayed, no model calls | 1.4s |
| pass | The pricing page shows a monthly price | replayed, no model calls | 0.9s |
On /cart, clicking “Proceed to checkout” left the page on /cart and replaced the cart contents with “Something went wrong. Your card was not charged.” No order number appeared.
Suspect: src/checkout/PayButton.tsx — this PR removed the string “Proceed to checkout” this test clicks
The recorded run no longer fits: the button named “Create account” could not be used. That is not yet a bug — the control may simply have been renamed.
2 of 4 ran from a recording, with no model calls. Stale is not a failure: a recorded run stopped fitting the app, which a replay cannot tell apart from a rename.
it reads the page, it does not squint at it
The agent sees the actual buttons, fields and their state — the way a screen reader does — and picks an element rather than a pixel. Tools that guess coordinates from a screenshot can click the wrong thing and then blame the wrong feature. A run that passes is recorded, so the next one replays with no model call at all: fifty recorded tests on an eight-core laptop, run in parallel, take about five seconds and bill nothing.
why this is not another test framework
We already have Playwright tests. Why would we pay for this?
Keep them. The question is not whether you can write end-to-end tests, it is whether anyone is still maintaining them in six months. This is for the flows nobody got round to covering, and for the ones that go red every time a button is renamed. When your UI changes, there is no selector to update — the agent looks at the page again and works it out.
There is no test code to maintain, because there is no test code. You describe what should work in a sentence, an agent works out how to do it in a real browser, and when your UI changes it works it out again instead of going red. The same agent knows which actions your app has, so it also keeps your analytics tracking correct — the two jobs are the same walk through your product.
We write tracking for Google Analytics, PostHog, Plausible, Mixpanel, Amplitude or Segment. To also watch those numbers and tell you when one stops, we need to read them, and today that means PostHog — or our own ingest, which is included.
say it, don't click it
The first two lines are the product: a sentence, a real browser, a verdict on the pull request. The rest is the instrumentation half — tools your own model calls by name once npx smolanalytics connect has wired it up — Cursor, Claude Code, VS Code, Windsurf, Claude Desktop or Cline, one command each. Nothing below drives a browser: the tests run from the terminal and from CI, and these read the repo, write the missing tracking calls in whichever SDK is already there, and prove they fire. Every report returns the real number or nothing, with a receipt naming the report behind it. Your model does the talking, so that part costs you nothing and there are no API keys to add.
what it costs
One plan. No tiers, no seats, no sales call.
what's live today
- npx smolanalytics test — a URL, a sentence, a verdict, with no account and nothing written to your repo
- an agent that drives a real browser from a test written as one English sentence
- the page read through its accessibility tree, so it picks an element and never a pixel coordinate
- a passing run recorded and replayed with zero model calls — 2.8 seconds for the one-step run published above
- a recording that no longer fits reported as stale, never as a bug, and re-run by the agent
- npx smolanalytics audit, free and with no account, reading whatever analytics you already run
- tracking calls written in your own SDK: PostHog, Mixpanel, Amplitude, Google Analytics, Segment or Plausible
- the pull request restoring a deleted tracking call, in whichever SDK it was deleted from, off by default twice over
- a finding you mark acted on, upgraded to verified only if the metric recovered after that date
- npx smolanalytics connect for cursor, claude code, vscode, windsurf, claude desktop and cline
not in the box
- per-pull-request preview environments — today the agent runs against a URL you give it (staging, a deploy preview, or localhost over a tunnel)
- writing the suite from your codebase — suggest drafts it from the running app instead, and you keep the sentences you agree with
- mobile apps: the agent drives web browsers only
- test data seeding — the agent uses whatever state the environment is already in
- does not replace PostHog, GA4, Amplitude or Plausible, and is not trying to
- PostHog is the only analytics we can read on a schedule; we write tracking for five more but cannot yet watch their numbers
- no video session replay
who built this
Arjun Varma. One person, and the only support there is. Email or DM, whichever you prefer, and you get me rather than a queue.