Skip to content

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.

POST /api/projects
{ "name": "My Project" }

Response (201):

{
"id": "uuid",
"name": "My Project",
"repos": [],
"created_at": "2025-01-01T00:00:00Z"
}
GET /api/projects

Response (200): Array of project objects (with repos).

GET /api/projects/{id}

Response (200): Project object with repos.

DELETE /api/projects/{id}

Response (204): No content.

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"
}
DELETE /api/projects/{project_id}/repos/{repo_id}

Response (204): No content.


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:

FieldDefault
cli_name"claude-code"
allowed_tools"Read,Edit,Write,Bash,Glob,Grep"
max_turns100
provider_config{}
role"builder"

Response (201): Agent object.

GET /api/agents/{id}

Response (200): Agent object.

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 /api/agents/{id}

Response (204): No content.

GET /api/projects/{project_id}/agents

Response (200): Array of agent objects.


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
}
GET /api/runs

Response (200): Array of run objects.

GET /api/runs/{id}

Response (200): Run object.

DELETE /api/runs/{id}

Cannot delete a running run. Cleans up worktrees, branches, events, and log files.

Response (204): No content.

POST /api/runs/{id}/cancel

Kills the CLI process and marks the run as cancelled. Only works on running runs.

Response (200): OK.

POST /api/runs/{id}/pause

Kills the CLI process, checkpoints uncommitted changes, and marks as paused.

Response (200): OK.

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.

POST /api/runs/{id}/notify
{ "notify": true }

Response (200): OK.


GET /api/runs/{id}/events

Response (200):

[
{
"id": 1,
"run_id": "uuid",
"sequence": 1,
"event_type": "run.created",
"payload": { "task": "...", "source_branch": "HEAD" },
"created_at": "..."
}
]
GET /api/runs/{id}/events/stream?last_event_id=0

Server-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.
TypeSourceDescription
run.createdLifecycleRun created with task and branch info
run.startedLifecycleRun marked as running
run.completedLifecycleRun finished
run.failedLifecycleRun failed with reason
run.cancelledLifecycleRun cancelled by user
run.pausedLifecycleRun paused
run.resultAdapterFinal metrics (tokens, cost, session_id)
session.initAdapterSession ID and CLI version captured
agent.tokenAdapterStreaming text token
agent.messageAdapterComplete agent message
agent.tool_callHookTool invocation (name + input)
agent.tool_resultHookTool result (output or error)
agent.needs_attentionHookPermission prompt or idle prompt
agent.subagent_startHookSubagent spawned
agent.subagent_stopHookSubagent stopped
user.messageAPIUser sent a continuation message

GET /api/runs/{id}/changes

Returns diff of all changes made by a run.

GET /api/runs/{id}/diff-stats

Lightweight file/insertion/deletion counts.

POST /api/runs/{id}/commit
{ "message": "feat: add auth" }
POST /api/runs/{id}/push
POST /api/runs/{id}/pull-request
{
"title": "feat: add auth",
"body": "Implements login flow"
}
POST /api/runs/{id}/rename-branch
{ "name": "feat/auth" }
POST /api/runs/{id}/accept

Pushes the run branch.

POST /api/runs/{id}/revert

Resets worktrees to base commit.


GET /api/projects/{id}/branches

Lists all branches across all repos with metadata (ahead/behind, push status, run association).

DELETE /api/projects/{id}/branches?branch=<name>&repo_id=<uuid>
POST /api/projects/{id}/branches/merge?branch=<name>&repo_id=<uuid>
POST /api/projects/{id}/branches/rebase?branch=<name>&repo_id=<uuid>
GET /api/projects/{id}/branches/pr-status

Fetches PR info for pushed branches (makes network calls — use lazily).


GET /api/runs/{id}/tasks

Reconstructed from TaskCreate/TaskUpdate hook events.


GET /api/settings/models
PUT /api/settings/models

Provider and model configuration. See Configuration for the schema.

GET /api/settings/notifications
PUT /api/settings/notifications

Discord webhook and notification preferences.


POST /api/runs/{id}/hook

Called by CLI hooks. Receives the raw hook payload as JSON. See CLI Hooks Reference for details.


GET /api/terminal?run_id=<uuid>

WebSocket endpoint for terminal access. Query parameters:

ParameterTypeDefaultDescription
run_idstringRun ID (persistent PTY mode)
cwdstring$HOMEWorking directory (ephemeral mode)
clistringclaudeCLI to launch (ephemeral mode)
taskstringInitial task (ephemeral -p mode)
colsint120Terminal columns
rowsint30Terminal rows

With run_id: attaches to the run’s persistent PTY session. Without: creates an ephemeral terminal.


GET /api/health

Response (200): "ok"


GET /api/runs/{id}/logs

Returns raw log file content for a run (plain text).