cairnpm/cairn

Self-hosted PM agent that turns a scattered stream of feedback into a roadmap you can reason about — Shape Up, code-aware, bring your own LLM key.

3

stars

112

commits

TypeScript

primary language

Aug 25, 2026

updated

cairnpm.com
ai-agent
claude
llm
nuxt
product-management
product-os
roadmap
self-hosted
shape-up
sqlite
typescript
vue

README

Cairn

Cairn

The hard part of building software moved from how to what.
Cairn is the PM agent that turns a dense, scattered stream of feedback into a roadmap you can actually reason about — open, self-hosted, built on Shape Up.

cairnpm.com · Self-host · Roadmap · How the agent works · Contributing

License: FSL-1.1-ALv2 Nuxt 4 Self-hosted PRs welcome

Cairn intake


Why Cairn?

AI made shipping cheap: how to build something is no longer the bottleneck. The scarce skill now is deciding what to build — and in what order — in a roadmap that fills up faster than anyone can read it. Cairn is built for that exact moment: an agent does the sorting (read, deduplicate, shape, route) so your judgment goes to the decision, not the pile.

  • 🪨 An agent, not a form. Paste a Slack thread, a bug report, or a whole meeting transcript. The intake agent extracts the distinct signals, recontextualizes each one, deduplicates against the backlog, and proposes where it belongs — you confirm. Writing only ever happens on confirmation.
  • 🔍 Grounded in your real code. Link your product repo (read-only GitHub App or a local path) and the agent checks what's actually shipped before it shapes: it dedupes against reality — citing file:line, not a stale ticket — grounds each pitch in the real architecture, and answers "is X built yet?" by reconciling the roadmap with the code. Zero-egress: the repo is grepped locally, never sent anywhere.
  • 🧗 Shape Up, natively. Pitches with a real problem and an appetite, a betting table to choose what's worth doing, hills to track in-flight work, frozen scope once a bet is placed, and a circuit breaker when a bet doesn't ship — it goes back to the pool to be re-defended, never silently extended. The method is the product, not a template.
  • 🧹 Anti feature-factory. No artificial caps, no vanity metrics. The backlog is meant to stay small: duplicates get merged, noise gets discarded, shaping is a discipline — not a place where requests go to die.
  • 🔌 Bring your own LLM key. The agent runs on your Anthropic key. No data detour through us — there is no "us" in the loop.
  • 🏠 Self-hosted, you own the data. One Node process, one embedded SQLite file. No external database, no telemetry, no account on someone else's server.
  • 🔓 Source-available. Read every line, audit it, run it for free forever. It even becomes Apache-2.0 over time (see License).

What's inside

IntakeConversational agent: triage → clarify → propose → commit. Reads .docx/images, splits transcripts into N features, dedupes, attributes every change.
Code-awareLink the product repo; the intake greps it to dedupe against what's shipped and ground specs. Read-only, zero-egress — GitHub App (short-lived tokens, self-host manifest flow) or a local clone.
BacklogShaped features with problem · appetite · solution · rabbit holes · no-gos. Manually-assigned shapers.
Betting tableCollaborative deliberation: members vote, the owner validates → it bets features and opens a hill.
HillsIn-flight cycles with builders, periods and frozen scope.
ExecutionProgress reported by hand (bet ⇄ building → done) or by a merged PR, plus Shape Up's circuit breaker: a bet that didn't ship leaves the cycle and must be re-defended.
WorkspaceEmail + password auth, token invitations, roles, avatars, full attribution/audit trail.

Get started (self-host)

Cairn is a single container backed by an embedded SQLite file — no external database. Bring an Anthropic API key (or add it later in the UI) and a place to keep /data. Pick whichever fits:

One-click on Render:

Deploy to Render

Docker Compose (recommended for your own server):

git clone https://github.com/cairnpm/cairn && cd cairn
cp .env.example .env        # set NUXT_SESSION_PASSWORD (and your Anthropic key)
docker compose up -d        # → http://localhost:3000

Also supported — Fly.io, plain Docker, backups and env vars: see DEPLOY.md. Prebuilt images are published to ghcr.io/cairnpm/cairn (:latest = newest tagged release, :main = HEAD of main).

Staying up to date. Settings → Workspace → Version shows the version you run and whether a newer release exists, with the update command for your host — one anonymous GET to the GitHub releases API, nothing sent, switchable off. Commands per host: DEPLOY.md § Updating. Back up first with node bin/backup.mjs — a consistent VACUUM INTO snapshot of the live database (§ Backups).

First boot creates a single owner account — ceo@cairn.local / cairn — change the password right away. The workspace starts empty; set CAIRN_SEED_DEMO=1 to load a demo backlog/hills/team for a tour.

Develop locally

pnpm install
echo 'ANTHROPIC_API_KEY=sk-ant-…' > .env
pnpm dev            # http://localhost:3000
pnpm test:members   # hermetic auth/invitations test suite

