Local dev mode (cairn dev)
Run Cairn against a local repo on your machine — no GitHub App, no login, no cloud. Map flows, generate Playwright tests, run them against your local dev server, and watch which flows your edits affect, all from one command.
Think of it as a live E2E watcher for your dev loop, not the SaaS running offline.
Prerequisites
Before you run it, have these ready:
- Docker running (the CLI starts a throwaway Postgres) — or your own
DATABASE_URL - Node 20+
- A Gemini API key (
GOOGLE_GENERATIVE_AI_API_KEY) — for mapping + test generation - Your app running on a localhost port (that's the
--target)
One command
No clone — run it straight from npm, in the folder of the app you want to test:
export GOOGLE_GENERATIVE_AI_API_KEY=AIza...
npx cairn-dev dev --target http://localhost:3000 --port 4000
Working inside a Cairn checkout instead? Use the workspace CLI:
pnpm cairn dev --path ~/my-app --target http://localhost:3000 --port 4000
| Flag | Meaning | Default |
|---|---|---|
--path | the repo to map (reads its source from disk) | current directory |
--target | your running dev server to test against | http://localhost:3000 |
--port | the local dashboard port | 3000 |
cairn dev provisions a local Postgres (a Docker container, or your
DATABASE_URL), applies the schema, seeds the local repo, then runs the Inngest
dev server + worker + web in local mode and opens the dashboard at
http://localhost:<port>/local. Ctrl+C tears it all down.
What you get
- Flow mapping from local source — Cairn reads your working directory (no GitHub API), maps user flows, and generates self-contained Playwright specs.
- Runs against
localhost— tests execute against your--targetdev server, with video + trace, just like the cloud runner. - Watch mode — save a file and the flows it affects light up instantly in the dashboard ("affected by your last edit"). This is a free, no-LLM signal.
What's different from the cloud
Local mode never touches GitHub, so the GitHub-only features are adapted:
| Cloud | Local |
|---|---|
| Login with GitHub | No login — single local user |
| Files GitHub issues on failure | Creates the issue in the dashboard only (not filed to GitHub) |
| Auto-fix opens a PR | Off (auto-fix needs a GitHub PR) |
| Runs on merge / schedule / webhooks | Manual + watch mode |
Everything else — mapping, generation, running, video/trace, the dashboard — is the same code as the cloud product.
Graduating to the cloud — connect, push, pull
When you're happy with the flows and tests you built locally, you can port them
into a cloud Cairn account so they run on PRs and on a schedule — without
regenerating anything. It works like git's remote model: connect once, then
push / pull freely.
1. connect — link the repo (and get your token + repo id)
npx cairn-dev connect
connect opens your browser to sign in (or sign up) at
https://cairn.vela.partners, matches this repo to one you've connected via the
GitHub App (by its git remote — the local repo name must match), and then
saves the credentials to .cairn/connection.json:
{
"apiUrl": "https://cairn.vela.partners",
"token": "<a repo-scoped API token, minted for you>",
"cloudRepoId": "<the cloud repo id>",
"repo": "your-org/your-repo"
}
That's the whole point of connect: it obtains the token and cloud repo
id automatically so you never have to generate them by hand. push and pull
read this file — no re-auth each time.
Repo not connected yet?
connectlinks you to the GitHub App install page. Install Cairn on the repo, then re-runconnect.
2. push — send local flows up
npx cairn-dev push # add new flows only
npx cairn-dev push --overwrite # also update flows that already exist
Pushed flows land staged for review in the cloud — they don't run until you
approve them. Open the repo in the cloud dashboard and use the "imported —
review & approve" banner (Approve all, or per-flow). Flows are de-duplicated by
name, so re-pushing after a re-map never creates duplicates; any that already
existed are reported by name (and you can re-run with --overwrite, or use the
Replace with local / Keep cloud conflict banner in the dashboard).
3. pull — bring cloud flows down
npx cairn-dev pull # add new flows only
npx cairn-dev pull --overwrite # also replace local copies
The reverse of push: it fetches the cloud repo's flows + tests into your
running local instance so you can keep iterating locally after the cloud has
changed.
Doing it from the UI instead
The /local cockpit has Push and Pull buttons (top-right) that open the
same flow as dialogs. The manual dialog asks for a Cloud URL, a Repo API
token, and a Cloud repo id — these are exactly the values connect already
saved to .cairn/connection.json, so you can copy token and cloudRepoId from
there. (Or generate a fresh repo API token in the cloud dashboard.) The CLI path
fills them in for you, so the dialog is mainly a manual fallback.
Needs the cloud side live:
connect/push/pulltalk tohttps://cairn.vela.partners(override with--api-url), so the repo must be connected there via the GitHub App.
Fixing failures with a coding agent (Claude Code)
Local mode closes the loop with the agent already in your repo. When a flow
fails, Cairn writes a structured .cairn/failures.json (and a readable
.cairn/failures.md) — the flow, the error, the source files it touches, the
generated test, and recent output. Two ways to use it:
1. File handoff (works with any agent). Just tell Claude Code:
"Read
.cairn/failures.jsonand fix the failing flow."
2. MCP server (hands-free loop). Add Cairn's MCP server to Claude Code once
and the agent drives the whole loop — get_failures → edit code → run_flow to
verify → repeat. In your repo's .mcp.json:
{
"mcpServers": {
"cairn": {
"command": "node",
"args": ["/path/to/cairn/packages/mcp/bin/cairn-mcp.mjs"]
}
}
}
Then, with cairn dev running: "Run my Cairn flows and fix any that fail."
The server reads .cairn/local.json to reach the running instance. Tools:
get_failures, list_flows, get_test_source, run_flow.
The same server also works against cloud Cairn (read-only) — set
CAIRN_API_URL, CAIRN_API_TOKEN (a repo API token), and CAIRN_REPO_ID in the
MCP env, and get_failures returns your open failure issues. See
packages/mcp/README.md.
Notes
npx cairn-dev(no clone) is the recommended way to run it — it pulls the publishedcairn-web/cairn-workerDocker images and runs the whole stack. Working inside a Cairn checkout instead? Use the workspace CLI:pnpm cairn dev --path <your repo>.- Local state lives in a Postgres you own (or the Docker container); it's
separate from any cloud instance. Use
connect+pushto move it to the cloud (see above).