identityLABSCO SUMMARY
The gates are the same for the agent and for you.
Both front-ends are thin adapters over one rule-set, so an agent cannot close a task by a route that skips the checks a human would have to pass. Closing deliberately blocks while the checks run — the latency is the point, since closing is when verification belongs. Because identity comes from --actor at startup rather than from the call, the provenance trail is something an agent cannot spoof by passing a different name.
What it is
A single Go binary that serves one task graph two ways: a web board for you and an MCP server for your agents. The tasks are Markdown files in the repository — YAML frontmatter for the machine, prose for people — so they branch, merge and review like code, and a task's history is its git history. No database.
What you get
- Reads —
identityfor the bound actor,listfiltered bystatus,assignee,readyorexecution, andgetfor one task with its body, checks and provenance create— the engine assigns the id;depsmust already exist, so the graph never dangles, andcheckscan carry a shell command or be marked manualclaimto take a task,transitionto move it,noteto append an audit breadcrumb without changing state- Two gates enforced on every path: a task cannot leave its initial state until its dependencies close, and cannot enter a closed state until its checks pass —
transitionauto-runs the command checks and refuses on any failure run_checksto run them without transitioning, with full output written to.cairn/runs/- Agent sessions —
beginatomically claims the task and creates a durable attempt with an idempotency key,heartbeatreports progress,finishrequires a review summary and moves to review,cancelreleases the assignment and leaves the task open;get_sessionandlist_sessionsread them back readyderived on read from whether dependencies are satisfied, never stored — solist(ready=true)is the agent's "what can I start now" query- Every write stamped with the actor that made it
Requirements
No account and no key. make build produces bin/cairn; there is also a desktop app for macOS, Windows and Linux on the releases page. ./bin/cairn web --repo . opens the board, and its Connect page detects installed agents and writes their MCP config for you — Claude Code, Cursor, Codex, Windsurf, OpenCode, Kilo Code and Pi in one click. By hand, register the binary by its full path: /path/to/repo/bin/cairn serve --actor agent:claude --repo <path>. Identity is fixed at startup by --actor and is not a tool argument, which is how each agent gets its own name in the provenance. Local and single-user by design, with no authentication. MIT.
Setup effort
Build from source
USE CASES
Letting an agent pick up work on its own
Ask for ready tasks in the initial state and let it claim one instead of being told what to do.
Making sure done means tested
Attach the test command as a check, and let the transition run it and refuse to close on failure.
Watching a long agent run
Begin a session, read heartbeats as it progresses, and require a review summary before it hands back.
Reviewing what an agent changed, in git
The tasks are files, so the diff of the work and the diff of the plan land in the same pull request.
Recording a blocker without moving the task
Append a note to the provenance so the reason is attached to the work rather than lost in a chat log.
14 tools
Listed in project docs. Your client may show a different list.
listgetcreateclaimtransitionrun_checksnotebeginheartbeatfinishcancelget_sessionlist_sessionsBEFORE YOU INSTALL
What to know first
Tools you get
14 tools named in the project's documentation. Most tools write (create, claim, transition, note, finish, cancel and others), and identity is fixed at server start by --actor rather than passed per call.
INSTALLATION
Connect your client
You clone and build this one yourself.
Server setup
git clone https://github.com/ShahramMebashar/cairn
cd cairn
make build # -> bin/cairn
./bin/cairn web --repo .
claude mcp add cairn -- "$(pwd)/bin/cairn" serve --actor agent:claude --repo "$(pwd)"MCP Clients
Claude Code, Claude Desktop
{
"mcpServers": {
"cairn": {
"command": "<YOUR_PATH_TO_BIN_CAIRN>",
"args": [
"serve",
"--actor",
"agent:claude",
"--repo",
"<YOUR_PATH_TO_PROJECT>"
]
}
}
}Cursor
{
"mcpServers": {
"cairn": {
"command": "<YOUR_PATH_TO_BIN_CAIRN>",
"args": [
"serve",
"--actor",
"agent:cursor",
"--repo",
"<YOUR_PATH_TO_PROJECT>"
]
}
}
}Codex
[mcp_servers.cairn]
args = ["serve", "--actor", "agent:codex", "--repo", "<YOUR_PATH_TO_PROJECT>"]
command = "<YOUR_PATH_TO_BIN_CAIRN>"Windsurf
{
"mcpServers": {
"cairn": {
"command": "<YOUR_PATH_TO_BIN_CAIRN>",
"args": [
"serve",
"--actor",
"agent:windsurf",
"--repo",
"<YOUR_PATH_TO_PROJECT>"
]
}
}
}OpenCode
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"cairn": {
"type": "local",
"command": [
"<YOUR_PATH_TO_BIN_CAIRN>",
"serve",
"--actor",
"agent:opencode",
"--repo",
"<YOUR_PATH_TO_PROJECT>"
],
"enabled": true
}
}
}Kilo Code
{
"mcpServers": {
"cairn": {
"command": "<YOUR_PATH_TO_BIN_CAIRN>",
"args": [
"serve",
"--actor",
"agent:kilo",
"--repo",
"<YOUR_PATH_TO_PROJECT>"
]
}
}
}Pi
{
"mcpServers": {
"cairn": {
"command": "<YOUR_PATH_TO_BIN_CAIRN>",
"args": [
"serve",
"--actor",
"agent:pi",
"--repo",
"<YOUR_PATH_TO_PROJECT>"
]
}
}
}MCP Inspector (test)
npx @modelcontextprotocol/inspector ./bin/cairn serve --actor agent:dev --repo .