WebSocket API Reference¶
AI Code UI uses WebSocket connections for real-time communication. This document describes the WebSocket protocol and message formats.
WebSocket Endpoints¶
| Endpoint | Purpose |
|---|---|
/ws |
Chat messages and AI interactions |
/shell |
Interactive terminal (PTY) sessions |
Connection¶
Chat WebSocket (/ws)¶
const ws = new WebSocket('ws://localhost:3001/ws');
ws.onopen = () => {
console.log('Connected to chat WebSocket');
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
// Handle message
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('WebSocket closed');
};
Shell WebSocket (/shell)¶
const shell = new WebSocket('ws://localhost:3001/shell');
shell.onopen = () => {
// Initialize terminal session
shell.send(JSON.stringify({
type: 'init',
projectPath: '/path/to/project',
sessionId: 'session-id',
provider: 'claude'
}));
};
Chat WebSocket Messages¶
Client → Server¶
Start Claude Session¶
{
"type": "claude-command",
"command": "start",
"options": {
"projectPath": "/path/to/project",
"sessionId": "session-id",
"prompt": "User message",
"model": "claude-sonnet-4-5-20250929",
"contextWindow": 160000
}
}
Start Cursor Session¶
{
"type": "cursor-command",
"command": "start",
"options": {
"projectPath": "/path/to/project",
"sessionId": "session-id",
"prompt": "User message",
"model": "gpt-5.2"
}
}
Start Codex Session¶
{
"type": "codex-command",
"command": "start",
"options": {
"projectPath": "/path/to/project",
"sessionId": "session-id",
"prompt": "User message",
"model": "gpt-5.2"
}
}
Abort Session¶
Permission Response (Claude)¶
{
"type": "claude-permission-response",
"requestId": "request-id",
"allow": true,
"remember": false
}
Continue Conversation¶
Server → Client¶
Claude Response Events¶
{
"type": "claude-response",
"data": {
"type": "tool_use",
"tool": "bash",
"input": {
"command": "ls -la"
}
}
}
{
"type": "claude-response",
"data": {
"type": "tool_result",
"tool": "bash",
"output": "file1.js\nfile2.js"
}
}
Permission Request (Claude)¶
{
"type": "claude-permission-request",
"requestId": "request-id",
"tool": "bash",
"input": {
"command": "rm -rf node_modules"
},
"description": "Execute bash command"
}
Cursor Response Events¶
Codex Response Events¶
Session Events¶
{
"type": "session-ended",
"sessionId": "session-id",
"provider": "claude",
"reason": "completed|aborted|error"
}
Error Events¶
Projects Updated¶
{
"type": "projects-updated",
"projects": [
{
"path": "/path/to/project",
"name": "project-name",
"sessions": []
}
]
}
Token Usage¶
{
"type": "token-usage",
"usage": {
"inputTokens": 1000,
"outputTokens": 500,
"totalTokens": 1500,
"contextWindow": 160000
}
}
Shell WebSocket Messages¶
Client → Server¶
Initialize Terminal¶
{
"type": "init",
"projectPath": "/path/to/project",
"sessionId": "session-id",
"provider": "claude"
}
Send Input¶
Resize Terminal¶
Server → Client¶
Terminal Output¶
Terminal Ready¶
Terminal Error¶
Terminal Exit¶
Event Flow Examples¶
Complete Chat Flow¶
Client Server AI Provider
│ │ │
│ claude-command (start) │ │
├──────────────────────────────►│ │
│ │ Start session │
│ ├─────────────────────────────────►│
│ │ │
│ │ Stream: text │
│ │◄─────────────────────────────────┤
│ claude-response (text) │ │
│◄──────────────────────────────┤ │
│ │ │
│ │ Stream: tool_use │
│ │◄─────────────────────────────────┤
│ claude-permission-request │ │
│◄──────────────────────────────┤ │
│ │ │
│ claude-permission-response │ │
├──────────────────────────────►│ │
│ │ Execute tool │
│ ├─────────────────────────────────►│
│ │ │
│ │ Stream: tool_result │
│ │◄─────────────────────────────────┤
│ claude-response (tool_result) │ │
│◄──────────────────────────────┤ │
│ │ │
│ │ Stream: end │
│ │◄─────────────────────────────────┤
│ session-ended │ │
│◄──────────────────────────────┤ │
Tool Approval Flow¶
Client Server
│ │
│ │ Tool requires approval
│ │
│ claude-permission-request │
│◄──────────────────────────────┤
│ │
│ [User reviews in UI] │
│ │
│ claude-permission-response │
│ {allow: true, remember: true} │
├──────────────────────────────►│
│ │
│ │ Execute tool
│ │ (future uses auto-approved)
Connection Management¶
Reconnection Strategy¶
The frontend implements automatic reconnection:
// From src/utils/websocket.js
const RECONNECT_DELAY = 1000;
const MAX_RECONNECT_DELAY = 30000;
function reconnect() {
const delay = Math.min(
RECONNECT_DELAY * Math.pow(2, reconnectAttempts),
MAX_RECONNECT_DELAY
);
setTimeout(() => {
connect();
reconnectAttempts++;
}, delay);
}
Heartbeat¶
The server sends periodic heartbeat messages:
Clients should respond within 30 seconds or the connection may be terminated.
Error Handling¶
Error Message Format¶
{
"type": "error",
"error": "Human-readable error message",
"code": "ERROR_CODE",
"details": {
"field": "additional context"
}
}
Common Error Codes¶
| Code | Description |
|---|---|
INVALID_MESSAGE |
Malformed message format |
UNKNOWN_COMMAND |
Unrecognized message type |
SESSION_NOT_FOUND |
Session doesn't exist |
PROVIDER_ERROR |
AI provider returned error |
PERMISSION_DENIED |
Tool execution denied |
TIMEOUT |
Operation timed out |
CONNECTION_ERROR |
Connection-related error |
Best Practices¶
Message Handling¶
- Always validate message types before processing
- Handle unknown message types gracefully
- Implement timeout handling for requests
- Buffer messages during reconnection
Performance¶
- Avoid sending large payloads (>1MB)
- Implement client-side rate limiting
- Use message batching when appropriate
- Clean up listeners on disconnect
Security¶
- Validate all incoming messages
- Sanitize user input before sending
- Don't trust client-provided session IDs
- Implement proper authentication