.claude/skills/websocket-streaming/SKILL.md
WebSocket and Gemini Live API patterns — connection management, audio streaming, and response handling
npx skillsauth add mohitmujawdiya/dagabaaz websocket-streamingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Always disconnect before reconnecting. The connect() method must call disconnect() first to clean up any existing WebSocket and URLSession. Never leave orphaned connections.
Invalidate URLSession on disconnect. URLSession retains its delegate — calling invalidateAndCancel() is required to prevent memory leaks:
func disconnect() {
let (ws, session) = lock.withLock {
let ws = webSocket
let session = urlSession
webSocket = nil
urlSession = nil
_isConnected = false
return (ws, session)
}
ws?.cancel(with: .goingAway, reason: nil)
session?.invalidateAndCancel()
}
isConnected must be thread-safe. It's read from the audio streaming thread (high frequency) and written from the WebSocket thread. Protect with NSLock.
sendAudioChunk is called thousands of times per second. Keep it minimal:
isConnected first (fast exit)async/await here — the audio callback can't awaitJSON message structure for Gemini Live audio:
{
"realtime_input": {
"media_chunks": [
{ "data": "<base64>", "mime_type": "audio/pcm;rate=16000" }
]
}
}
Gemini Live responses use tagged text for routing. The listening prompt instructs Gemini to prefix output:
[QUESTION] <text> — detected interview question[TRANSCRIPT] <text> — general transcriptUse String.dropFirst() for tag stripping, not replacingOccurrences. It's more efficient and semantically correct for prefix removal.
turnComplete signals end of response. Use this to update UI state (stop spinner, mark answer as complete).
The setup message must be sent before any audio. It configures:
gemini-2.0-flash-live-001["TEXT"] (we don't need audio output)0.7 (natural-sounding but not too random)System prompt goes in setup, mode prompt goes in client_content. The listening prompt (always active) is set during setup. The answer mode prompt is sent as a user turn when generating answers. This means Gemini has full conversation context when answering.
development
Swift macOS code quality standards — architecture, patterns, and anti-patterns for native macOS apps
data-ai
Swift concurrency patterns for this project — async/await, Sendable, thread safety, and MainActor usage
tools
Notch overlay UI patterns — NSPanel setup, SwiftUI overlay views, screen-sharing hiding, and display adaptation
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.