Skip to content

WebSocket API

Tide Commander uses a single WebSocket connection for all real-time updates. The client connects to ws://localhost:5174 (or whichever port is configured). All messages are JSON with a type discriminant and a payload object.

Connecting

const ws = new WebSocket('ws://localhost:5174');
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg.type, msg.payload);
};

Message direction

  • S→C — Server pushes to all connected clients
  • C→S — Client sends to server

Agent lifecycle (S→C)

TypeDescription
agents_updateFull agent list sync, sent on connect
agent_createdNew agent was created
agent_updatedAgent properties changed (status, position, context, etc.)
agent_deletedAgent was removed — payload: { id }

Example agent_updated:

{
"type": "agent_updated",
"payload": {
"id": "abc123",
"name": "Scout Alpha",
"status": "working",
"currentTool": "Bash",
"contextUsed": 12500,
"contextLimit": 200000
}
}

Output streaming (S→C)

Claude Code streams its output token-by-token. Each chunk arrives as an output message:

{
"type": "output",
"payload": {
"agentId": "abc123",
"text": "Analyzing the codebase...",
"isStreaming": true,
"timestamp": 1716000000000,
"toolName": "Bash",
"toolInput": { "command": "find . -name '*.ts'" },
"toolOutput": "src/index.ts\nsrc/app.ts\n"
}
}

isStreaming: false marks the final chunk of a turn. Optional toolName / toolInput / toolOutput are parsed from the stream for the debugger panel.


Context updates (S→C)

Lightweight real-time context usage update, emitted during streaming:

{
"type": "context_update",
"payload": {
"agentId": "abc123",
"contextUsed": 45000,
"contextLimit": 200000
}
}
TypeDescription
context_updateLive context usage during a streaming turn
context_statsFull context breakdown (after /context command)
compacting_statusAutocompact active / finished — payload: { agentId, active }

Notifications (S→C)

Sent when an agent calls POST /api/notify:

{
"type": "agent_notification",
"payload": {
"id": "notif_xyz",
"agentId": "abc123",
"agentName": "Scout Alpha",
"agentClass": "scout",
"title": "Task Complete",
"message": "Build succeeded",
"timestamp": 1716000000000
}
}

Boss / delegation (S→C and C→S)

Client → Server

TypeDescription
spawn_boss_agentCreate a new boss agent
assign_subordinatesAdd subordinates to a boss
remove_subordinateRemove one subordinate from a boss
send_boss_commandSend a task command to a boss for delegation
request_delegation_historyRequest past delegation decisions

assign_subordinates example:

{
"type": "assign_subordinates",
"payload": {
"bossId": "boss123",
"subordinateIds": ["sub1", "sub2"]
}
}

Server → Client

TypeDescription
delegation_decisionBoss decided which subordinate handles a task
boss_subordinates_updatedSubordinate list changed
delegation_historyPast delegation records for a boss
boss_spawned_agentBoss spawned a new subordinate
agent_task_startedSubordinate started a delegated task
agent_task_outputStreaming output from a subordinate’s delegated task
agent_task_completedSubordinate finished — payload: { bossId, subordinateId, success }

Exec tasks (S→C)

When an agent calls POST /api/exec, output is streamed to all clients:

TypePayload fields
exec_task_startedtaskId, agentId, agentName, command, cwd
exec_task_outputtaskId, agentId, output, isError?
exec_task_completedtaskId, agentId, exitCode, success

Permissions (C→S and S→C)

When an agent requests a tool permission, the server sends a permission_request to all clients. The UI responds with a permission_response:

{
"type": "permission_response",
"payload": {
"agentId": "abc123",
"permissionId": "perm_xyz",
"granted": true
}
}

Miscellaneous (S→C)

TypeDescription
activityHuman-readable activity log entry
errorServer-side error — payload: { message }
focus_agentUI should focus/scroll to an agent
work_plan_createdNew work plan created
work_plan_updatedWork plan changed
work_plan_deletedWork plan removed
work_plans_updateFull work plan sync on connect