Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/docs/guides/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The catalog is being built out one guide at a time, prioritized by the questions
| [Set up memory](/docs/guides/set-up-memory) | How do I enable memory and inspect what is stored? |
| [Fix a failed install](/docs/guides/fix-a-failed-install) | My install broke — how do I diagnose and repair it? |
| [Upgrade Coven](/docs/guides/upgrade-coven) | How do I upgrade safely without losing sessions? |
| Script the API | How do I call the daemon API from my own scripts? |
| [Script the API](/docs/guides/script-the-api) | How do I call the daemon API from my own scripts? |

## Start here today

Expand Down
2 changes: 1 addition & 1 deletion content/docs/guides/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"description": "Step-by-Step How-Tos",
"root": true,
"icon": "LuCompass",
"pages": ["index", "install-and-first-run", "connect-a-harness", "set-up-the-daemon", "set-up-memory", "fix-a-failed-install", "upgrade-coven"]
"pages": ["index", "install-and-first-run", "connect-a-harness", "set-up-the-daemon", "set-up-memory", "fix-a-failed-install", "upgrade-coven", "script-the-api"]
}
113 changes: 113 additions & 0 deletions content/docs/guides/script-the-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
title: "Script the API"
summary: "Call the daemon API from your own scripts: health handshake, listing and launching sessions, following events with a cursor, and handling structured errors."
description: "Step-by-step guide to scripting the Coven daemon socket API with curl: health, sessions, session launch, event cursors, and the error envelope."
read_when:
- You want your own script or tool to drive Coven instead of the CLI
- You need the minimal correct client loop: health, launch, events, errors
---

Everything the CLI and every other client does goes through the daemon's local HTTP API. This guide builds the minimal correct client loop with `curl`: handshake, list, launch, follow events, and branch on structured errors. The full contract is the [API reference](/docs/reference/api) and the [OpenAPI pages](/docs/openapi).

## Prerequisites

- The daemon running — see [Set up the daemon](/docs/guides/set-up-the-daemon).
- `curl`; `jq` helps but is optional.
- A project directory and one connected harness for the launch step — see [Connect a harness](/docs/guides/connect-a-harness).

All examples use the Unix socket. Set the path once:

```bash
SOCK="$HOME/.coven/coven.sock"
```

## Step 1 — Start with the health handshake

Every client should begin every run here:

```bash
curl --unix-socket "$SOCK" http://localhost/api/v1/health
```

**Expected output:** `"ok": true`, `"apiVersion": "coven.daemon.v1"`, and a capability map. Scripts should verify the `apiVersion` matches the contract they were written for and check `GET /api/v1/capabilities` before using optional features — see [versioning rules](/docs/reference/api#versioning).

## Step 2 — List sessions

```bash
curl --unix-socket "$SOCK" http://localhost/api/v1/sessions
```

**Expected output:** a JSON array of session records with snake_case fields (`id`, `project_root`, `harness`, `title`, `status`, `created_at`, …). An empty array just means no active, non-archived sessions. The record shape is documented under [session records](/docs/reference/api#session-records).

## Step 3 — Launch a session

`POST /api/v1/sessions` validates the project boundary before spawning anything:

```bash
curl --unix-socket "$SOCK" http://localhost/api/v1/sessions \
-H 'content-type: application/json' \
-d '{
"projectRoot": "/Users/you/code/your-repo",
"cwd": "/Users/you/code/your-repo",
"harness": "codex",
"prompt": "explain this repo in 5 bullets",
"title": "API launch smoke test"
}'
```

**Expected output:** `201` with the created session record — capture its `id` for the next step. `cwd` must resolve inside `projectRoot`, `harness` must be a supported harness id, and provider credentials are never part of the request.

## Step 4 — Follow events with the cursor

Poll the event page for your session, then resume from `nextCursor.afterSeq`:

```bash
curl --unix-socket "$SOCK" \
"http://localhost/api/v1/events?sessionId=<session-id>&afterSeq=0&limit=100"
```

**Expected output:** an `events` array (each with `seq`, `kind`, `payload_json`), a `nextCursor`, and `hasMore`. The loop that never loses data:

1. Request with your last `afterSeq` (start at `0`).
2. Process the returned events.
3. Persist `nextCursor.afterSeq` — it survives daemon restarts.
Comment thread
BunsDev marked this conversation as resolved.
Outdated
4. Repeat while `hasMore` is `true`, then poll on your own interval.

The daemon caps `limit` at 1000. `GET /api/v1/sessions/<id>/events` is the same read, path-scoped — see [events](/docs/reference/api#events).

## Step 5 — Branch on the error envelope

Force a failure to see the shape every error uses:

```bash
curl --unix-socket "$SOCK" http://localhost/api/v1/sessions/does-not-exist
```

**Expected output:**

```json
{
"error": {
"code": "session_not_found",
"message": "Session was not found.",
"details": { "sessionId": "does-not-exist" }
}
}
```

Branch on `error.code`, never on message text. The stable codes (`not_found`, `invalid_request`, `session_not_found`, `session_not_live`, `project_root_violation`, `pty_spawn_failed`, `runtime_unavailable`, `internal_error`) and their HTTP statuses are tabulated in the [error envelope reference](/docs/reference/api#error-envelope). A robust script treats `runtime_unavailable` as retry-after-status, and `session_not_live` as "switch to replay, do not send input."
Comment thread
BunsDev marked this conversation as resolved.
Outdated

## Troubleshooting

- **`curl` cannot connect** — daemon down or wrong socket path for your `COVEN_HOME`; see [Set up the daemon](/docs/guides/set-up-the-daemon).
- **`invalid_request` on launch** — compare your body against Step 3's fields; an unknown harness id lands here too.
- **`project_root_violation`** — your `cwd` escapes `projectRoot`; see [`cwd` rejected](/docs/reference/troubleshooting#cwd-rejected).
- **Events stop arriving** — the session likely completed; check its `status` via `GET /api/v1/sessions/<id>`.
- **Version mismatch after an upgrade** — see [API version rejected](/docs/reference/troubleshooting#api-version-rejected) and [Upgrade Coven](/docs/guides/upgrade-coven).

## Related

- [API reference](/docs/reference/api)
- [API architecture diagrams](/docs/reference/api-architecture)
- [OpenAPI endpoint pages](/docs/openapi)
- [Socket API overview](/docs/daemon/socket-api)
10 changes: 10 additions & 0 deletions scripts/check-guides-docs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const requiredPages = [
'set-up-memory',
'fix-a-failed-install',
'upgrade-coven',
'script-the-api',
];

const requiredMentions = [
Expand Down Expand Up @@ -53,6 +54,11 @@ const requiredMentions = [
'coven --version',
'/api/v1/capabilities',
'coven sessions --all --plain',
'/api/v1/sessions',
'/api/v1/events',
'nextCursor',
'error.code',
'session_not_found',
];

function fail(message) {
Expand Down Expand Up @@ -148,4 +154,8 @@ if (!readFileSync(join(guidesRoot, 'upgrade-coven.mdx'), 'utf8').includes('/docs
fail('upgrade-coven guide must link to the recovery and upgrades reference.');
}

if (!readFileSync(join(guidesRoot, 'script-the-api.mdx'), 'utf8').includes('/docs/reference/api')) {
fail('script-the-api guide must link to the API reference.');
}

console.log('Guides docs check passed.');