Skip to content

Repository files navigation

Cairnline

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.

Goals

  • 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.

Concept Boundary

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.

Security Boundaries

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.

Current Slice

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 include AGENTS.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, _meta passthrough on tools, resources, resource content, and tool results, embedded-resource and base64 blob tool-result content, and capabilities.extensions negotiation during initialize (the server declares none by default)
  • MCP read tools return human-readable text plus structuredContent where 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-readiness
    • cairnline://projects/{project_id}/assignments/{assignment_id}
    • cairnline://projects/{project_id}/assignments/{assignment_id}/launch-packet
    • cairnline://projects/{project_id}/memory-candidates/{memory_candidate_id}
  • MCP tools:
    • coordination.capabilities
    • projects.list
    • projects.get
    • projects.create
    • projects.update
    • projects.delete
    • projects.activity
    • projects.health
    • projects.operations_brief
    • projects.setup_readiness
    • roots.list
    • roots.create
    • roots.update
    • roots.delete
    • context_sources.list
    • context_sources.create
    • context_sources.update
    • context_sources.delete
    • assistant.propose
    • assistant.proposals.list
    • assistant.proposals.get
    • assistant.apply
    • skills.list
    • skills.create
    • skills.update
    • skills.discover
    • roles.list
    • roles.create
    • roles.update
    • roles.delete
    • work_items.list
    • work_items.get
    • work_items.create
    • work_items.update
    • work_items.delete
    • work_items.closeout_readiness
    • assignments.list
    • assignments.get
    • assignments.next
    • assignments.create
    • assignments.update
    • assignments.claim
    • assignments.renew_claim
    • assignments.recover_claim
    • assignments.prepare
    • assignments.release
    • assignments.update_status
    • assignments.context
    • assignments.launch_packet
    • assignments.complete
    • assignments.delete
    • artifacts.list
    • artifacts.get
    • artifacts.create
    • evidence.list
    • evidence.get
    • evidence.record
    • reviews.list
    • reviews.get
    • reviews.record
    • handoffs.create
    • handoffs.list
    • handoffs.get
    • handoffs.update
    • handoffs.update_status
    • handoffs.delete
    • handoffs.accept_with_follow_up
    • memory_entries.list
    • memory_entries.get
    • memory_entries.create
    • memory_entries.update
    • memory_entries.delete
    • memory_candidates.list
    • memory_candidates.get
    • memory_candidates.create
    • memory_candidates.promote
    • memory_candidates.reject
    • memory_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

Run

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" -version

On Windows, download the cairnline_${version}_windows_amd64.tar.gz archive from the same release, extract cairnline.exe, and run:

.\cairnline.exe -version

Each 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@latest

Ephemeral in-memory state:

go run ./cmd/cairnline

Durable SQLite state:

go run ./cmd/cairnline -db ./cairnline.db

The 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.

Embedded Go API

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.

MCP Client Config

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"
    }
  }
}

MCP Apps (Interactive Views)

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.

Hecate Integration Status

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

Test

go test ./...

The public CI also runs:

go vet ./...
go test -race ./...

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages