Cairn

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
FlagMeaningDefault
--paththe repo to map (reads its source from disk)current directory
--targetyour running dev server to test againsthttp://localhost:3000
--portthe local dashboard port3000

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 --target dev 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:

CloudLocal
Login with GitHubNo login — single local user
Files GitHub issues on failureCreates the issue in the dashboard only (not filed to GitHub)
Auto-fix opens a PROff (auto-fix needs a GitHub PR)
Runs on merge / schedule / webhooksManual + 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.

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? connect links you to the GitHub App install page. Install Cairn on the repo, then re-run connect.

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 / pull talk to https://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.json and 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 published cairn-web / cairn-worker Docker 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 + push to move it to the cloud (see above).