Covendocs

Coven local socket API

The Coven local HTTP API served over a Unix socket: health, capabilities, actions, sessions, events, and input forwarding under /api/v1.

Coven Local API

Last updated: 2026-05-09

Coven exposes a small HTTP API over the local Unix socket at <covenHome>/coven.sock. The Rust daemon is the authority boundary: clients may validate for UX, but the daemon still validates project roots, cwd, harness ids, session ids, input, and live-session state before acting.

Rendering diagram…

Every route returns either a documented success shape or the structured error envelope. Unknown routes, unknown action ids, and unknown API versions all fail closed with invalid_request or not_found.

See Authentication and local access for the current auth posture. In short: the daemon API does not use OAuth, JWTs, bearer tokens, API keys, or cookies today. Access is local Unix-socket based, provider credentials stay with the harness CLIs, and any remote, browser, or TCP exposure needs a separate auth design.

Versioning

The current public API contract is the named coven.daemon.v1 contract served under the /api/v1 route prefix.

Versioned clients should use the /api/v1 prefix:

coven.daemon.v1 endpoint reference
MethodPathSurfacePurpose
GET/api/v1/api-versionMetaRead the active API version and supported versions.
GET/api/v1/healthMetaCheck daemon health and metadata.
GET/api/v1/capabilitiesMetaDiscover daemon / control-plane capabilities and policy hints.
POST/api/v1/actionsControlRoute a policy-shaped control-plane action.
GET/api/v1/sessionsSessionsList active sessions.
POST/api/v1/sessionsSessionsLaunch a session.
GET/api/v1/sessions/:idSessionsFetch one session.
GET/api/v1/events?sessionId=...EventsRead session events.
POST/api/v1/sessions/:id/inputSessionsForward input to a live session.
POST/api/v1/sessions/:id/killSessionsKill a live session.

Unversioned routes currently remain as legacy aliases during the early MVP window, but new clients should not rely on them.

Unknown /api/<version>/... prefixes fail closed with an unsupported API version JSON response.

Health Response

GET /api/v1/health is the required compatibility handshake. It returns the named contract version, the installed Coven binary version, machine-readable capabilities, and optional daemon metadata:

{
  "ok": true,
  "apiVersion": "coven.daemon.v1",
  "covenVersion": "0.0.0",
  "capabilities": {
    "sessions": true,
    "events": true,
    "eventCursor": "sequence",
    "structuredErrors": true
  },
  "daemon": {
    "pid": 12345,
    "startedAt": "2026-05-09T12:00:00Z",
    "socket": "/Users/example/.coven/coven.sock"
  }
}

When no daemon metadata is available, daemon is null.

Clients should treat apiVersion: "coven.daemon.v1" as the stable contract guard. covenVersion identifies the binary build and can be shown in diagnostics, but clients should not branch compatibility on a package version alone.

GET /api/v1/api-version is lower-level route metadata. It currently returns the route prefix version, not the named contract:

{
  "apiVersion": "v1",
  "supportedApiVersions": ["v1"]
}

Use /api/v1/health for normal client handshakes. Use /api/v1/api-version only when debugging route-prefix support.

Control-plane Capabilities

GET /api/v1/capabilities is the discovery point for first-party clients. It returns capability ids, adapter ownership, availability, policy hints, and action ids. This keeps clients from hard-coding what the daemon can do.

{
  "capabilities": [
    {
      "id": "coven.control.actions",
      "label": "Coven control-plane action router",
      "adapter": "coven-daemon",
      "status": "available",
      "policy": "allow",
      "actions": ["coven.capabilities.refresh"]
    },
    {
      "id": "desktop.automation",
      "label": "Desktop automation adapters",
      "adapter": "desktop-use",
      "status": "planned",
      "policy": "requiresApproval",
      "actions": []
    }
  ]
}

Control-plane Actions

POST /api/v1/actions accepts a structured intent envelope. The daemon routes only known actions; unknown actions fail closed before any adapter can run.

{
  "action": "coven.capabilities.refresh",
  "origin": "coven-client",
  "args": {}
}

Immediately completed safe actions return 200 with an event-shaped payload that clients can render optimistically or fold into later event streams:

{
  "ok": true,
  "accepted": true,
  "action": "coven.capabilities.refresh",
  "status": "completed",
  "event": {
    "kind": "capabilities.refreshed",
    "action": "coven.capabilities.refresh",
    "origin": "coven-client",
    "payload": { "capabilities": 3 }
  }
}

Session Records

Session endpoints return the Rust daemon's SessionRecord shape with snake_case field names:

{
  "id": "session-1",
  "project_root": "/Users/example/project",
  "harness": "codex",
  "title": "Fix failing tests",
  "status": "running",
  "exit_code": null,
  "archived_at": null,
  "created_at": "2026-05-09T06:43:00Z",
  "updated_at": "2026-05-09T06:43:05Z"
}
Session record endpoints
MethodPathResponseNotes
GET/api/v1/sessionsSessionRecord[]Lists active, non-archived sessions.
POST/api/v1/sessionsSessionRecordLaunches a project-scoped harness session.
GET/api/v1/sessions/:idSessionRecordReturns 404 session_not_found for unknown ids.

POST /api/v1/sessions accepts the launch fields the daemon validates before spawning a harness:

{
  "projectRoot": "/Users/example/project",
  "cwd": "/Users/example/project",
  "harness": "codex",
  "prompt": "Fix the failing tests",
  "title": "Fix failing tests"
}

cwd must resolve inside projectRoot. harness must be a supported harness id. Provider credentials are not part of this request; Codex, Claude Code, and future harnesses keep their own local auth flows.

Events

GET /api/v1/events returns an event page for one session.

Events query parameters
ParameterRequiredMeaning
sessionIdYesSession id whose events should be returned.
afterSeqNoPreferred cursor. Returns events with seq > afterSeq.
afterEventIdNoCompatibility cursor resolved to a sequence position.
limitNoMaximum records to return. The daemon enforces a max of 1000.
{
  "events": [
    {
      "seq": 42,
      "id": "event-1",
      "session_id": "session-1",
      "kind": "output",
      "payload_json": "{\"data\":\"hello\"}",
      "created_at": "2026-05-09T06:43:10Z"
    }
  ],
  "nextCursor": {
    "afterSeq": 42
  },
  "hasMore": false
}

nextCursor is null when there are no events. Persisting nextCursor.afterSeq lets clients resume incremental reads after a daemon restart.

Live Input

POST /api/v1/sessions/:id/input forwards input only to a daemon-verified live session.

Request:

{
  "data": "continue with the next failing test\n"
}

Success returns 202:

{
  "ok": true,
  "accepted": true
}

The daemon records accepted input as a session event. Completed, failed, killed, archived, or orphaned sessions are replay/log surfaces, not live input targets.

Live Kill

POST /api/v1/sessions/:id/kill terminates only a daemon-verified live process. The request body is empty.

Success returns 202:

{
  "ok": true,
  "accepted": true
}

After a successful kill, the daemon updates the session status to killed and writes a kill event. Killing a session is not the same as deleting its history; use archive/summon/sacrifice lifecycle commands for record management.

Error Envelope

All API failures use this structured envelope. Clients should branch on error.code, not message text:

{
  "error": {
    "code": "session_not_found",
    "message": "Session was not found.",
    "details": {
      "sessionId": "session-1"
    }
  }
}
Stable daemon error codes
CodeHTTP statusMeaning
not_found404Route not found.
invalid_request400 or 404Malformed request, unsupported API version, or unknown control action.
session_not_found404Session id does not exist.
session_not_live409Session exists but cannot accept input or kill because it is not running in this daemon.
project_root_violation400Requested cwd resolves outside the declared project root.
pty_spawn_failed500Harness PTY could not be launched.
runtime_unavailable503The session runtime is unavailable.
internal_error500Unexpected internal daemon error.

Unknown session:

{
  "error": {
    "code": "session_not_found",
    "message": "Session was not found.",
    "details": { "sessionId": "session-1" }
  }
}

Non-live input or kill:

{
  "error": {
    "code": "session_not_live",
    "message": "Session is not live.",
    "details": { "sessionId": "session-1" }
  }
}

Compatibility Rules

API compatibility rules
RuleRisk areaClient or maintainer action
Additive JSON fields are allowed in v1 responses.Forward compatibilityClients should ignore unknown optional fields when safe.
Existing required fields should not be removed or renamed inside v1.Breaking changesKeep required response shapes stable for versioned clients.
Breaking response-shape or behavior changes require a new API version prefix.VersioningMove incompatible behavior behind a new route prefix.
External clients should call /api/v1/health before assuming compatibility.HandshakeCheck daemon availability and API version first.
Daemon changes that affect /api/v1/health, /api/v1/sessions, /api/v1/events, input, or kill behavior should update client compatibility tests in the same repo.Contract driftUpdate tests with the API-affecting change.

Last updated on

On this page