Drive it from an agent (CLI)

cairn is a thin HTTP client over the running server, so an agent can ground itself on the roadmap and feed signal into the intake — no second write path.

export CAIRN_URL=http://localhost:3000
export CAIRN_EMAIL=agent@your-workspace   # use a DEDICATED, least-privilege account:
export CAIRN_PASSWORD=…                    # the cached session can hit any endpoint it's a member of

pnpm exec cairn features --status shaping  # reads: features / feature <id> / hills / betting / overview
pnpm exec cairn capture "les users veulent le mode sombre"   # → {session_id, state, agent_message, proposal}
pnpm exec cairn capture --session <id> "priorité haute"      # answer a clarify turn
pnpm exec cairn commit --session <id>                        # finalise a single proposal
pnpm exec cairn commit-batch --session <id> --segments a,b   # finalise a decomposed (batch_review) capture

Output is JSON by default (--pretty for humans). The session cookie is cached in ./.cairn/ relative to the working directory — run from the workspace root. The command surface is a closed allowlist (reads + intake); it's an agent guardrail, not a security boundary — a real boundary is the account's own permissions.

Why source-available and not "free for everyone"?

Cairn is free to run, read, modify and self-host — for any purpose except re-selling it as a competing hosted product. That single restriction is what lets a small team keep building it in the open instead of behind a closed door.

It's licensed under the Functional Source License (FSL-1.1-ALv2): two years after each release, that version automatically becomes Apache-2.0. So the protection is temporary and the openness is permanent — you're never locked out of your own infrastructure, and our infra is never in your critical path.

Today everything is free and self-hostable. Team/organisation capabilities (SSO, multi-workspace, advanced integrations) may later require a license key — the core always runs without one. See the roadmap.

Tech

  • Nuxt 4 (Vue 3) + Nitro — SSR app and single write gateway
  • node:sqlite — embedded database, zero native deps
  • shadcn-vue + Tailwind v4 — dark, calm UI
  • Anthropic Claude via a thin provider interface (swap-able; deterministic offline fallback)

Contributing

Issues and PRs are welcome — see CONTRIBUTING.md for the setup, commit convention and how routing decisions are tested. Be kind; assume good intent.

License

FSL-1.1-ALv2 — source-available now, Apache-2.0 two years after each release. © 2026 The Cairn Authors. "Cairn" and the logo are trademarks and are not covered by the code license.

Contributors

jrpersico

111 commits

DnzzL

1 commits

cairnpm/cairn

Self-hosted PM agent that turns a scattered stream of feedback into a roadmap you can reason about — Shape Up, code-aware, bring your own LLM key.

3

stars

112

commits

TypeScript

primary language

Aug 25, 2026

updated

cairnpm.com
ai-agent
claude
llm
nuxt
product-management
product-os
roadmap
self-hosted
shape-up
sqlite
typescript
vue

README

Cairn

Cairn

The hard part of building software moved from how to what.
Cairn is the PM agent that turns a dense, scattered stream of feedback into a roadmap you can actually reason about — open, self-hosted, built on Shape Up.

cairnpm.com · Self-host · Roadmap · How the agent works · Contributing

License: FSL-1.1-ALv2 Nuxt 4 Self-hosted PRs welcome

Cairn intake


Why Cairn?

AI made shipping cheap: how to build something is no longer the bottleneck. The scarce skill now is deciding what to build — and in what order — in a roadmap that fills up faster than anyone can read it. Cairn is built for that exact moment: an agent does the sorting (read, deduplicate, shape, route) so your judgment goes to the decision, not the pile.

  • 🪨 An agent, not a form. Paste a Slack thread, a bug report, or a whole meeting transcript. The intake agent extracts the distinct signals, recontextualizes each one, deduplicates against the backlog, and proposes where it belongs — you confirm. Writing only ever happens on confirmation.
  • 🔍 Grounded in your real code. Link your product repo (read-only GitHub App or a local path) and the agent checks what's actually shipped before it shapes: it dedupes against reality — citing file:line, not a stale ticket — grounds each pitch in the real architecture, and answers "is X built yet?" by reconciling the roadmap with the code. Zero-egress: the repo is grepped locally, never sent anywhere.
  • 🧗 Shape Up, natively. Pitches with a real problem and an appetite, a betting table to choose what's worth doing, hills to track in-flight work, frozen scope once a bet is placed, and a circuit breaker when a bet doesn't ship — it goes back to the pool to be re-defended, never silently extended. The method is the product, not a template.
  • 🧹 Anti feature-factory. No artificial caps, no vanity metrics. The backlog is meant to stay small: duplicates get merged, noise gets discarded, shaping is a discipline — not a place where requests go to die.
  • 🔌 Bring your own LLM key. The agent runs on your Anthropic key. No data detour through us — there is no "us" in the loop.
  • 🏠 Self-hosted, you own the data. One Node process, one embedded SQLite file. No external database, no telemetry, no account on someone else's server.
  • 🔓 Source-available. Read every line, audit it, run it for free forever. It even becomes Apache-2.0 over time (see License).

