Claude CodeでWebSocket・リアルタイム機能を実装する——SSEからChannelsまで

はじめに

REST/GraphQL APIの話でも、ChatOpsでSlackからClaude Codeを操作する話でもない。「タイピング中のインジケーターが出る・ページをリロードせずに通知が届く」——そんなリアルタイムUI機能をClaude Codeで実装する話と、Claude Code自体のストリーミング出力をパイプラインで活用する話だ。

リアルタイム機能の実装はREST APIより複雑だ。接続管理・再接続ロジック・Redis Pub/Subによるスケーリング・エラーハンドリングを同時に考慮しながらコードを書く必要がある。「ポーリングで妥協する」チームが多いのは、この実装コストの高さが原因だ。Claude Codeにこれらの要件をCLAUDE.mdで定義しておくことで、WebSocketやSSEの実装を自動生成できる。

WebSocket・SSE実装の自動生成——CLAUDE.mdでプロトコル選択から規約まで

リアルタイム機能の設計で最初に直面するのは「WebSocketかSSEか」という選択だ。誤った選択をするとスケーリングが難しくなったり、実装が無駄に複雑になる。CLAUDE.mdにこの判断基準を定義しておくことで、Claude Codeが毎回適切なプロトコルを選択する。

# CLAUDE.md(リアルタイム機能ポリシー)
## Real-Time Features Policy

### プロトコル選択ガイドライン
- 双方向通信(チャット・コラボレーション): WebSocket
- サーバー→クライアント単方向(通知・ダッシュボード更新): SSE推奨
- 単純なポーリングで十分な場合はWebSocket不使用(過剰設計の禁止)

### WebSocket実装ルール
- 接続管理: 必ず再接続ロジックを実装(exponential backoff)
- 認証: 接続時にJWTトークンをクエリパラメータで渡す
- スケーリング: Redis Pub/Sub + Socket.io Adapterを標準構成とする
- プロトコル: メッセージはNDJSON形式

### SSEルール
- ハートビート: 30秒ごとにコメント行送信(接続維持)
- リトライ: retry: フィールドで再接続間隔を指定(3000ms推奨)
- イベントID: id: フィールドで最終受信IDを管理(再接続時のレジューム)

WebSocketのスケーリング設計をCLAUDE.mdで定義しておくことが特に重要だ。「後でスケーリング問題が出て書き直す」コストは大きい。Redis Pub/Sub + Socket.io Adapterをデフォルト構成として定義することで、Claude Codeが生成するWebSocket実装が最初から水平スケーリングに対応する。

Claude Codeへの自然言語指示パターンはこうなる。

「Node.js + Socket.ioでリアルタイム通知システムを実装して。
要件:
- ユーザー認証後に専用ルームに参加
- 通知の種類: メッセージ・いいね・コメント・フォロー
- Redis Pub/Subで複数サーバーにスケール(水平スケーリング)
- 接続切断時の自動再接続(exponential backoff)
- 未読通知のRedisキャッシュ(接続前の通知を保持)」

CLAUDE.mdにこれらのルールが定義されていれば、Claude Codeはこの指示から再接続ロジック・Redis Pub/Sub設定・認証フロー・未読管理まで含む実装を生成する。

SSEはWebSocketより実装がシンプルで、HTTP標準のためプロキシやロードバランサーを意識する必要が少ない。自動再接続もブラウザネイティブで組み込まれている。通知やダッシュボード更新のような単方向のユースケースなら、SSEの方が適切な場合が多い。

Claude Code自体がAnthropicのAPIとSSEで通信している(code.claude.com/docs)。Claude Code Internalsの解析(kotrotsos.medium.com)によると、以下のイベントフローで処理が行われる。

メッセージメタデータ → コンテンツブロック(段階的更新)
→ テキスト出力 → ツール呼び出し → ツール結果 → 最終応答

このSSEイベントフローを参考に、アプリケーションのイベント設計に適用できる。

チャット通知: event: notification, data: {type, message, userId}
進捗更新:    event: progress, data: {taskId, percent, status}
エラー通知:  event: error, data: {code, message, retry: true/false}

大規模な接続数(10万接続超)では、Socket.io + Redis Pub/Subでは限界に達することがある。その場合はKafka等のメッセージブローカーが必要になるが、多くのアプリケーションではSocket.io + Redisの構成で十分対応できる。

Claude Code自体のstream-json——CIパイプラインとエージェント間チェーニング

