agents-inc/skills/src/skills/web-realtime-sse/SKILL.md
web-realtime-sse
Server-Sent Events for unidirectional server-to-client streaming, EventSource API, fetch streaming, reconnection patterns, message parsing
- Source repository stars
- 23
- Declared platforms
- 0
- Static risk flags
- 1
- Last source update
- 2026-08-09
- Source checked
- 2026-08-28
Decision brief
What it does: where it fits
Quick Guide: Use SSE for unidirectional server-to-client real-time updates over HTTP. Use the native EventSource API for automatic reconnection and message parsing. Use fetch streaming when you need custom headers or POST requests.
Not for
- Tasks that require unconfirmed production actions or broad system permissions.
- Environments where the pinned source and install steps cannot be inspected.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/agents-inc/skills --skill "src/skills/web-realtime-sse"Inspect the Agent Skill "web-realtime-sse" from https://github.com/agents-inc/skills/blob/81d43a51211aca12c85dcc16085fa99014ec548e/src/skills/web-realtime-sse/SKILL.md at commit 81d43a51211aca12c85dcc16085fa99014ec548e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
Implementation
Why good: All three lifecycle events handled, readyState check distinguishes reconnection from permanent failure, named constant for URL, cleanup shown
Why good: All three lifecycle events handled, readyState check distinguishes reconnection from permanent failure, named constant for URL, cleanup shownWhy bad: Missing onerror means failures are silent, missing cleanup causes memory leaks and zombie connections, hardcoded URL string - 02
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)
Server-to-client real-time updates (notifications, feeds, dashboards)LLM/AI response streaming (token-by-token output)Live data feeds (stock prices, sports scores, news) - 03
Philosophy
Server-Sent Events (SSE) provide a simple, HTTP-based protocol for servers to push real-time updates to clients. Unlike WebSockets, SSE is unidirectional (server to client only), built on standard HTTP, and includes automatic reconnection.
Simplicity: Standard HTTP protocol - works through firewalls, proxies, and load balancers without special configuration.Built-in Reconnection: The EventSource API automatically reconnects when connections drop, with configurable retry intervals.Message Recovery: The Last-Event-ID header enables servers to replay missed messages after reconnection. - 04
Core Patterns
The native EventSource API provides automatic connection management, message parsing, and reconnection.
The native EventSource API provides automatic connection management, message parsing, and reconnection.Why good: All three lifecycle events handled, readyState check distinguishes reconnection from permanent failure, named constant for URL, cleanup shownWhy bad: Missing onerror means failures are silent, missing cleanup causes memory leaks and zombie connections, hardcoded URL string - 05
Pattern 1: Basic EventSource Connection
The native EventSource API provides automatic connection management, message parsing, and reconnection.
The native EventSource API provides automatic connection management, message parsing, and reconnection.Why good: All three lifecycle events handled, readyState check distinguishes reconnection from permanent failure, named constant for URL, cleanup shownWhy bad: Missing onerror means failures are silent, missing cleanup causes memory leaks and zombie connections, hardcoded URL string
Permission review
Static risk signals and limitations
Network access
The documentation includes network, browsing, or remote request actions.
const SSE_URL = "https://api.example.com/events";Evidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 23 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- agents-inc/skills
- Skill path
- src/skills/web-realtime-sse/SKILL.md
- Commit
- 81d43a51211aca12c85dcc16085fa99014ec548e
- License
- MIT
- Collected
- 2026-08-28
- Default branch
- main
View the original SKILL.md
Server-Sent Events (SSE) Patterns
Quick Guide: Use SSE for unidirectional server-to-client real-time updates over HTTP. Use the native EventSource API for automatic reconnection and message parsing. Use fetch streaming when you need custom headers or POST requests.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use named constants for ALL timing values - reconnect intervals, keep-alive periods, timeouts)
(You MUST implement proper cleanup by calling eventSource.close() when connections are no longer needed)
(You MUST use event IDs (id: field) to enable message recovery on reconnection)
(You MUST handle the onerror event and check readyState to distinguish reconnection from permanent failure)
(You MUST set Content-Type: text/event-stream and Cache-Control: no-cache on SSE responses — do NOT set Connection: keep-alive on HTTP/2+)
</critical_requirements>
Auto-detection: SSE, Server-Sent Events, EventSource, text/event-stream, onmessage, server push, one-way streaming, real-time updates
When to use:
- Server-to-client real-time updates (notifications, feeds, dashboards)
- LLM/AI response streaming (token-by-token output)
- Live data feeds (stock prices, sports scores, news)
- Server push notifications without client responses needed
- Long-polling replacement with better browser support
Key patterns covered:
- EventSource API connection lifecycle
- Custom event types with addEventListener
- Fetch-based streaming for custom headers/POST
- SSE message parsing (data, event, id, retry fields)
- Reconnection with Last-Event-ID recovery
- Keep-alive comments to prevent proxy timeouts
- Custom React hooks (useEventSource, useSSE)
When NOT to use:
- Bidirectional communication needed (use WebSocket)
- Binary data transmission required (use WebSocket)
- Client needs to send frequent messages (use WebSocket)
- Sub-millisecond latency required (use WebSocket)
Detailed Resources:
- examples/core.md - React hooks (useEventSource, useSSE), shared context, conditional connection
- examples/fetch-streaming.md - Fetch-based SSE, message parser, auth, POST streaming, LLM pattern
- examples/reconnection.md - Last-Event-ID recovery, exponential backoff, health checks, visibility-aware
- reference.md - Decision frameworks, anti-patterns, message format reference
Philosophy
Server-Sent Events (SSE) provide a simple, HTTP-based protocol for servers to push real-time updates to clients. Unlike WebSockets, SSE is unidirectional (server to client only), built on standard HTTP, and includes automatic reconnection.
Why SSE exists:
-
Simplicity: Standard HTTP protocol - works through firewalls, proxies, and load balancers without special configuration.
-
Built-in Reconnection: The EventSource API automatically reconnects when connections drop, with configurable retry intervals.
-
Message Recovery: The
Last-Event-IDheader enables servers to replay missed messages after reconnection. -
Text-Based Protocol: Human-readable format makes debugging straightforward.
Connection Lifecycle:
CONNECTING (0) → OPEN (1) → messages... → CLOSED (2)
↓ ↓
(error) ← auto-reconnect ← (connection lost)
When to Choose SSE over WebSocket:
- Server sends updates, client only listens
- Working with HTTP/2 (multiplexing multiple SSE streams)
- Need automatic reconnection without custom logic
- Proxies/firewalls block WebSocket but allow HTTP
- Building LLM streaming interfaces
Core Patterns
Pattern 1: Basic EventSource Connection
The native EventSource API provides automatic connection management, message parsing, and reconnection.
Constants
const SSE_URL = "/api/events";
Implementation
// ✅ Good Example - Complete lifecycle handling
const SSE_URL = "/api/events";
const eventSource = new EventSource(SSE_URL);
eventSource.onopen = () => {
console.log("SSE connection opened");
// Connection is ready - server can now push events
};
eventSource.onmessage = (event: MessageEvent) => {
console.log("Received:", event.data);
console.log("Event ID:", event.lastEventId);
};
eventSource.onerror = (error: Event) => {
console.error("SSE error:", error);
// Check connection state to determine action
if (eventSource.readyState === EventSource.CLOSED) {
console.log("Connection closed permanently");
} else if (eventSource.readyState === EventSource.CONNECTING) {
console.log("Reconnecting...");
}
};
// Cleanup when done
// eventSource.close();
Why good: All three lifecycle events handled, readyState check distinguishes reconnection from permanent failure, named constant for URL, cleanup shown
// ❌ Bad Example - Missing error handling and cleanup
const eventSource = new EventSource("/api/events");
eventSource.onmessage = (event) => {
console.log(event.data);
};
// No onerror handler - connection failures are silent
// No cleanup - connection stays open forever
Why bad: Missing onerror means failures are silent, missing cleanup causes memory leaks and zombie connections, hardcoded URL string
Pattern 2: Custom Event Types
SSE supports named events via the event: field. Use addEventListener to handle specific event types.
// ✅ Good Example - Multiple event type handling
const SSE_URL = "/api/notifications";
const eventSource = new EventSource(SSE_URL);
// Default message event (no event: field in server response)
eventSource.onmessage = (event: MessageEvent) => {
console.log("Generic message:", event.data);
};
// Named custom events
eventSource.addEventListener("notification", (event: MessageEvent) => {
const notification = JSON.parse(event.data);
showNotification(notification.title, notification.body);
});
eventSource.addEventListener("user-joined", (event: MessageEvent) => {
const user = JSON.parse(event.data);
updateUserList(user);
});
eventSource.addEventListener("heartbeat", (event: MessageEvent) => {
// Keep-alive event - connection is healthy
console.log("Heartbeat received at:", event.data);
});
Why good: Separate handlers for different event types, typed MessageEvent parameters, JSON parsing for structured data, heartbeat handling for connection health
When to use: When server sends multiple types of events with different handling requirements.
Pattern 3: Credentials and Cross-Origin
For cross-origin requests or when cookies are required, configure withCredentials.
// ✅ Good Example - Cross-origin with credentials
const SSE_URL = "https://api.example.com/events";
const eventSource = new EventSource(SSE_URL, {
withCredentials: true, // Include cookies for cross-origin
});
eventSource.onopen = () => {
console.log("Connected with credentials");
};
eventSource.onerror = (error) => {
// CORS errors will trigger onerror
console.error("Connection error - check CORS configuration");
};
Why good: withCredentials enables cookie-based authentication, CORS error handling noted
When to use: Cross-origin SSE connections that require authentication cookies.
Pattern 4: Connection State Management
Track connection state for UI feedback and smart reconnection decisions.
Constants
type SSEStatus = "connecting" | "open" | "closed" | "error";
const READY_STATE_MAP: Record<number, SSEStatus> = {
[EventSource.CONNECTING]: "connecting",
[EventSource.OPEN]: "open",
[EventSource.CLOSED]: "closed",
};
Implementation
// ✅ Good Example - State tracking class
const MAX_MANUAL_RETRIES = 5;
const RETRY_DELAY_MS = 3000;
class SSEConnection {
private eventSource: EventSource | null = null;
private status: SSEStatus = "closed";
private manualRetryCount = 0;
private onStatusChange?: (status: SSEStatus) => void;
private onMessage?: (data: string, eventType: string) => void;
constructor(
private url: string,
options?: {
onStatusChange?: (status: SSEStatus) => void;
onMessage?: (data: string, eventType: string) => void;
},
) {
this.onStatusChange = options?.onStatusChange;
this.onMessage = options?.onMessage;
}
connect(): void {
if (this.eventSource) {
this.disconnect();
}
this.setStatus("connecting");
this.eventSource = new EventSource(this.url);
this.eventSource.onopen = () => {
this.setStatus("open");
this.manualRetryCount = 0; // Reset on successful connection
};
this.eventSource.onmessage = (event: MessageEvent) => {
this.onMessage?.(event.data, "message");
};
this.eventSource.onerror = () => {
if (this.eventSource?.readyState === EventSource.CLOSED) {
this.setStatus("closed");
// EventSource won't auto-reconnect if server sent HTTP error
this.attemptManualReconnect();
} else {
this.setStatus("error");
// EventSource is auto-reconnecting
}
};
}
private attemptManualReconnect(): void {
if (this.manualRetryCount < MAX_MANUAL_RETRIES) {
this.manualRetryCount++;
console.log(`Manual reconnect attempt ${this.manualRetryCount}`);
setTimeout(() => this.connect(), RETRY_DELAY_MS);
}
}
disconnect(): void {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = null;
this.setStatus("closed");
}
}
private setStatus(status: SSEStatus): void {
this.status = status;
this.onStatusChange?.(status);
}
getStatus(): SSEStatus {
return this.status;
}
}
export { SSEConnection };
Why good: Named constants for retry values, status tracking enables UI updates, manual retry for HTTP errors (EventSource only auto-retries network errors), cleanup resets state properly
Pattern 5: SSE Message Format
Messages are \n-separated fields terminated by \n\n. Five field types: data: (payload), event: (named type), id: (recovery ID), retry: (reconnect ms), : (comment/keep-alive).
event: notification
data: {"title": "New message"}
id: msg-002
: keep-alive comment (ignored by client)
Key behaviors: multiple data: lines concatenate with \n; id: persists until changed; retry: is remembered for future reconnections; comments (:) keep connection alive but are not delivered.
See reference.md for the full field reference and behavior table.
Pattern 6: Discriminated Unions for Message Types
Use TypeScript discriminated unions for type-safe message handling.
// ✅ Good Example - Type-safe SSE message handling
// Server message types
type SSEMessage =
| {
type: "notification";
title: string;
body: string;
priority: "low" | "high";
}
| { type: "user-update"; userId: string; action: "joined" | "left" }
| { type: "data-sync"; payload: unknown; timestamp: number }
| { type: "heartbeat"; serverTime: number };
function parseSSEMessage(data: string): SSEMessage | null {
try {
return JSON.parse(data) as SSEMessage;
} catch {
console.error("Failed to parse SSE message:", data);
return null;
}
}
function handleSSEMessage(message: SSEMessage): void {
switch (message.type) {
case "notification":
showNotification(message.title, message.body, message.priority);
break;
case "user-update":
updateUserPresence(message.userId, message.action);
break;
case "data-sync":
syncData(message.payload, message.timestamp);
break;
case "heartbeat":
updateServerTime(message.serverTime);
break;
default:
// Exhaustiveness check
const exhaustive: never = message;
console.warn("Unknown message type:", exhaustive);
}
}
// Usage with EventSource
eventSource.onmessage = (event: MessageEvent) => {
const message = parseSSEMessage(event.data);
if (message) {
handleSSEMessage(message);
}
};
Why good: Discriminated union enables type narrowing, exhaustiveness check catches missing cases at compile time, separate parse and handle functions, error handling for malformed messages
Integration Guide
SSE is a transport mechanism. This skill covers the EventSource API and fetch streaming patterns only.
- Components receive SSE data via callbacks/hooks and pass it to your UI layer via props or state
- Authentication integrates via cookies (
withCredentials: true) or fetch streaming with custom headers - For bidirectional communication, SSE is not the right tool — evaluate WebSocket instead
<red_flags>
RED FLAGS
- No cleanup on unmount - EventSource stays open, memory leaks, zombie connections
- Ignoring onerror event - Connection failures are silent, users see stale data
- Not checking readyState in onerror - Cannot distinguish reconnection from permanent failure
- Token in URL query string - Security risk: visible in server logs, browser history
- Missing keep-alive comments - Proxies may close "idle" connections after 60-120 seconds
- JSON.parse without try-catch - Malformed messages crash the entire handler
- Creating new EventSource without closing old one - Duplicate connections, duplicate messages
- Not handling buffer boundaries in fetch streaming - Messages split across chunks are missed
Gotchas & Edge Cases:
- EventSource has no timeout - dead connections may not fire onerror for minutes
- HTTP/1.1 browsers limit 6 connections per domain (SSE counts against this)
retry:field is in milliseconds, not seconds- Empty
data:\n\nsends empty string, not undefined Connection: keep-aliveheader is prohibited in HTTP/2+ (Safari rejects it)
See reference.md for full anti-pattern examples with code.
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md
(You MUST use named constants for ALL timing values - reconnect intervals, keep-alive periods, timeouts)
(You MUST implement proper cleanup by calling eventSource.close() when connections are no longer needed)
(You MUST use event IDs (id: field) to enable message recovery on reconnection)
(You MUST handle the onerror event and check readyState to distinguish reconnection from permanent failure)
(You MUST set Content-Type: text/event-stream and Cache-Control: no-cache on SSE responses — do NOT set Connection: keep-alive on HTTP/2+)
Failure to follow these rules will result in memory leaks, missed messages, and silent connection failures.
</critical_reminders>
Frequently asked questions
What to verify before installation and use
What does the web-realtime-sse source document cover?
Quick Guide: Use SSE for unidirectional server-to-client real-time updates over HTTP. Use the native EventSource API for automatic reconnection and message parsing. Use fetch streaming when you need custom headers or POST requests.
How do I install web-realtime-sse?
The source record exposes this install command: npx skills add https://github.com/agents-inc/skills --skill "src/skills/web-realtime-sse". Inspect the command and pinned source before running it.
Which permission-related actions were detected?
Static rules flagged network in the source; the page lists the matching lines and excerpts.
Alternatives
Compare before choosing
coreyhaines31/marketingskills
ab-testing
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
garrytan/gbrain
bulk-ingestion
End-to-end discipline for turning any large data source (audio libraries, email takeouts, document corpora, chat exports, API dumps) into brain pages at scale. The lifecycle spine: SCHEMA → ACCESS → TRIAL → EVALUATE → IMPROVE → CODIFY → TEST → SKILLIFY → BULK → MONITOR. State is tracked in a durable JSON manifest (see MANIFEST-PATTERN.md) so any crash, session boundary, or subagent fan-out resumes from ground truth instead of memory.
alirezarezvani/claude-skills
app-store-optimization
App Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklist
dotnet/skills
migrate-vstest-to-mtp
Migrates .NET test projects from VSTest to Microsoft.Testing.Platform (MTP). Use when user asks to "migrate to MTP", "switch from VSTest", "enable Microsoft.Testing.Platform", "use MTP runner", set OutputType=Exe only for test projects in Directory.Build.props, or mentions EnableMSTestRunner, EnableNUnitRunner, or UseMicrosoftTestingPlatformRunner. USE FOR: MTP behavioral differences vs VSTest (exit code 8, zero tests discovered, --ignore-exit-code, TESTINGPLATFORM_EXITCODE_IGNORE); centralizing