What's inside

IntakeConversational agent: triage → clarify → propose → commit. Reads .docx/images, splits transcripts into N features, dedupes, attributes every change.
Code-awareLink the product repo; the intake greps it to dedupe against what's shipped and ground specs. Read-only, zero-egress — GitHub App (short-lived tokens, self-host manifest flow) or a local clone.
BacklogShaped features with problem · appetite · solution · rabbit holes · no-gos. Manually-assigned shapers.
Betting tableCollaborative deliberation: members vote, the owner validates → it bets features and opens a hill.
HillsIn-flight cycles with builders, periods and frozen scope.
ExecutionProgress reported by hand (bet ⇄ building → done) or by a merged PR, plus Shape Up's circuit breaker: a bet that didn't ship leaves the cycle and must be re-defended.
WorkspaceEmail + password auth, token invitations, roles, avatars, full attribution/audit trail.

Get started (self-host)

Cairn is a single container backed by an embedded SQLite file — no external database. Bring an Anthropic API key (or add it later in the UI) and a place to keep /data. Pick whichever fits:

One-click on Render:

Deploy to Render

Docker Compose (recommended for your own server):

git clone https://github.com/cairnpm/cairn && cd cairn
cp .env.example .env        # set NUXT_SESSION_PASSWORD (and your Anthropic key)
docker compose up -d        # → http://localhost:3000

Also supported — Fly.io, plain Docker, backups and env vars: see DEPLOY.md. Prebuilt images are published to ghcr.io/cairnpm/cairn (:latest = newest tagged release, :main = HEAD of main).

Staying up to date. Settings → Workspace → Version shows the version you run and whether a newer release exists, with the update command for your host — one anonymous GET to the GitHub releases API, nothing sent, switchable off. Commands per host: DEPLOY.md § Updating. Back up first with node bin/backup.mjs — a consistent VACUUM INTO snapshot of the live database (§ Backups).

First boot creates a single owner account — ceo@cairn.local / cairn — change the password right away. The workspace starts empty; set CAIRN_SEED_DEMO=1 to load a demo backlog/hills/team for a tour.

Develop locally

pnpm install
echo 'ANTHROPIC_API_KEY=sk-ant-…' > .env
pnpm dev            # http://localhost:3000
pnpm test:members   # hermetic auth/invitations test suite

Drive it from an agent (CLI)

cairn is a thin HTTP client over the running server, so an agent can ground itself on the roadmap and feed signal into the intake — no second write path.

export CAIRN_URL=http://localhost:3000
export CAIRN_EMAIL=agent@your-workspace   # use a DEDICATED, least-privilege account:
export CAIRN_PASSWORD=…                    # the cached session can hit any endpoint it's a member of

pnpm exec cairn features --status shaping  # reads: features / feature <id> / hills / betting / overview
pnpm exec cairn capture "les users veulent le mode sombre"   # → {session_id, state, agent_message, proposal}
pnpm exec cairn capture --session <id> "priorité haute"      # answer a clarify turn
pnpm exec cairn commit --session <id>                        # finalise a single proposal
pnpm exec cairn commit-batch --session <id> --segments a,b   # finalise a decomposed (batch_review) capture

Output is JSON by default (--pretty for humans). The session cookie is cached in ./.cairn/ relative to the working directory — run from the workspace root. The command surface is a closed allowlist (reads + intake); it's an agent guardrail, not a security boundary — a real boundary is the account's own permissions.

Why source-available and not "free for everyone"?

Cairn is free to run, read, modify and self-host — for any purpose except re-selling it as a competing hosted product. That single restriction is what lets a small team keep building it in the open instead of behind a closed door.

It's licensed under the Functional Source License (FSL-1.1-ALv2): two years after each release, that version automatically becomes Apache-2.0. So the protection is temporary and the openness is permanent — you're never locked out of your own infrastructure, and our infra is never in your critical path.

Today everything is free and self-hostable. Team/organisation capabilities (SSO, multi-workspace, advanced integrations) may later require a license key — the core always runs without one. See the roadmap.

Tech

  • Nuxt 4 (Vue 3) + Nitro — SSR app and single write gateway
  • node:sqlite — embedded database, zero native deps
  • shadcn-vue + Tailwind v4 — dark, calm UI
  • Anthropic Claude via a thin provider interface (swap-able; deterministic offline fallback)

Contributing

Issues and PRs are welcome — see CONTRIBUTING.md for the setup, commit convention and how routing decisions are tested. Be kind; assume good intent.

License

FSL-1.1-ALv2 — source-available now, Apache-2.0 two years after each release. © 2026 The Cairn Authors. "Cairn" and the logo are trademarks and are not covered by the code license.

Contributors

jrpersico

111 commits

DnzzL

1 commits

Languages

TypeScript

58.0%

Vue

39.5%

JavaScript

1.5%