Change the route without moving the finish line.
A contract hash covers intent + outcomes. Healing can rewrite drifted steps, but it cannot silently weaken what the spec promises.
sha256:98b7…4a21verifiedBrowser acceptance tests for AI coding agents
Cairntrace turns what a feature should do into a YAML spec, replays it in a real browser, and hands your agent a failure report it can fix. Heal the path, never the promise.
Works with Claude Code · Cursor · Codex · OpenCode
Install
brew install abdul-hamid-achik/tap/cairntracecairn doctorNeeds Bun 1.3+ (Homebrew installs it) · browser: agent-browser or Playwright
Open source · MIT licensed · View on GitHub · Build from source
version: 1
name: dashboard_nav
intent: from the home page, follow "Open dashboard" and land on a working dashboard
outcomes:
- id: url_is_dashboard
verify:
url: { endsWith: /dashboard.html }
- id: dashboard_heading_visible
verify:
text: { contains: Dashboard }
- id: no_console_errors
verify:
console: { errorsMax: 0 }
steps:
- id: open_home
open: http://localhost:8787/
- id: click_open_dashboard
click: { by: role, role: link, name: Open dashboard }
- id: wait_for_dashboard
wait: { text: Dashboard, timeoutMs: 5000 }The missing acceptance layer
Coding agents can change the code, run unit tests, and still miss a broken checkout, an empty dashboard, or a button that no longer responds. Cairntrace moves the final check into the browser and makes its result legible to the next agent.
Read the contract-first authoring guideintent + outcomes define what success means.
steps are executable hints, not the contract itself.
Reports, snapshots, console, network, and outcome files.
A tighter agent loop
Cairntrace gives the agent a deterministic route from product intent to browser evidence without coupling the spec to one model or one test runner.
Write the intent and typed observables before scripting the clicks.
cairn spec verify flows/checkout.yml --stampUse a login action, checkpoint, or deterministic precondition for cold-start replay.
cairn run flows/checkout.yml --cold-start --jsonRead the focused agent context, inspect the evidence, and repair only the path.
cairn context latestConnect your agent
Cairntrace runs as a stdio MCP server started with cairn mcp. Register it once in your harness, then have the agent call cairn_doctor to verify the setup, then cairn_explain once to read the tool surface.
run in your terminal
claude mcp add cairntrace -- cairn mcpBuilt for work that survives the demo
Human-readable contracts at authoring time. Stable machine-readable output at run time. Rich evidence when the browser disagrees.
A contract hash covers intent + outcomes. Healing can rewrite drifted steps, but it cannot silently weaken what the spec promises.
sha256:98b7…4a21verifiedCLI commands support JSON, YAML, and Markdown. MCP tools mirror the same surface, so any capable coding agent can author, run, and read the same spec.
Beyond the click
Outcomes can read the backend, not only the page. Fixtures, services, suites, and runners are declared in cairntrace.config.yml, next to your specs.
mongo, temporal, http, and xlsx outcomes check the data behind the UI.
Fixtures create test data before a run and tear it down after.
FixturesPick a suite with --suite, set bail and preflight rules, and hold the run on readiness gates while services start and tear down with it.
Hand cairn run to a command you provide. The local process keeps the journal, run directories, and exit code.
Emit @playwright/test files from a spec. --verify checks the export before you rely on it.
How it differs
Ad-hoc agent browsing is fast to start. Hand-written Playwright is mature. Cairntrace keeps the check as a spec the agent can run and repair.
| Criterion | Ad-hoc agent + browser MCP | Hand-written Playwright | Cairntrace |
|---|---|---|---|
| Survives the session | No. Steps live in the chat. | Yes. Test files in the repo. | Yes. YAML spec in the repo. |
| Fixed definition of done | Whatever the agent decides it is. | Yes. The assertions you wrote. | Yes. Intent and outcomes, covered by a contract hash. |
| Agent-readable failure evidence | Screenshots and logs the agent has to interpret. | Traces and reports built for people. | Start with agent_context.md, then outcomes, snapshots, and console. |
| Drift repair | Re-explore the page each time. | Edit the test by hand. | Heal proposes step changes. The contract hash blocks changes to outcomes. |
| Exports to Playwright | No. | Native. | cairn export playwright, with --verify. |
Playwright wins on ecosystem, maturity, and CI adoption. Cairntrace can use Playwright as its browser backend, and it can export to Playwright when a conventional test is the better home. Full comparison
From agent loop to CI
--cold-start clears the browser profile first, so a pass does not depend on leftover state. --junit writes a report your CI can read. Exit codes tell the job what happened.
# cairn is installed earlier in the job (see /ci)
- name: Browser acceptance
run: cairn run --suite <name> --cold-start --junit cairn-junit.xmlUse it where confidence is expensive
Cairntrace fits the moment between “the code compiles” and “ship it.” Keep the spec beside the feature, let the agent run it while working, and preserve the evidence for review or CI.
Verify the user-visible outcome before the task is called complete.
Cover login, checkout, imports, dashboards, and multi-step operations.
Compare the browser state and patch locator drift without rewriting intent.
Open a self-contained report instead of reconstructing the run from raw logs.
Questions, answered
Still evaluating the fit? The docs stay concrete and the repository is public.
Inspect the source on GitHubCairntrace is a local-first behavioral browser-spec layer for coding agents. A YAML spec defines the product intent, the observable outcomes, and a repairable sequence of browser steps.
No. Cairntrace adds a contract and agent-readable evidence layer. It can use Playwright as a backend and export stable specs to Playwright when conventional CI tests are the better destination.
Any agent that can call a CLI or MCP server can use the same Cairntrace surface. There are no product-specific branches for Codex, Claude Code, Cursor, or OpenCode.
Yes, Bun 1.3.0 or newer (engines.bun in package.json). Homebrew installs it as a dependency. npm and bun installs need Bun on your PATH.
Yes. --cold-start is on by default in CI, --junit writes JUnit XML, and cairn run exits with documented codes. The CI recipe is on /ci.
It runs over stdio. Shell hooks and service starts (docker, seed, tmux) are refused until you opt in with --allow-hooks or --allow-services, or the matching CAIRN_MCP_ALLOW_* environment variable.
Playwright MCP gives the agent a browser to drive. Cairntrace is a spec format and a runner on top of a browser (agent-browser by default, or Playwright). Use a browser MCP to explore. Use Cairntrace to keep the check and its evidence.
The install docs cover macOS and Linux (Homebrew, npm, bun, and the curl installer). Windows is not documented as supported.
The CLI does not import an analytics SDK or send usage data. Runs write browser state and artifacts locally. Network calls come from what you configure or invoke, such as your app, datasources, or cairn publish. This website uses Vercel Analytics for page views and CTA clicks.
MIT. There is no Cairntrace account. Local runs use your files and your browser. Checkpoints that hold app logins are created by you with cairn login.
The browser gets the final word
Install Cairntrace, run cairn doctor, and give your next coding task a browser contract.
brew install abdul-hamid-achik/tap/cairntrace