Cairnline is an experimental local-first coordination server for human and AI work.
It provides durable project identity, work coordination, context metadata, collaboration artifacts, evidence, reviews, handoffs, accepted project memory, and memory-candidate concepts without assuming that any specific agent host can be launched or supervised.
Initial status: early implementation. Cairnline is usable as an experimental local MCP server, but its contracts are not stable yet.
For host authors, see Agent Host Integration for how MCP-capable clients should map Cairnline roles, assignments, desired-agent hints, and skills into their own agent/runtime concepts.
- Work for rootless planning/research/design projects and workspace-backed code projects.
- Expose project coordination over MCP stdio.
- Let agents pull/claim work through MCP instead of requiring push-based orchestration.
- Keep Hecate-specific runtime behavior out of the portable core.
Cairnline's portable concepts are coordination concepts:
- Project role: a responsibility inside a project, such as architect, implementer, reviewer, researcher, designer, or operator.
- Assignment: a durable coordination record binding work item, role, optional root, execution mode, desired agent metadata, and lifecycle status.
- Desired agent: a portable hint about which kind of human or agent host should claim work, plus skill ids the claimant may understand.
- Skill metadata: referenced capability/instruction metadata only; it does not load, inject, execute, install, or fetch skill bodies.
Cairnline does not expose agent presets, runtime profiles, provider settings,
model settings, sandbox policy, or launch permissions as portable MCP concepts.
MCP clients should create project roles plus assignments with
execution_mode, desired_agent.kind, and desired_agent.skill_ids, then map
those hints to their own Claude, Cursor, Copilot, OpenAI, Hecate, human, or
other host-specific agent configuration. Cairnline records intent and
provenance; the agent host remains responsible for runtime policy,
permissions, model choice, sandboxing, and launch behavior.
Cairnline does not keep portable agent-preset or runtime-profile catalogs, and
host-specific preset/runtime ids should live in the consuming agent host rather
than in Cairnline coordination records.
Cairnline is local-first and single-operator by default. It stores coordination state and exposes it over MCP, so clients should treat mutating tools as durable state changes that need the same care as editing a project database.
Project roots are optional metadata until a feature explicitly needs local
files. Current skill discovery is the main local-read path: it reads bounded
guidance files from active roots, discovers local SKILL.md metadata, and skips
absolute paths, parent traversal, remote URLs, and hidden worktree folders. It
stores names, descriptions, provenance, suggested tool names, and nullable
permission hints without storing, injecting, executing, installing, or fetching
skill bodies. Skill metadata is not permission to enable tools, writes, network
access, approvals, or sandbox escapes.
Source locators, evidence locators, and evidence URLs are operator-provided metadata. Cairnline stores them as-is and does not fetch or render them. Clients must validate schemes before displaying a locator as a clickable link or before opening/fetching it.
Assignments are coordination records. Claiming or reading an assignment does not authorize an agent host to bypass its own sandboxing, approval policy, network policy, credential handling, or logged-in session boundaries. Secrets, cookies, provider credentials, and external-agent private memory are outside Cairnline's core model.
MCP assignment claims carry a server-issued claim.id. It is a concurrency
fence, not a bearer credential or proof of identity. Hosts must still decide who
may call mutation tools. The pre-start reservation expires after the TTL
advertised by coordination.capabilities; expiry only makes an explicit
assignments.recover_claim possible. Cairnline never treats a running agent as
dead, cancels host execution, or requeues running work automatically.
Cairnline assignment metadata is not authorization. Agent hosts and orchestrators must enforce their own policy boundaries even when an assignment asks for a particular execution mode, desired agent kind, or skill id.
Role references are durable coordination metadata rather than hard ownership. Creating or updating work-item owner/reviewer refs and assignment role refs validates the role at write time, but deleting a role does not delete or block historical records that still carry that role id. Context and launch-packet reads surface missing-role warnings so operators can repair or preserve the historical record deliberately.
Implemented now:
- portable core types for projects with roots/default root, context source provenance metadata, project roles, work items, assignments with lifecycle timestamps, desired agent hints, skill metadata, generic collaboration artifacts, assignment-scoped evidence with source/provider/external-id metadata, structured review verdict/risk metadata, handoffs with source/target refs and status-transition timestamps, accepted memory, and memory candidates
- in-memory service for projects, project roles, work items, assignments, assistant proposal records including project-root/default-root actions, and collaboration artifacts
- SQLite store for durable projects, project roles, work items, assignments, skill metadata, assistant proposal records, and collaboration artifacts
- expiring, renewable MCP assignment reservations with server-issued fencing ids; expired pre-start claims can be explicitly recovered without allowing a stale worker to prepare, start, or complete a later claim generation
- project skill discovery from interoperable
.agents/skills, Cairnline-native.cairnline/skills, Claude-compatible.claude/skills, Gemini-compatible.gemini/skills, compatibility.hecate/skills, and enabled guidance-linked local skill roots; recognized guidance locators includeAGENTS.md,CLAUDE.md,GEMINI.md,.cursor/rules,.github/instructions,.devin/rules, and.windsurf/rules; rediscovery refreshes discovered status, provenance, suggested tools, and permission hints while preserving operator-edited enabled/title/description and trust-label fields
Skill roots are metadata discovery only: Cairnline records SKILL.md title,
description, path, provenance, suggested-tool hints, and nullable permission
hints, but never loads skill bodies, executes skill code, or treats a skill as
authorization. The .claude/skills default follows the Claude Code skills
documentation, and .gemini/skills follows Gemini CLI Agent Skills workspace
discovery; both were checked on July 4, 2026:
Claude Code skills,
Gemini CLI Agent Skills.
- embeddable Go API for applications that want to use the coordination core directly instead of speaking MCP, including work-item owner/reviewer role-ref validation, assignment metadata updates that preserve created time and claim ownership while validating work-item, role, root, and durable coordination references, a narrow claimed-assignment release path for pre-dispatch retry cleanup, plus source-level context metadata create/update/delete helpers that avoid whole-project replacement
- embeddable snapshot export/import for migration rehearsals and bridge seeding; snapshots cover projects, skills, roles, work, assignments, artifacts, evidence, reviews, handoffs, memory entries, memory candidates, and assistant proposal records (snapshot v2 preserves claim fences and still accepts v1 imports as host-authoritative unleased historical claims)
- stdio MCP server with JSON-RPC framing
- MCP protocol structs carry the spec fields a richer tool surface needs: tool
outputSchema,_metapassthrough on tools, resources, resource content, and tool results, embedded-resource and base64blobtool-result content, andcapabilities.extensionsnegotiation duringinitialize(the server declares none by default) - MCP read tools return human-readable text plus
structuredContentwhere a stable data shape exists, including core project/role/work/assignment list surfaces, coordination capabilities, and assignment context/launch packet reads, so compatible clients can avoid scraping text output - MCP resources and resource templates:
cairnline://projects/{project_id}cairnline://projects/{project_id}/work-items/{work_item_id}cairnline://projects/{project_id}/work-items/{work_item_id}/closeout-readinesscairnline://projects/{project_id}/assignments/{assignment_id}cairnline://projects/{project_id}/assignments/{assignment_id}/launch-packetcairnline://projects/{project_id}/memory-candidates/{memory_candidate_id}
- MCP tools:
coordination.capabilitiesprojects.listprojects.getprojects.createprojects.updateprojects.deleteprojects.activityprojects.healthprojects.operations_briefprojects.setup_readinessroots.listroots.createroots.updateroots.deletecontext_sources.listcontext_sources.createcontext_sources.updatecontext_sources.deleteassistant.proposeassistant.proposals.listassistant.proposals.getassistant.applyskills.listskills.createskills.updateskills.discoverroles.listroles.createroles.updateroles.deletework_items.listwork_items.getwork_items.creatework_items.updatework_items.deletework_items.closeout_readinessassignments.listassignments.getassignments.nextassignments.createassignments.updateassignments.claimassignments.renew_claimassignments.recover_claimassignments.prepareassignments.releaseassignments.update_statusassignments.contextassignments.launch_packetassignments.completeassignments.deleteartifacts.listartifacts.getartifacts.createevidence.listevidence.getevidence.recordreviews.listreviews.getreviews.recordhandoffs.createhandoffs.listhandoffs.gethandoffs.updatehandoffs.update_statushandoffs.deletehandoffs.accept_with_follow_upmemory_entries.listmemory_entries.getmemory_entries.creatememory_entries.updatememory_entries.deletememory_candidates.listmemory_candidates.getmemory_candidates.creatememory_candidates.promotememory_candidates.rejectmemory_candidates.delete
- assignment launch packets with project, role, assignment, desired-agent, skill, generic-artifact, evidence, review, handoff, accepted-memory, and memory-candidate metadata
- read-only work-item closeout readiness summaries derived from assignment, evidence, review, and handoff metadata
- read-only project operations briefs for attention routing across active assignments, expired pre-start claims, blocked closeout, review follow-up, memory candidates, and open work
- read-only project activity projections grouped by active, blocked, completed, and recent assignment state; queued assignments are attention items until claimed, unexpired claimed/running/review assignments are active, and expired pre-start claims are blocked recovery items
- read-only project setup-readiness and health summaries for onboarding, context/skill gaps, and bounded operator attention
- deterministic assistant proposal/apply tools with durable proposal records, proposal warnings, apply attempts, latest-result state, and repeat-apply protection for confirmed project-state mutations; applying a proposal can create queued assignment coordination records, but it does not launch or supervise agents
- snapshot and proposal-record imports preserve assistant ledger state without replaying proposal actions
Install a release binary on macOS or Linux:
version=v0.1.0-alpha.4 # replace with the release tag you want
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
arch="$(uname -m)"
case "$arch" in
x86_64) arch=amd64 ;;
aarch64) arch=arm64 ;;
esac
curl -L "https://github.com/hecatehq/cairnline/releases/download/${version}/cairnline_${version}_${os}_${arch}.tar.gz" -o cairnline.tar.gz
tar -xzf cairnline.tar.gz cairnline
mkdir -p "$HOME/.local/bin"
install -m 0755 cairnline "$HOME/.local/bin/cairnline"
"$HOME/.local/bin/cairnline" -versionOn Windows, download the cairnline_${version}_windows_amd64.tar.gz archive
from the same release, extract cairnline.exe, and run:
.\cairnline.exe -versionEach release also publishes checksums.txt for the archives. Prerelease tags
such as v0.1.0-alpha.4 are published as GitHub prereleases while the MCP
contract is still settling. Release binaries are built for darwin/amd64,
darwin/arm64, linux/amd64, linux/arm64, and windows/amd64.
Maintainers cut binary releases by pushing a v* tag. The release workflow
runs tests, vet, race tests, builds the archives, and attaches them to the
GitHub release.
Or install the command from source:
go install github.com/hecatehq/cairnline/cmd/cairnline@latestEphemeral in-memory state:
go run ./cmd/cairnlineDurable SQLite state:
go run ./cmd/cairnline -db ./cairnline.dbThe server speaks MCP over newline-delimited JSON-RPC on stdin/stdout.
For a first standalone workflow, see the MCP quickstart. It walks through creating a rootless project, adding a role and work item, queueing an assignment, claiming it from an agent, recording evidence, and completing the assignment without any Hecate-specific runtime.
Applications can embed Cairnline directly through the root Go package. Do not
import internal/* packages; they are private implementation details.
package main
import (
"context"
"log"
"github.com/hecatehq/cairnline"
)
func main() {
ctx := context.Background()
service, store, err := cairnline.NewSQLiteService(ctx, "cairnline.db")
if err != nil {
log.Fatal(err)
}
defer store.Close()
project, err := service.CreateProject(ctx, cairnline.Project{
Name: "Example project",
})
if err != nil {
log.Fatal(err)
}
_, err = service.CreateWorkItem(ctx, cairnline.WorkItem{
ProjectID: project.ID,
Title: "Coordinate the next reviewable task",
})
if err != nil {
log.Fatal(err)
}
}For tests or short-lived tools, use the in-memory service:
service := cairnline.NewMemoryService()Embedded hosts can rehearse migration through snapshots:
snapshot, err := source.ExportSnapshot(ctx)
if err != nil {
log.Fatal(err)
}
_, err = target.ImportSnapshot(ctx, snapshot)
if err != nil {
log.Fatal(err)
}Snapshot import is additive/upsert. It does not delete records that are absent from the snapshot, does not replay assistant proposal actions, and is not exposed as an MCP bulk mutation tool.
An embedding host can also build the MCP server from the root package instead of
shelling out to the stdio binary. cairnline.NewMCPServer(service, version)
returns the fully-registered server; mount it on a custom transport by feeding
each inbound JSON-RPC message through server.HandleMessage(ctx, msg) (the
second return is false for notifications), or run the built-in stdio loop with
server.Serve(ctx, os.Stdin, os.Stdout). See
Agent Host Integration for the mount details
and optional capabilities.extensions negotiation.
Use a durable SQLite database for normal local use:
{
"mcpServers": {
"cairnline": {
"command": "cairnline",
"args": ["-db", "/Users/alice/.local/share/cairnline/cairnline.db"]
}
}
}For development from a checkout:
{
"mcpServers": {
"cairnline-dev": {
"command": "go",
"args": [
"run",
"./cmd/cairnline",
"-db",
"/tmp/cairnline-dev.db"
],
"cwd": "/path/to/cairnline"
}
}
}Cairnline ships an optional read-only Project Status view using the MCP Apps
extension (io.modelcontextprotocol/ui, SEP-1865). It is served as a
self-contained ui://cairnline/project-status HTML resource and linked from the
projects.health, projects.operations_brief, and projects.activity tools via
_meta.ui.resourceUri.
Host support is uneven today. Hosts that render MCP Apps — such as Claude
Desktop, VS Code Copilot, and Goose — can display the interactive view. Hosts
that do not yet render apps, including current coding-agent CLIs, are unaffected:
they receive the exact same text and structuredContent tool results as before.
The extension is only advertised when an app is registered, and adding it never
changes tool call results.
Authoring and host-integration details are in
docs/agent-host-integration.md and
internal/app/views/README.md.
Cairnline is the intended portable extraction path for Hecate's Projects coordination substrate. It is still developed as a standalone, agent-neutral server first; Hecate is one integration client, not the host that defines the core model.
Cairnline ships a public embeddable Go API, and Hecate embeds it live today:
Hecate pins Cairnline through go.mod and runs it as an in-process service. A
sidecar connector mode also exists for running Cairnline out of process. MCP
remains the interoperability surface for external agents and other hosts.
Mirror-on-write is live. Hecate live-mirrors every portable project-coordination write family into the embedded Cairnline store: project identity, metadata/defaults, roots, context sources, skills, roles, work items, assignments, collaboration artifacts, handoffs, accepted memory, memory candidates, and Project Assistant proposal-ledger records.
Current Hecate dogfood covers:
- embedded Cairnline read-model projections for Hecate's project list/detail, setup, health, skills, memory, roles, work, assignment, collaboration, Project Assistant, chat-context, activity, closeout, and operations views
- live write-mirroring of all the portable project-coordination families listed above into the embedded Cairnline store
- strict embedded mirror/parity probes, migration rehearsal evidence, rollback notes, and backend-status gates for deciding when Cairnline is authoritative for portable project coordination state
- Cairnline-only project identity and project-work journeys in Hecate tests, where Hecate keeps only runtime/workspace overlays for task/chat execution
Recent fidelity work (cairnline#76, merged 2026-07-09) added a structured
ExecutionRef, a first-class awaiting_approval assignment status, and memory
in assignment context packets, tightening how host runtime state maps onto
Cairnline coordination records.
An opt-in armed replacement mode is implemented and off by default. When an operator enables it, Cairnline becomes authoritative for portable project coordination and Hecate keeps only a runtime overlay for task/chat execution. Normal builds still default to Hecate-owned coordination with Cairnline mirrored alongside.
These integration contracts are not stable yet. Cairnline is still alpha, and both the MCP surface and the embedded Go API can change.
Hecate still owns native operator UI/UX, model gateway behavior, task runtime, External Agent supervision, approvals, traces, root discovery, and Git worktree creation. Those are host/orchestrator responsibilities, not Cairnline core.
Before Hecate can make Cairnline the default Projects backend in normal builds, the remaining integration work is:
- keep replacement-mode gates green under real dogfood, not only fixture tests
- shrink Hecate compatibility-shadow code once cutover behavior is stable
- package Cairnline as an additional local download for non-Hecate hosts
- keep MCP contracts stable enough for MCP-pull/manual assignment workflows
- decide whether Hecate should also support standalone MCP-server mode as an operator-selectable backend in addition to the embedded Go service
go test ./...The public CI also runs:
go vet ./...
go test -race ./...