Claude Code Server-Sent Events API Guide
Server-Sent Events (SSE) provide a simple, standards-based way to push real-time updates from a server to a client over HTTP. Unlike WebSockets, SSE works over a single persistent connection and automatically handles reconnection, making it ideal for streaming logs, live dashboards, and notification systems. This guide shows you how to implement SSE with Claude Code, with practical examples you can apply to your projects.
How Server-Sent Events Work
SSE relies on the Content-Type: text/event-stream header. The server sends events in a specific format:
data: {"message": "processing"}
data: {"message": "complete"}
event: done
Each event consists of optional fields: event, data, id, and retry. The data field contains your payload, and the event field lets you name events for routing on the client.
Basic Server Implementation
Create a simple SSE endpoint using any backend framework. Here’s a Python Flask example:
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
@app.route('/stream')
def stream():
def generate():
for i in range(10):
yield f"data: {i}\n\n"
time.sleep(1)
return Response(generate(), mimetype='text/event-stream')
The yield pattern streams each message immediately rather than waiting for the full response. For production use with the pdf skill or other document processing workflows, you might stream progress updates as files are processed.
Client-Side Consumption
On the client side, use the native EventSource API:
const source = new EventSource('/stream');
source.onmessage = (event) => {
console.log('Received:', event.data);
};
source.addEventListener('progress', (event) => {
updateProgressBar(JSON.parse(event.data));
});
source.onerror = () => {
console.log('Connection lost, reconnecting...');
};
The EventSource API automatically handles reconnection and sends the last event ID, allowing your server to resume from where the connection dropped. This makes SSE particularly reliable for long-running operations.
Combining SSE with Claude Skills
When building AI-powered applications with Claude Code, SSE becomes valuable for streaming responses. Many Claude skills work well with streaming architectures:
- The webapp-testing skill can validate SSE endpoints, checking that connections open correctly and events stream as expected
- The tdd skill helps you write integration tests for your streaming endpoints, ensuring events fire in the correct order
- The frontend-design skill can suggest UI patterns for displaying real-time updates from SSE streams
Here’s how you might stream Claude Code responses to a client:
async function streamClaudeResponse(prompt) {
const response = await fetch('/api/claude/stream', {
method: 'POST',
body: JSON.stringify({ prompt })
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
// Parse SSE format and append to UI
displayChunk(chunk);
}
}
Event Routing and Filtering
For complex applications, use named events to route messages to different handlers:
@app.route('/updates')
def updates():
def generate():
# Send status updates
yield "event: status\ndata: {\"stage\": \"loading\"}\n\n"
# Send progress
for i in range(100):
yield f"event: progress\ndata: {i}\n\n"
# Send completion
yield "event: complete\ndata: {}\n\n"
return Response(generate(), mimetype='text/event-stream')
Client-side routing:
source.addEventListener('status', (e) => updateStatus(e.data));
source.addEventListener('progress', (e) => updateProgress(e.data));
source.addEventListener('complete', (e) => finishTask(e.data));
This pattern keeps your client code organized when multiple event types flow through a single connection.
Error Handling and Reconnection
SSE handles reconnection automatically, but you should implement graceful degradation:
source.onerror = (error) => {
if (source.readyState === EventSource.CLOSED) {
// Manual reconnect after delay
setTimeout(() => {
source = new EventSource('/stream');
}, 5000);
}
};
For critical applications, the supermemory skill can help you track connection health metrics and alert you when streams fail unexpectedly.
Performance Considerations
SSE connections consume server resources. For high-traffic applications:
- Limit concurrent connections per user
- Implement connection timeouts and periodic heartbeats
- Use a message queue to decouple event generation from delivery
import redis
@app.route('/stream')
def stream():
pubsub = redis.pubsub()
pubsub.subscribe('updates')
for message in pubsub.listen():
if message['type'] == 'message':
yield f"data: {message['data']}\n\n"
This Redis-backed approach scales horizontally and handles thousands of simultaneous connections efficiently.
Testing Your SSE Endpoints
Use the tdd skill to write comprehensive tests for your streaming endpoints:
def test_sse_endpoint():
response = client.get('/stream')
assert response.status_code == 200
assert response.content_type == 'text/event-stream'
# Read streamed content
lines = response.response
assert any(b'data:' in line for line in lines)
The webapp-testing skill can also validate SSE behavior in browser environments, checking that events arrive within expected timeframes and that reconnection works after network interruptions.
Conclusion
Server-Sent Events offer a straightforward solution for real-time streaming in web applications. The protocol is simple, works natively in browsers, and handles reconnection automatically. By combining SSE with Claude Code skills like tdd, webapp-testing, frontend-design, and supermemory, you can build robust real-time features while maintaining code quality and user experience.
Whether you’re streaming AI responses, live logs, or notification updates, SSE provides a reliable foundation that integrates well with modern development workflows.
Related Reading
- Claude Code WebSocket API Implementation
- Claude Code gRPC API Development Guide
- Claude Code REST API Design Best Practices
- Claude Skills Integrations Hub
Built by theluckystrike — More at zovo.one