/cairn-adopt
One-time Cairn adoption pipeline for a new project.
$ npx -y skills add isaacriehm/cairn --skill cairn-adopt --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/cairn-adopt
Context preview
The summary Claude sees to decide when to auto-load this skill.
One-time Cairn adoption pipeline for a new project.
SKILL.md
cairn-adopt.SKILL.mdname: cairn-adopt
description: One-time Cairn adoption pipeline for a new project.
when_to_use: |
Use when operator opens a supported coding agent in a project without `.cairn/`
AND Cairn not declined. Drives one-time adoption inline via
cairn_init_run MCP tool as state machine — each phase returns
complete (advance) or needs_input (AskUserQuestion, thread answer,
re-invoke). Skip when `.cairn/` exists or operator picked "never".
allowed-tools: Skill(cairn:cairn-attention), Task(curator-map), Task(curator-reduce), Task(component-annotator), Task(component-registrar)
Skill: cairn-adopt
Host portability
This skill is shared by Claude Code, Cursor, and Codex. Tool names in this file describe capabilities, not a required vendor API:
- Resolve Cairn MCP tools with the host's native tool-discovery mechanism.
`ToolSearch(...)` is the Claude Code spelling; Codex and Cursor use their equivalent discovery surface.
- `AskUserQuestion` means the host's structured question UI. If unavailable,
ask the same concise A/B/C question in chat and pause for the answer.
- Named subagents live under `../../agents/`. Claude Code may dispatch them
by name; other hosts read the matching brief and pass it to their native subagent tool. If the host has no subagent tool, execute the brief inline.
You are guiding the operator through one-time Cairn adoption for the current project. Adoption is **visual, comprehensive, and one-time** — once finished, Cairn runs invisibly forever. Refer to `docs/PLUGIN_ARCHITECTURE.md` §6 for the canonical phase sequence.
Step 0 — preload tools
Open the skill with **one** `ToolSearch` call that batch-loads every deferred tool the loop needs. This avoids one round-trip per phase. Use the **fully-qualified MCP tool names** (the bare `cairn_…` form silently no-ops in `select:`). `AskUserQuestion` is built-in and stays unprefixed.
ToolSearch(select:mcp__plugin_cairn_cairn__cairn_init_resume,mcp__plugin_cairn_cairn__cairn_init_run,mcp__plugin_cairn_cairn__cairn_decision_get,mcp__plugin_cairn_cairn__cairn_resolve_attention,mcp__plugin_cairn_cairn__cairn_attention_dedup,AskUserQuestion)
After this single call all phase tools + the question tool + the attention resolver are loaded for the rest of the skill.
Trigger gate
Before doing anything else, classify the project's adoption state. There are three buckets, NOT two — fresh, mid-adoption, and fully adopted — because Phase 4-seed writes `.cairn/config.yaml` very early. A simple `ls .cairn` check can't distinguish "operator quit during Phase 7" from "adoption finished cleanly N sessions ago."
Run this single shell probe to classify. It is **ghost-aware**: a ghost-adopted repo has no in-repo `.cairn/` — its state lives out-of-repo at `~/.cairn/state/<root-commit>/`. The probe resolves the effective state home (in-repo when present, else the out-of-repo ghost dir keyed on the repo's root-commit) before classifying, so a previously-adopted ghost repo is recognized as `adopted` / `mid-adoption` instead of re-triggering `fresh` and re-prompting consent:
node -e '
const fs=require("node:fs");
const os=require("node:os");
const path=require("node:path");
const cp=require("node:child_process");
const root=process.cwd();
let home=path.join(root,".cairn");
if(!fs.existsSync(home)){
// No in-repo .cairn — this repo may be ghost-adopted. Ghost state lives
// at ~/.cairn/state/<repo-id>; repo-id is the move-stable root-commit SHA
// (matches registerGhostRepo). Resolve it and probe there instead.
let rc="";
try{rc=cp.execFileSync("git",["-C",root,"rev-list","--max-parents=0","HEAD"],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim().split(/\s+/)[0]||"";}catch{}
if(rc){const g=path.join(os.homedir(),".cairn","state",rc);if(fs.existsSync(g))home=g;}
}
const initState=path.join(home,"init-state.json");
const config=path.join(home,"config.yaml");
if(!fs.existsSync(home)){console.log("fresh");process.exit(0);}
if(fs.existsSync(initState)){
try{
const s=JSON.parse(fs.readFileSync(initState,"utf8"));
console.log("mid-adoption:"+(s.currentPhase||"unknown"));
}catch{console.log("mid-adoption:unparseable");}
process.exit(0);
}
if(fs.existsSync(config)){console.log("adopted");process.exit(0);}
console.log("fresh");'Branch on the output:
- **`fresh`** → check operator decline-state, then continue to Step 1
(consent prompt). Decline check: `${CLAUDE_PLUGIN_DATA}/projects.json` → abort if `decline-never` is recorded for the current absolute repo path.
- **`mid-adoption:<phase>`** → adoption is in progress and was
interrupted (operator `/exit`, crash, rate-limit bail, etc.). Consent was already granted. Skip Step 1 + Step 1.5, jump straight to Step 2 (`cairn_init_resume`). Surface a plain one-line note like "Picking up Cairn setup where it left off." — do NOT print the raw `<phase>` id to the user; the per-phase banner already narrates the current step.
- **`adopted`** → fully adopted. Surface a one-line note ("Project
already adopted — `/cairn:cairn-resume` or `/cairn:cairn-attention` for daily flow.") and exit.
If the probe errors entirely, fail closed by exiting with no output.
Step 1 — propose adoption
Call `AskUserQuestion` directly. The user may have never heard of Cairn, so the question text itself must say, in plain words, what it is and what it does for them — no jargon, no "ground state" / "DEC" / "ingest".
Question text (use this, or very close to it):
> **Set up Cairn for this project?** Cairn reads your code, docs, and > commit history once to learn your project — the decisions you've made, > the rules to follow, and the components you've built — then keeps that > knowledge handy so your AI assistant stays consistent instead of > re-guessing. One-time, ~1-2 minutes; you can stop and resume anytime.
Options (set each option's `description` to the plain line shown):
- **`y
Read more
name: cairn-adopt description: One-time Cairn adoption pipeline for a new project. when_to_use: | Use when operator opens a supported coding agent in a project without `.cairn/` AND Cairn not declined. Drives one-time adoption inline via cairn_init_run MCP tool as state machine — each phase returns complete (advance) or needs_input (AskUserQuestion, thread answer, re-invoke). Skip when `.cairn/` exists or operator picked "never". allowed-tools: Skill(cairn:cairn-attention), Task(curator-map), Task(curator-reduce), Task(component-annotator), Task(component-registrar)
Skill: cairn-adopt
Host portability
This skill is shared by Claude Code, Cursor, and Codex. Tool names in this file describe capabilities, not a required vendor API:
- Resolve Cairn MCP tools with the host's native tool-discovery mechanism.
`ToolSearch(...)` is the Claude Code spelling; Codex and Cursor use their equivalent discovery surface.
- `AskUserQuestion` means the host's structured question UI. If unavailable,
ask the same concise A/B/C question in chat and pause for the answer.
- Named subagents live under `../../agents/`. Claude Code may dispatch them
by name; other hosts read the matching brief and pass it to their native subagent tool. If the host has no subagent tool, execute the brief inline.
You are guiding the operator through one-time Cairn adoption for the current project. Adoption is **visual, comprehensive, and one-time** — once finished, Cairn runs invisibly forever. Refer to `docs/PLUGIN_ARCHITECTURE.md` §6 for the canonical phase sequence.
Step 0 — preload tools
Open the skill with **one** `ToolSearch` call that batch-loads every deferred tool the loop needs. This avoids one round-trip per phase. Use the **fully-qualified MCP tool names** (the bare `cairn_…` form silently no-ops in `select:`). `AskUserQuestion` is built-in and stays unprefixed.
ToolSearch(select:mcp__plugin_cairn_cairn__cairn_init_resume,mcp__plugin_cairn_cairn__cairn_init_run,mcp__plugin_cairn_cairn__cairn_decision_get,mcp__plugin_cairn_cairn__cairn_resolve_attention,mcp__plugin_cairn_cairn__cairn_attention_dedup,AskUserQuestion)
After this single call all phase tools + the question tool + the attention resolver are loaded for the rest of the skill.
Trigger gate
Before doing anything else, classify the project's adoption state. There are three buckets, NOT two — fresh, mid-adoption, and fully adopted — because Phase 4-seed writes `.cairn/config.yaml` very early. A simple `ls .cairn` check can't distinguish "operator quit during Phase 7" from "adoption finished cleanly N sessions ago."
Run this single shell probe to classify. It is **ghost-aware**: a ghost-adopted repo has no in-repo `.cairn/` — its state lives out-of-repo at `~/.cairn/state/<root-commit>/`. The probe resolves the effective state home (in-repo when present, else the out-of-repo ghost dir keyed on the repo's root-commit) before classifying, so a previously-adopted ghost repo is recognized as `adopted` / `mid-adoption` instead of re-triggering `fresh` and re-prompting consent:
node -e '
const fs=require("node:fs");
const os=require("node:os");
const path=require("node:path");
const cp=require("node:child_process");
const root=process.cwd();
let home=path.join(root,".cairn");
if(!fs.existsSync(home)){
// No in-repo .cairn — this repo may be ghost-adopted. Ghost state lives
// at ~/.cairn/state/<repo-id>; repo-id is the move-stable root-commit SHA
// (matches registerGhostRepo). Resolve it and probe there instead.
let rc="";
try{rc=cp.execFileSync("git",["-C",root,"rev-list","--max-parents=0","HEAD"],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim().split(/\s+/)[0]||"";}catch{}
if(rc){const g=path.join(os.homedir(),".cairn","state",rc);if(fs.existsSync(g))home=g;}
}
const initState=path.join(home,"init-state.json");
const config=path.join(home,"config.yaml");
if(!fs.existsSync(home)){console.log("fresh");process.exit(0);}
if(fs.existsSync(initState)){
try{
const s=JSON.parse(fs.readFileSync(initState,"utf8"));
console.log("mid-adoption:"+(s.currentPhase||"unknown"));
}catch{console.log("mid-adoption:unparseable");}
process.exit(0);
}
if(fs.existsSync(config)){console.log("adopted");process.exit(0);}
console.log("fresh");'Branch on the output:
- **`fresh`** → check operator decline-state, then continue to Step 1
(consent prompt). Decline check: `${CLAUDE_PLUGIN_DATA}/projects.json` → abort if `decline-never` is recorded for the current absolute repo path.
- **`mid-adoption:<phase>`** → adoption is in progress and was
interrupted (operator `/exit`, crash, rate-limit bail, etc.). Consent was already granted. Skip Step 1 + Step 1.5, jump straight to Step 2 (`cairn_init_resume`). Surface a plain one-line note like "Picking up Cairn setup where it left off." — do NOT print the raw `<phase>` id to the user; the per-phase banner already narrates the current step.
- **`adopted`** → fully adopted. Surface a one-line note ("Project
already adopted — `/cairn:cairn-resume` or `/cairn:cairn-attention` for daily flow.") and exit.
If the probe errors entirely, fail closed by exiting with no output.
Step 1 — propose adoption
Call `AskUserQuestion` directly. The user may have never heard of Cairn, so the question text itself must say, in plain words, what it is and what it does for them — no jargon, no "ground state" / "DEC" / "ingest".
Question text (use this, or very close to it):
> **Set up Cairn for this project?** Cairn reads your code, docs, and > commit history once to learn your project — the decisions you've made, > the rules to follow, and the components you've built — then keeps that > knowledge handy so your AI assistant stays consistent instead of > re-guessing. One-time, ~1-2 minutes; you can stop and resume anytime.
Options (set each option's `description` to the plain line shown):
- **`y
Showing the first part of this file.
Persistent ground truth for AI coding agents. First-class support for Claude Code, Cursor, and Codex. Stop agents from drifting.
Repo: isaacriehm/cairn
Other skills on cairn.
- /cairn-adopt-components
Backfill the Cairn component store into a project that was adopted before the component store shipped.
Open skill - /cairn-attention
Resolve Cairn's pending-attention queue inline (DEC drafts, baseline findings, drift events).
Open skill - /cairn-direction
Spec-tightener + subagent dispatcher. Engage on code-change asks — verbs, bug reports, observations. Pivot-aware on active tasks.
Open skill - /cairn-resync
Operator-initiated re-discovery — resolve config drift, re-cluster topics, re-curate grown areas into DEC/INV drafts.
Open skill

