The wiki was written for seven run modes and never received Grok Build, DeepSeek Harness or OMP. They now appear everywhere the others do: the modes table and per-CLI notes, install commands, environment prefixes, the Quick Start table, the requirements rows, the vocabulary, and every "seven modes" count. The 1.27 to 1.29.0 changes land on the pages that own them: attaching a case to an existing container, multi-case adoption and the copy-a-case picker (Docker Cases); file reads over ssh in remote cases and what stays unavailable (Remote SSH Sessions, Working With Files, Security); single-page app routing, frame recovery, localhost links as tabs and the egress guard (Web Tabs); DeepSeek as the one non-Claude mode with real stop/blocked signals and Approvals items, Codex's own work detection, last-response, the model-endpoint routes and refreshed counts (HTTP API, Driving From An Agent, Hooks, Notifications, Keeping Agents Running, Core Concepts); Shift+drag, right-click copy, Auto Copy, the Ctrl+Z guard, font weight, the vertical rail and its activity sort (Keyboard Shortcuts, Input And Voice, The Dashboard, Settings Reference); the 600px phone cutoff, Codex shift arrows and iPhone Duo (Mobile Guide); the Docker Compose route and its update rule (Installation, Running As A Service); four new symptom entries and a "which CLIs" question (Troubleshooting, FAQ). Custom model endpoints are deliberately left to #430, which adds that page and edits Agent CLIs, Settings Reference and the sidebar; these edits stay out of the regions #430, #428 and #376 touch, and all three still merge cleanly on top. Both READMEs: the web-tab menu entry is labelled "Add URL" in the UI, not "Add dashboard". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
8.8 KiB
HTTP API
Codeman's HTTP and SSE API is a stable contract. Everything the dashboard does goes through it, so anything the dashboard can do, a script can do.
This page is the orientation. The complete specification, including every wait semantic and
the SSE catalogue, is
docs/api-reference.md.
What is stable
Covered by semantic versioning: endpoint paths under /api/v1, the response envelope,
errorCode values, and SSE event names.
Not covered, and free to change in a patch release: on-disk state files, internal modules, and anything marked experimental. The full statement is in Versioning.
/api/v1/* is a versioned alias of /api/*. Prefer the versioned form in anything you
intend to keep.
The envelope
{ "success": true, "data": { } }
{ "success": false, "error": "human readable", "errorCode": "NOT_FOUND" }
A few legacy GET handlers return bare bodies rather than the envelope, so a robust client
reads body.data ?? body.
Branch on errorCode, which is stable. The HTTP status is reliable too:
errorCode |
HTTP | Meaning |
|---|---|---|
INVALID_INPUT |
400 | Malformed request or failed validation. |
UNAUTHORIZED |
401 | Authentication required or failed. |
NOT_FOUND |
404 | No such resource. |
SESSION_BUSY |
409 | The session is busy. |
CONFLICT |
409 | Conflicts with current state. |
ALREADY_EXISTS |
409 | Resource already exists. |
OPERATION_FAILED |
422 | Well formed, could not be completed. |
RATE_LIMITED |
429 | Too many requests. |
INTERNAL_ERROR |
500 | Unexpected server error. |
New error codes are non-breaking. Removing or renaming one is a major change.
A 401 is the bare string Unauthorized, not the envelope. Piping it into jq throws
a parse error rather than showing the failure, so check the status first.
Authentication
With no password set, and the default loopback bind, there is none. With CODEMAN_PASSWORD
set, use HTTP Basic or the session cookie:
curl -s -u admin:"$CODEMAN_PASSWORD" "$API/api/sessions"
A missing Origin header is allowed, so curl and CLI tools work unchanged. A
present-but-foreign origin is rejected by the CSRF guard. On an HTTPS install with the
self-signed certificate, add -k.
Endpoint map
Roughly 235 handlers across 26 route modules. By domain:
| Domain | Handlers | Covers |
|---|---|---|
| System | 56 | Status, settings, digest, updates, tunnel. |
| Sessions | 34 | Create, input, terminal, wait, last response, kill. |
| Cases | 34 | Create, link, clone, remote and docker cases. |
| Files | 17 | Preview, edit, raw, attachments, path picker. |
| Orchestrator | 10 | Plans and phases. |
| Ralph | 9 | Loop control and configuration. |
| Cron | 9 | Jobs and run history. |
| Admin | 8 | Multi-user administration. |
| Plan | 8 | Plan orchestration. |
| Respawn | 7 | Respawn configuration and presets. |
| Webviews | 6 | Saved dashboards, plus the proxy. |
| Mux | 5 | tmux operations. |
| Custom model endpoints | 5 | Saved OpenAI-compatible endpoints, and applying one to a session. |
| Push | 4 | Web push subscriptions. |
| Read My Mind | 4 | Intent profiles and prediction. |
| Scheduled | 4 | The legacy scheduled-run concept. |
| Approvals | 4 | The inbox, answering, acknowledging. |
| Tab layout | 2 | Named tab groups per owner. |
| Teams, me, search, hooks, clipboard, telemetry, voice, ws | 1-2 each |
Each route module documents its own endpoints in its file header.
Long-polling instead of polling
Three calls block until something happens, so an agent driving Codeman from a shell can wait rather than spin:
| Call | Blocks until |
|---|---|
GET /api/v1/sessions/:id/wait |
One of a set of lifecycle signals fires. |
GET /api/v1/sessions/:id/wait-output |
A literal string appears in the session's output. |
POST /api/v1/sessions/:id/input + wait |
The input is delivered and then a signal fires. |
Three semantics that break callers who assume otherwise:
- A timeout is
200, not an error. It answers withwait.timedOut: true. Loop over short waits; a single long call gets cut by tunnels and proxies. - Send-and-wait is not a POST followed by a wait. It registers the waiter before writing, which closes the window where a separate wait sees the session still idle from the previous turn and answers instantly about the wrong turn.
- Signals are edge triggered with no history. One that fires with no waiter registered is unobservable afterwards. Fan-outs must register their waits as they dispatch.
wait-output matches a literal substring, never a regex. That is deliberate: no regex
means no catastrophic backtracking on attacker-influenced output.
Only claude and deepseek sessions emit stop and blocked: Claude's come from Claude
Code hooks, DeepSeek's from the harness reporting its state to Codeman. Shell and the other
external CLI sessions accept idle, working, and exit.
SSE
GET /api/events is the live event stream. 158 event names, kept in sync between server and
client with a test that fails on drift.
The heartbeat is a named sse:heartbeat event rather than an SSE comment, because
comments are invisible to EventSource by specification and a client could not observe
them. That is what lets the browser detect a stream that has silently stopped delivering.
const es = new EventSource('/api/events');
es.addEventListener('session:created', (e) => console.log(JSON.parse(e.data)));
Quick examples
API="${CODEMAN_API_URL:-http://localhost:3000}"
curl -s "$API/api/status" | jq # whole-system snapshot
curl -s "$API/api/sessions" | jq '.data[].name' # live sessions
curl -s "$API/api/sessions/unified" | jq # live + historical, deduped
curl -s "$API/api/subagents" | jq # background agents
curl -s "$API/api/search?q=deploy" | jq # cross-session search
# with ID set to a session id:
curl -s "$API/api/sessions/$ID/last-response" | jq -r '.data.text' # last answer, from the transcript (claude, codex, deepseek)
curl -s "$API/api/model-endpoints" | jq # saved custom OpenAI-compatible endpoints
curl -s -X POST "$API/api/sessions/$ID/custom-model" -H 'Content-Type: application/json' \
-d '{"endpointId":"local-llama","modelId":"qwen3-27b"}' | jq # restart the CLI on that endpoint; {"clear":true} undoes it
Limits
| Limit | Default |
|---|---|
| Max sessions | 50 |
| Max agent windows | 500 |
| Max SSE clients | 100 |
| Terminal buffer | 32 MB per session |
| Text payload | 1 MB |
| Wait timeout ceiling | 600 s, and the response tells you what was applied |
Most are environment-overridable. See src/config/.
Read next
- Driving Codeman From An Agent - the practical version, with recipes.
- Hooks And Integrations - events flowing back into Codeman.
- Versioning - what the version number promises.
docs/api-reference.md- the full specification.