API Reference
All endpoints are prefixed with /api/. The server runs on http://127.0.0.1:3000 by default.
Responses are JSON. Errors return a status code with a plain text message.
Projects
Section titled “Projects”Create Project
Section titled “Create Project”POST /api/projects{ "name": "My Project" }Response (201):
{ "id": "uuid", "name": "My Project", "repos": [], "created_at": "2025-01-01T00:00:00Z"}List Projects
Section titled “List Projects”GET /api/projectsResponse (200): Array of project objects (with repos).
Get Project
Section titled “Get Project”GET /api/projects/{id}Response (200): Project object with repos.
Delete Project
Section titled “Delete Project”DELETE /api/projects/{id}Response (204): No content.
Add Repo
Section titled “Add Repo”POST /api/projects/{id}/repos{ "name": "backend", "repo_path": "/absolute/path/to/repo"}The path must exist and contain a .git directory.
Response (201):
{ "id": "uuid", "name": "backend", "repo_path": "/absolute/path/to/repo"}Remove Repo
Section titled “Remove Repo”DELETE /api/projects/{project_id}/repos/{repo_id}Response (204): No content.
Agents
Section titled “Agents”Create Agent
Section titled “Create Agent”POST /api/agents{ "project_id": "uuid", "name": "Feature Builder", "cli_name": "claude-code", "model": "claude-sonnet-4-6", "instructions": "You are a senior developer...", "allowed_tools": "Read,Edit,Write,Bash,Glob,Grep", "max_turns": 100, "provider_config": {}, "role": "builder"}All fields except project_id and name have defaults:
| Field | Default |
|---|---|
cli_name | "claude-code" |
allowed_tools | "Read,Edit,Write,Bash,Glob,Grep" |
max_turns | 100 |
provider_config | {} |
role | "builder" |
Response (201): Agent object.
Get Agent
Section titled “Get Agent”GET /api/agents/{id}Response (200): Agent object.
Update Agent
Section titled “Update Agent”PUT /api/agents/{id}Partial update — only include fields you want to change:
{ "name": "Renamed Agent", "max_turns": 50}Response (200): Updated agent object.
Delete Agent
Section titled “Delete Agent”DELETE /api/agents/{id}Response (204): No content.
List Agents by Project
Section titled “List Agents by Project”GET /api/projects/{project_id}/agentsResponse (200): Array of agent objects.
Create Run
Section titled “Create Run”POST /api/runs{ "agent_id": "uuid", "task": "Implement user authentication", "source_branch": "HEAD"}Creates the run, sets up worktrees, configures hooks, and spawns the CLI in a PTY. The source_branch defaults to "HEAD".
Response (201):
{ "id": "uuid", "project_id": "uuid", "agent_id": "uuid", "task": "Implement user authentication", "status": "queued", "source_branch": "HEAD", "run_branch": "abbado/run-a1b2c3d4", "cli_name": "claude-code", "created_at": "...", "updated_at": "...", "tokens_in": 0, "tokens_out": 0, "cost_usd": 0.0, "parent_run_id": null, "notify": false}List Runs
Section titled “List Runs”GET /api/runsResponse (200): Array of run objects.
Get Run
Section titled “Get Run”GET /api/runs/{id}Response (200): Run object.
Delete Run
Section titled “Delete Run”DELETE /api/runs/{id}Cannot delete a running run. Cleans up worktrees, branches, events, and log files.
Response (204): No content.
Cancel Run
Section titled “Cancel Run”POST /api/runs/{id}/cancelKills the CLI process and marks the run as cancelled. Only works on running runs.
Response (200): OK.
Pause Run
Section titled “Pause Run”POST /api/runs/{id}/pauseKills the CLI process, checkpoints uncommitted changes, and marks as paused.
Response (200): OK.
Continue Run
Section titled “Continue Run”POST /api/runs/{id}/continue{ "message": "Please also add tests for the login flow"}Resumes a completed/paused/failed/cancelled run. Requires the run to have a session_id. Re-creates worktrees if needed and launches the CLI with session resume.
Response (200): Updated run object.
Toggle Notifications
Section titled “Toggle Notifications”POST /api/runs/{id}/notify{ "notify": true }Response (200): OK.
Events
Section titled “Events”Get Run Events
Section titled “Get Run Events”GET /api/runs/{id}/eventsResponse (200):
[ { "id": 1, "run_id": "uuid", "sequence": 1, "event_type": "run.created", "payload": { "task": "...", "source_branch": "HEAD" }, "created_at": "..." }]Stream Events (SSE)
Section titled “Stream Events (SSE)”GET /api/runs/{id}/events/stream?last_event_id=0Server-Sent Events stream. Replays events after last_event_id, then streams live events. Uses keep-alive to maintain the connection.
Each SSE event has:
id: event database ID (use for reconnect)data: JSON with event_type, payload, etc.
Event Types
Section titled “Event Types”| Type | Source | Description |
|---|---|---|
run.created | Lifecycle | Run created with task and branch info |
run.started | Lifecycle | Run marked as running |
run.completed | Lifecycle | Run finished |
run.failed | Lifecycle | Run failed with reason |
run.cancelled | Lifecycle | Run cancelled by user |
run.paused | Lifecycle | Run paused |
run.result | Adapter | Final metrics (tokens, cost, session_id) |
session.init | Adapter | Session ID and CLI version captured |
agent.token | Adapter | Streaming text token |
agent.message | Adapter | Complete agent message |
agent.tool_call | Hook | Tool invocation (name + input) |
agent.tool_result | Hook | Tool result (output or error) |
agent.needs_attention | Hook | Permission prompt or idle prompt |
agent.subagent_start | Hook | Subagent spawned |
agent.subagent_stop | Hook | Subagent stopped |
user.message | API | User sent a continuation message |
Changes & Git
Section titled “Changes & Git”Get Changes
Section titled “Get Changes”GET /api/runs/{id}/changesReturns diff of all changes made by a run.
Get Diff Stats
Section titled “Get Diff Stats”GET /api/runs/{id}/diff-statsLightweight file/insertion/deletion counts.
Commit
Section titled “Commit”POST /api/runs/{id}/commit{ "message": "feat: add auth" }POST /api/runs/{id}/pushCreate PR/MR
Section titled “Create PR/MR”POST /api/runs/{id}/pull-request{ "title": "feat: add auth", "body": "Implements login flow"}Rename Branch
Section titled “Rename Branch”POST /api/runs/{id}/rename-branch{ "name": "feat/auth" }Accept Changes
Section titled “Accept Changes”POST /api/runs/{id}/acceptPushes the run branch.
Revert Changes
Section titled “Revert Changes”POST /api/runs/{id}/revertResets worktrees to base commit.
Branches
Section titled “Branches”List Branches
Section titled “List Branches”GET /api/projects/{id}/branchesLists all branches across all repos with metadata (ahead/behind, push status, run association).
Delete Branch
Section titled “Delete Branch”DELETE /api/projects/{id}/branches?branch=<name>&repo_id=<uuid>Merge Branch
Section titled “Merge Branch”POST /api/projects/{id}/branches/merge?branch=<name>&repo_id=<uuid>Rebase Branch
Section titled “Rebase Branch”POST /api/projects/{id}/branches/rebase?branch=<name>&repo_id=<uuid>PR Status
Section titled “PR Status”GET /api/projects/{id}/branches/pr-statusFetches PR info for pushed branches (makes network calls — use lazily).
Get Tasks
Section titled “Get Tasks”GET /api/runs/{id}/tasksReconstructed from TaskCreate/TaskUpdate hook events.
Settings
Section titled “Settings”Models
Section titled “Models”GET /api/settings/modelsPUT /api/settings/modelsProvider and model configuration. See Configuration for the schema.
Notifications
Section titled “Notifications”GET /api/settings/notificationsPUT /api/settings/notificationsDiscord webhook and notification preferences.
Hook Endpoint
Section titled “Hook Endpoint”POST /api/runs/{id}/hookCalled by CLI hooks. Receives the raw hook payload as JSON. See CLI Hooks Reference for details.
Terminal (WebSocket)
Section titled “Terminal (WebSocket)”GET /api/terminal?run_id=<uuid>WebSocket endpoint for terminal access. Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
run_id | string | — | Run ID (persistent PTY mode) |
cwd | string | $HOME | Working directory (ephemeral mode) |
cli | string | claude | CLI to launch (ephemeral mode) |
task | string | — | Initial task (ephemeral -p mode) |
cols | int | 120 | Terminal columns |
rows | int | 30 | Terminal rows |
With run_id: attaches to the run’s persistent PTY session. Without: creates an ephemeral terminal.
Health
Section titled “Health”GET /api/healthResponse (200): "ok"
GET /api/runs/{id}/logsReturns raw log file content for a run (plain text).