# Cairn

> Persistent ground truth for Claude Code. Stop AI agents from drifting on your codebase.

- **Type:** MCP server
- **Install:** `agentstack add mcp-isaacriehm-cairn`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [isaacriehm](https://agentstack.voostack.com/s/isaacriehm)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [isaacriehm](https://github.com/isaacriehm)
- **Source:** https://github.com/isaacriehm/cairn
- **Website:** https://github.com/isaacriehm/cairn

## Install

```sh
agentstack add mcp-isaacriehm-cairn
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Cairn

**Persistent ground truth for Claude Code.**
Stop AI agents from drifting.

[](https://www.npmjs.com/package/@isaacriehm/cairn)
[](https://claude.com/claude-code)
[](LICENSE)
[](https://nodejs.org)

```bash
/plugin marketplace add isaacriehm/cairn
/plugin install cairn@isaacriehm-cairn
/reload-plugins
```

[The Problem](#the-problem) · [What You Get](#what-you-get) · [Quick Start](#quick-start) · [Glossary](#glossary) · [How It Works](#how-it-works) · [Features](#features) · [Multi-Dev](#multi-developer-enforcement) · [Docs](#documentation)

---

A *cairn* is a stack of stones marking a trail. This project stacks the
**decisions, invariants, and canonical references** that define your
codebase into a single queryable ground state — so every Claude Code
session starts with the same map.

## The Problem

Monday: you tell Claude Code "auth tokens expire after 24 hours." It
ships. Works.

Friday, new session, new prompt. The agent reads `auth/tokens.ts`, sees
no comment about expiry, and "improves" the code to a 7-day refresh.
You catch it in review. Or you don't.

The model isn't bad. The model has **no memory of what you decided**.

A bigger context window doesn't fix this — it just delays it. What
fixes it is a structured record on disk that every session reads from
and writes to. Cairn is that record, plus the runtime that keeps it
load-bearing.

## What You Get

Three persistent stores, version-controlled in `.cairn/`:

🪨 **Decisions (`DEC-`)** — every architectural choice gets a
markdown file with rationale, scope, and a supersedes chain. Once
accepted, canonical until explicitly replaced. The agent reads the
in-scope decisions before touching the affected code.

```
DEC-a3f7b2c  Auth tokens expire after 24 hours
  Scope:       src/auth/**
  Rationale:   PCI compliance — short-lived bearer tokens
  Supersedes:  DEC-7c2f10a (7-day refresh, deprecated 2026-02-14)
```

🧭 **Invariants (`§INV-`)** — domain rules whose violation is a
bug, not a style preference. *"All API responses must include a
`request-id` header."* Sensors enforce them on every diff at
pre-commit and again at CI.

🗺️ **Canonical map** — `topic → file` index. Ask
`cairn_canonical_for_topic("rate limiting")` and get the actual file
paths instead of the agent grepping vaguely or fabricating them.

Plus four runtime layers that keep those stores live: an **MCP
server** (29 typed tools), a **Claude Code plugin** (skills + hooks +
reviewer agent), **sensors** (stub-catalog + decision-assertions), and
a **CLI** for bootstrap and debug.

## Quick Start

Inside Claude Code, in any project:

```bash
/plugin marketplace add isaacriehm/cairn
/plugin install cairn@isaacriehm-cairn
/reload-plugins
```

(First registers the GitHub repo as a marketplace; second installs the
plugin; third loads it. The plugin ships a self-contained bundle —
hooks, MCP server, and CLI all run from `dist/cli.mjs` inside the
plugin cache. No `npx`, no `npm install -g`, no PATH dependency.)

**Recommended:** disable Claude Code's built-in auto-memory before
adopting — Cairn is your memory layer and the two conflict:

```
/memory → Disable Auto-Memory
```

Open Claude Code in any project. The plugin auto-detects on session
start and offers `[a] adopt now`. Pick `[a]` once. The pipeline streams
inline so you watch what's happening — typically 2-15 minutes
depending on repo size.

When it finishes, your next session starts with the full ground state
preloaded.

If you want `cairn` directly on your shell PATH (for `cairn doctor`,
`cairn attention`, `cairn trace`, etc.):

```bash
npm install -g @isaacriehm/cairn
```

…but the plugin doesn't require it. Outside Claude Code, you can adopt
via CLI instead:

```bash
cairn init
```

## Glossary

Read this once and the rest of the doc reads cleanly.

| Term                | Means                                                                                                  |
| ------------------- | ------------------------------------------------------------------------------------------------------ |
| **DEC**             | Decision record — one architectural choice with rationale + scope + supersedes chain.                  |
| **§INV**            | Invariant — a domain rule the codebase must obey. Violations are bugs.                                 |
| **Scope**           | The file glob a DEC or §INV applies to (`src/auth/**`, `packages/billing/**`).                         |
| **Canonical map**   | `topic → file` index. The single source of truth for *"where does X live?"*                            |
| **Sensor**          | A mechanical check on a diff: stub patterns, decision violations.                                       |
| **Attestation**     | A subagent's signed-off summary of what changed and why; drives task auto-graduation.                  |
| **Drift**           | When code or docs disagree with the ground state in `.cairn/`.                                         |
| **Bypass**          | A commit that skipped Cairn's hooks (`--no-verify`, broken hook path). Detected and surfaced.          |
| **Attention queue** | The pile of DEC drafts, baseline findings, drift events, and conflicts waiting for operator review.    |
| **Tightener**       | The Sonnet-driven step that turns a vague prompt into a structured spec before dispatching subagents.  |

## How It Works

Two flows: **adoption** runs once when you onboard a repo. **Daily
flow** runs on every prompt thereafter.

### Adoption (one time)

A single visual pass with 13 phases. The plugin streams output
inline so nothing is opaque.

| Phase                | What happens                                                                                                            |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 1. Detect            | Probe environment + framework signals.                                                                                  |
| 2. Walk              | File manifest, extension stats, language detection.                                                                     |
| 3. Map               | Sonnet domain mapper proposes module boundaries + `scope-index.yaml` globs.                                             |
| 4. Seed              | Write `.cairn/` skeleton, `config.yaml`, grandfather pre-adoption commits into `.attested-commits`.                     |
| 5. Pilot             | Operator picks a seed module from the mapper's top-3 candidates (one A/B/C question).                                   |
| 6. Brand             | Auto-fill brand / voice / product DEC drafts from the mapper's domain summary (one A/B/C).                              |
| 7. Topic index      | Content-fingerprint pre-pass — dedupes facts that appear across docs, source, and rules before drafting DECs.           |
| 8, 9, 10 (parallel) | **Docs ingest** + **Source comments ingest** + **Rules merge** (`CLAUDE.md` / `AGENTS.md`) — all Haiku-batched.         |
| 11. Baseline         | First sensor sweep against a synthetic full-tree diff. Findings written to `.cairn/baseline/`.                           |
| 12. Strip            | Per-module strip-replace consent — operator chooses keep / strip / skip for each flagged module.                         |
| 13. Multi-dev        | Detects package manager, installs git hooks, emits `JOIN.md` for new contributors.                                       |

After the pipeline finishes, recorded decisions auto-accept into the
ledger (the review checkpoint is the committed diff). The
**`cairn-attention` skill** drains what's left — baseline sensor
findings, drift events, and any dedup-fallback drafts — interactively.

### Daily flow

```
You type a prompt
        │
        ▼
┌────────────────────────────────────────────────┐
│  Plugin auto-invokes the cairn-direction skill │
│   1. Skill loads in-scope DECs, §INVs,         │
│      and canonical-map entries via MCP         │
│   2. Main Claude classifies prompt readiness   │
│   3. If unclear → inline A/B/C questions       │
│   4. If ready → tightens spec inline, writes   │
│      .cairn/tasks/active//spec.tightened.md│
│   5. Spec dispatched to subagents              │
└────────────────┬───────────────────────────────┘
                 ▼
   Subagents work in your repo with MCP access:
     cairn_decisions_in_scope, cairn_invariant_get,
     cairn_canonical_for_topic, cairn_search, …
                 │
                 ▼
   Reviewer subagent attests the diff,
   extracts non-obvious decisions as DEC drafts
                 │
                 ▼
   Stop hook surfaces inline:
     "Review DEC-b1e9c04 draft? [a] accept [b] reject [c] edit"
                 │
                 ▼
   You commit → pre-commit hook runs sensors
              → CI gate verifies again on PR
              → drift caught before merge
```

The key bit: **the agent never starts cold.** Every prompt enters
with the relevant decisions, invariants, and canonical references
already loaded into the spec.

## Features

### Memory + ground state

- **Persistent decisions / invariants / canonical map** in
  version-controlled `.cairn/`.
- **Component registry** — every component file carries a structured
  `@cairn ` header; the agent loads the full in-scope
  inventory before any UI work and follows USE > EXTEND > CREATE so it
  never rebuilds a component that already exists. A check gate blocks
  missing headers / duplicate names; an advisory audit flags probable
  inline rebuilds.
- **Supersedes chains** — old decisions stay readable but flagged
  superseded; the chain is queryable via `cairn_supersedes_chain`.
- **Scope-aware preload** — the SessionStart hook injects only the
  DECs / §INVs that apply to files you've recently touched, instead
  of dumping the whole ledger into context.

### Adoption

- **Single visual pass** — operator watches the pipeline stream
  inline. No opaque background job.
- **Haiku-batched classification** — docs, source comments, and
  rules are ingested in parallel for speed.
- **Conflict detection** — when two sources disagree, surfaces a
  side-by-side resolution prompt instead of silently picking one.
- **Topic-index dedup** — content fingerprints prevent the same fact
  landing as three separate DEC drafts.
- **Component-store backfill** — projects adopted before the component
  store shipped add it in one pass: the `cairn-adopt-components` skill
  detects the config, dispatches `component-annotator` subagents to write
  `@cairn` headers, and builds the index + singleton §INVs. No manual
  header-writing — just ask the agent to adopt the component store.

### Daily flow

- **`cairn-direction` skill** — auto-tightens vague prompts (*"fix
  the bug"*) into structured specs before dispatch. Loads the
  in-scope DECs, §INVs, and canonical-map entries automatically.
- **`cairn-attention` skill** — drains the queue of dedup-fallback
  DEC drafts, baseline sensor findings, and drift events
  interactively (decisions auto-accept; review rides the diff).
- **Reviewer subagent** — every multi-chunk task ends with the
  reviewer attesting the diff and extracting non-obvious decisions
  into DEC drafts.
- **Status-line badge** — `⬡ cairn` in the Claude Code status row
  shows pending attention count, bypass warnings, GC state, and the
  active task title. Color-codes by absolute token usage.
- **Session trace log** — `cairn trace` pretty-prints unified
  per-session events. `--tail`, `--errors-only`, `--session`,
  `--json` flags supported.

### Sensors

| Sensor                  | What it checks                                                                       |
| ----------------------- | ----------------------------------------------------------------------------------- |
| **Stub-pattern catalog** | Regex catalog of incomplete-impl markers (TODO throws, not-implemented, …) over the diff. |
| **Decision-assertions** | Was the in-scope DEC honored? Machine-readable assertions evaluated against the changed tree. |
| **Structural**          | Route handlers non-empty; DTOs carry real validators (no `@IsOptional()`-only fields). |

The sweep runs as a real gate at **pre-commit** (`cairn sensor-run
--staged`, blocks on hard findings) and at **CI** (`cairn sensor-run
--diff  --strict`). Live SoT alignment runs separately on every
PostToolUse Write/Edit. The Stop hook surfaces task / GC / attention
state — it does **not** run the sensor sweep. Drift events log to
`.cairn/staleness/log.jsonl` and surface on the next GC sweep.

### Tooling surfaces

- **MCP server** — 32 typed tools across read, write, history,
  attention, init, and search. Used by the plugin and any other MCP
  client.
- **CLI** — `cairn init / join / mcp / gc / scope / doctor / fix /
  migrate / attention / align / baseline / hook / sensor-run / tag /
  trace / status-line`.
- **Claude Code plugin** — manifest + 5 hook events (SessionStart,
  SessionEnd, Stop, UserPromptSubmit, PostToolUse — matchers
  Read, Write|Edit, AskUserQuestion) + 3 skills + 1 reviewer agent +
  3 commands.
- **Cairn Lens** — VS Code / Cursor extension. Hover, gutter icons,
  code lens, optional DEC Explorer sidebar. Resolves `§INV-`,
  `§DEC-`, `TODO(TSK-…)` inline. Read-only — same ground state,
  no separate index.

## Editor Extension — Cairn Lens

Hover, ghost text, gutter icons, code lens — all resolved live from
`.cairn/ground/` ledgers. Read-only. Hovering a `@cairn` component
header shows its registry entry (`[S]` singleton; amber drift when the
header name ≠ the exported name).

| Status      | Meaning                       |
| ----------- | ----------------------------- |
| `●` (green) | Active invariant              |
| `◐` (amber) | Superseded — see chain        |
| `○` (red)   | Orphan — not in ledger        |

Install the latest `.vsix` from
[releases](https://github.com/isaacriehm/cairn/releases) →
`Cmd/Ctrl+Shift+P` → `Extensions: Install from VSIX…`. Full setup in
[`packages/cairn-lens/README.md`](packages/cairn-lens/README.md). Because
the `.vsix` is not on the Marketplace, Cairn Lens checks npm once a day
and notifies you when a newer release is published (disable via
`cairn.lens.checkForUpdates`).

## Multi-Developer Enforcement

Once a project is Cairn-adopted, every developer runs Cairn — locally
and at PR time. **Defense in depth:**

| Layer                         | What                                                          | Catches                                                     |
| ----------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------- |
| **1. Versioned git hooks**    | `.cairn/git-hooks/{pre,post,commit-msg}-commit`               | Local commits violating ground state.                       |
| **2. `cairn join` bootstrap** | CLI + `package.json prepare` script                           | Clones that haven't activated `core.hooksPath`.             |
| **3. CI gate**                | `.github/workflows/cairn-check.yml`                           | `--no-verify` slipping through. **Non-bypassable.**         |
| **4. Plugin degraded mode**   | SessionStart banner + MCP guard                               | Write tools refuse with `BOOTSTRAP_REQUIRED` until joined.  |

Plus **Stop-hook bypass detection** — flags any HEAD commits not in
`.cairn/.attested-commits` and surfaces `[a] backfill / [b] accept
(record DEC) / [c] defer`.

## Disk Layout

After `cairn init`:

```
.cairn/
├── config.yaml                  slug, version, off_limits, domain
├── config/                      workflow.md, sensors.yaml, stub-patterns.yaml
├── ground/
│   ├── decisions/               DEC-.md per choice + _inbox/.draft.md
│   ├── invariants/              INV-.md per §V rule
│   ├── canonical-map/           topic → file index
│   ├── components/              derived @cairn inventory (gitignored; rebuil

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [isaacriehm](https://github.com/isaacriehm)
- **Source:** [isaacriehm/cairn](https://github.com/isaacriehm/cairn)
- **License:** MIT
- **Homepage:** https://github.com/isaacriehm/cairn

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-isaacriehm-cairn
- Seller: https://agentstack.voostack.com/s/isaacriehm
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
