Skip to main content

WebSocket API

The WebSocket API provides real-time status updates for monitored sessions.

Connection

Connect to the WebSocket server:

ws://localhost:3000

The connection uses the same port as the HTTP server.

Message Format

All messages are JSON-encoded with a type field indicating the message type.

interface WebSocketMessage {
type: string;
[key: string]: any;
}

Server Messages

claude_status_updated

Sent when a session's status changes.

{
"type": "claude_status_updated",
"session": {
"name": "my-project",
"claude": {
"primary": "active",
"detail": "thinking",
"health": "ALIVE",
"timestamp": "2024-01-15T10:30:00.000Z",
"unchangedCount": 0
}
}
}

Fields

FieldTypeDescription
type"claude_status_updated"Message type identifier
session.namestringSession identifier
session.claude.primarystringPrimary status: idle, active, waiting, stuck, dead
session.claude.detailstring | nullDetail status
session.claude.healthstringHealth: ALIVE, STUCK, DEAD, RECOVERED
session.claude.timestampstringISO 8601 timestamp
session.claude.unchangedCountnumberConsecutive unchanged checks

session_created

Sent when a new session is added to monitoring.

{
"type": "session_created",
"session": {
"name": "my-project",
"claude": {
"primary": "idle",
"detail": "waiting_input",
"health": "ALIVE",
"timestamp": "2024-01-15T10:30:00.000Z",
"unchangedCount": 0
}
}
}

session_deleted

Sent when a session is removed from monitoring.

{
"type": "session_deleted",
"sessionName": "my-project"
}

sessions_list

Sent on connection with the current state of all sessions.

{
"type": "sessions_list",
"sessions": [
{
"name": "project-a",
"claude": { ... }
},
{
"name": "project-b",
"claude": { ... }
}
]
}

error

Sent when an error occurs.

{
"type": "error",
"message": "Error description"
}

Client Messages

Clients can send messages to request actions.

request_sessions

Request the current list of all sessions.

{
"type": "request_sessions"
}

Response: Server sends sessions_list message.

Detail Status Values

Activity Details (when primary is active)

ValueDescription
thinkingClaude is processing the request
using_toolsClaude is executing tool calls
respondingClaude is generating response text
compactingClaude is compressing conversation history

Waiting Details (when primary is waiting)

ValueDescription
permissionClaude needs permission (Yes/No prompt)
questionClaude has asked a question

Idle Details (when primary is idle)

ValueDescription
readyInitial ready state
waiting_inputWaiting for user command

Connection Example

Browser JavaScript

const ws = new WebSocket('ws://localhost:3000');

ws.onopen = () => {
console.log('Connected to Claude Session Tools');
};

ws.onmessage = (event) => {
const message = JSON.parse(event.data);

switch (message.type) {
case 'sessions_list':
console.log('Current sessions:', message.sessions);
break;

case 'claude_status_updated':
console.log(`Session ${message.session.name}: ${message.session.claude.primary}`);
break;

case 'session_created':
console.log(`New session: ${message.session.name}`);
break;

case 'session_deleted':
console.log(`Session removed: ${message.sessionName}`);
break;
}
};

ws.onerror = (error) => {
console.error('WebSocket error:', error);
};

ws.onclose = () => {
console.log('Disconnected from server');
};

React Hook

import { useState, useEffect, useCallback, useRef } from 'react';

interface Session {
name: string;
claude: ClaudeStatus;
}

export function useWebSocket() {
const [sessions, setSessions] = useState<Session[]>([]);
const [connected, setConnected] = useState(false);
const wsRef = useRef<WebSocket | null>(null);

useEffect(() => {
const ws = new WebSocket('ws://localhost:3000');
wsRef.current = ws;

ws.onopen = () => setConnected(true);
ws.onclose = () => setConnected(false);

ws.onmessage = (event) => {
const message = JSON.parse(event.data);

switch (message.type) {
case 'sessions_list':
setSessions(message.sessions);
break;

case 'claude_status_updated':
setSessions(prev =>
prev.map(s =>
s.name === message.session.name ? message.session : s
)
);
break;

case 'session_created':
setSessions(prev => [...prev, message.session]);
break;

case 'session_deleted':
setSessions(prev =>
prev.filter(s => s.name !== message.sessionName)
);
break;
}
};

return () => ws.close();
}, []);

return { sessions, connected };
}

Reconnection

The WebSocket connection may drop due to network issues. Implement reconnection logic:

function createWebSocket() {
const ws = new WebSocket('ws://localhost:3000');

ws.onclose = () => {
console.log('Connection closed, reconnecting in 3s...');
setTimeout(createWebSocket, 3000);
};

ws.onerror = (error) => {
console.error('WebSocket error:', error);
ws.close();
};

return ws;
}

Message Frequency

Status updates are sent:

  • Immediately when status changes
  • On each file system change detection (approximately every 200ms during activity)
  • Once per second during stable states (for unchanged count updates)

For high-frequency updates, consider debouncing on the client side if needed.