Claude Codeには--output-format stream-jsonオプションがあり、JSON Lines(NDJSON)形式でリアルタイムに出力を流せる(code.claude.com/docs/en/agent-sdk/streaming-output)。これをCIパイプラインやエージェント間連携に使うことで、「何が起きているかわからない」ブラックボックス実行から抜け出せる。

# CI/CDパイプラインでのリアルタイム処理
claude -p "コードレビューして" \
  --output-format stream-json | \
  jq -j '.event.delta.text?'

# 出力例(イベントとして流れてくる)
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"コードの"}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"問題点を"}}}

stream-jsonが活きるユースケースをまとめると次の通りだ。

| ユースケース | 活用パターン |

|-----------|-----------|

| CI/CDパイプライン | 長時間タスクの進捗をリアルタイムでログに記録 |

| エージェント間チェーニング | 前のエージェントの出力を次のエージェントにストリーム |

| プログレスモニタリング | 処理状況をWebSocket経由でダッシュボードに表示 |

| Kubernetes CronJob | バッチ処理の結果をstream-jsonでキャプチャ |

エージェント間のパイプラインもシンプルに書ける。

# エージェント1の出力をエージェント2にパイプ
claude -p "コード生成して" --output-format stream-json | \
  claude -p "生成されたコードをレビューして" --output-format text

Khan Academyが提供するformat-claude-stream(github.com/Khan/format-claude-stream)は、stream-jsonの出力を人間が読めるテキストに変換するCLIフィルターだ。デバッグやログの可視化に役立つ。

Channels × イベント駆動エージェント——外部イベントでClaude Codeを動かす

Channelsは「外部イベントをClaude Codeのライブセッションにプッシュ」する機能だ(code.claude.com/docs/en/channels、2026年3月20日リリース)。従来の「人間がClaude Codeを呼ぶ」モデルから「イベントが来たらClaude Codeが反応する」モデルへの転換を可能にする。

CI失敗Webhook → Channels → ライブセッションに通知
→ Claude Codeが自動でエラーを解析・修正提案
→ Discord/Telegramに報告

イベント駆動エージェントパターンとして、次のような構成が考えられる。

外部イベント源(Webhook/CI/Discord/Telegram)
    ↓ Channels経由でプッシュ
Claude Codeライブセッション
    ↓ タスクを分類してサブエージェントに割り振り
Sub-agent 1: コードレビュー
Sub-agent 2: テスト生成
Sub-agent 3: ドキュメント更新
    ↓ 結果をDiscord/Telegramに報告

実際に使えるシナリオとして、CIパイプライン失敗時の自動コード解析・修正提案、Sentryアラート時のスタックトレース即時解析、PRレビューコメントへの自動修正対応、本番エラーの初動対応自動化などがある。これらをChannelsで設計すると、深夜のオンコールで人間が起こされる頻度を下げられる可能性がある。

2026年4月時点でChannelsが公式に対応しているのはDiscordとTelegramだ。Slackは未対応(コミュニティ実装のみ)のため、Slack連携を検討している場合はchatops記事で紹介しているClaude Code in Slack公式統合を参照してほしい。

ChatOps記事と本記事のChannels扱いは意図的にアングルが異なる。ChatOps記事は「SlackからClaude Codeを操作する」という人間主導の操作を扱い、本記事のChannelsは「外部イベントにClaude Codeが自律反応する」エージェント設計を扱う。

まとめ

リアルタイム機能とClaude Codeの組み合わせには二つの軸がある。アプリケーション層のWebSocket/SSE実装をClaude Codeで自動生成する使い方と、Claude Code自体のstream-json出力をパイプラインやエージェント間連携に活かす使い方だ。

WebSocket/SSE実装の品質はCLAUDE.mdへのプロトコル選択ルール・スケーリング設計・必須ヘッダの定義にかかっている。stream-jsonは長時間タスクの可視化とエージェント間チェーニングで、Channelsはイベントドリブンなオンコール自動化で効果を発揮する。

まず試すなら、CLAUDE.mdに「サーバー→クライアント単方向通知はSSE推奨」「WebSocketにはexponential backoffを必ず実装」の二行を追加してからリアルタイム機能の実装を依頼してみてほしい。その二行が、毎回のコードレビューで同じ指摘をしなくて済む設計の出発点になる。

コメント

タイトルとURLをコピーしました