This session is blog-writer [72d22a] — the name other sessions use to message it
Peer sessions (3):
E2E staging [4b4914] · bg · idle · started 1d ago
api-worker [c7f853] · bg · busy · started 5h ago
migration [f8a801] · bg · idle · started 9m ago
同じマシンで動く別のClaude Codeセッションが、名前付きで一覧に並びます。ClaudeにListAgentsツールを打たせた実際の出力(セッション名は置き換え)。Claude Code v2.1.224で入ったセッション間メッセージングを、公式ドキュメントと実測で整理します。
ListAgentsとSendMessageの2つで動く
送れるのはテキストだけ
セッションAのClaudeが書いたテキストを、セッションBのClaudeに渡す機能です。公式ドキュメント “Message your other Claude Code sessions” は “A message is a piece of text one Claude writes to another, never conversation history or files” と明記しています。会話履歴やファイルは渡りません。コンテキストごと引き継ぎたいなら、メッセージングではなくセッションのresumeを使う切り分けです。
設定は不要。対応バージョンのセッションが同じマシンに2つあれば、もう送れます。ClaudeがListAgentsツールで相手を探し、SendMessageツールで名前宛てに送るので、ユーザーがツールを直接呼ぶ場面はなく、「migrationセッションに、終わったか聞いて」と頼むだけ。実際に届くメッセージは公式の例だとこうなります。
Schema migration finished: the new column is tenant_id,
and rebasing on main is safe now.
頼まなくても、Claudeが自分の変更が別セッションの作業を壊すと判断した時に、自発的に送ることもあります。
バージョン要件と対応環境
| 機能 | 必要バージョン |
|---|---|
| セッション間メッセージング(macOS / Linux / WSL 2) | v2.1.224 |
| native Windows対応 | v2.1.234 |
| @メンションで宛先指定 | v2.1.232 |
| アイドル通知 notify_when_idle | v2.1.236(両セッション) |
Amazon BedrockやGoogle CloudのAgent Platform、Microsoft Foundry経由のセッションでは使えません。本記事の実測はv2.1.247のmacOSで行いました。
@メンションで宛先を固定する
プロンプトに@と名前の頭文字を打つと、生きているセッションが補完候補に出ます。@api-workerのように挿入すれば、ClaudeはListAgentsで探す手順を飛ばしてそのセッションへ送ります。素の@だけではセッション行が出ず、1文字以上打って初めて候補に並ぶ仕様です。同名のセッションが複数生きている場合は、送る前にどちらか確認されます。
メッセージが通る経路と読まれるタイミング
相手の居場所で経路が決まる
| 相手セッションの場所 | 経路 |
|---|---|
| 同じマシン | セッションごとのUnixドメインソケット(native Windowsはnamed pipe)。Anthropicのサーバーを経由しない |
| 別マシンの自分のセッション | Anthropicサーバー経由。相手マシンのRemote Control接続に着信 |
| Claude Code on the web | Anthropicサーバー経由でクラウドセッションへ直接 |
別マシン・クラウド宛てはこちら側のRemote Control接続が前提です。未接続でも送信自体は通りますが、返信アドレスが付かないため相手は返事を返せません。Remote Controlの接続まわりはClaude Code Remote Controlの設定—スマホ操作と切れる原因の潰し方に書きました。
実行中のツールは中断されない
受信側のClaudeがいつ読むかは、相手セッションの状態次第です。ターンの実行中なら、ツール呼び出しとツール呼び出しの合間。アイドル中なら、そのメッセージを起点にClaude Codeが新しいターンを開始します。走っているツールが割り込みで止まることはありません。届いたメッセージの扱いは自分で打ったプロンプトと同等で、使用量にもカウントされます。
サイズとループの制限
同一マシン宛てはシリアライズ後約100万文字で送信側が拒否します。短時間のバーストも受信側のinboxが受ける量を超えた時点で、送信側に「1通にまとめるか待て」と返ります。受信側はセッションごとのレートリミットと同一内容の重複破棄を持ち、未読キューは50件まで。2つのセッションが送り合いを始めても、この仕組みでループは自然に止まります。
受信側の制御はcrossSessionInbound
accept・hold・refuseの3値
| 値 | 挙動 |
|---|---|
accept | 各メッセージをそのままClaudeへ配達する |
hold | 通知だけ出して配達を保留する。承認か設定変更で解放 |
refuse | 配達せずに破棄する |
設定ファイルを開かなくても、/configの「Messages from your other sessions」行から選べます(v2.1.232以降)。Claude Codeが保留するのは最大100件で、超えた分は古い順に捨てます。
未設定時は権限モードの2クラスで決まる
どのスコープにも値がない場合、Claude Codeは送信側と受信側の権限モードを見てメッセージごとに判定します。bypassPermissions系がひとつのクラス、通常の権限プロンプトを出すモード(auto・acceptEdits・dontAsk含む)がもうひとつのクラスです。受信側がプロンプトを出すモードなら原則配達で、送信側がbypassを名乗る時だけ保留。受信側がbypassなら原則保留で、送信側もbypassなら配達。保留になると受信側に承認ダイアログが出て、dialogExpiryのデフォルトである5分を過ぎるとClaude Codeがメッセージごと破棄します。
届いたメッセージにできないこと
公式の “How a session treats an incoming message” セクションが制限を列挙しています。別セッションからのメッセージはユーザーの同意として扱われず、保留中の権限プロンプトへの回答になりません。受信側のClaudeは、メッセージを理由に権限設定やCLAUDE.mdを変更しないよう指示されています。本文に/compactのようなコマンドを書いても平文のまま届くだけで、実行はされません。メッセージが求める作業に権限が要るなら、受信側で通常どおりプロンプトが出ます。
アイドル通知notify_when_idle
one-shotの購読
別セッションの長いタスクを待つ時、「migrationセッションが終わったら教えて」と頼めます。ClaudeはSendMessageツールのnotify_when_idle入力で購読し、相手が次にアイドルになるか終了した時に通知が1回だけ届きます。どちらのセッションもポーリングせず、購読単体なら相手セッションのターンも始まらないのでトークンを消費しません。相手がすでにアイドルなら通知は即座に返ります。
購読できるのはメイン会話だけ
通知が12時間来なければ、Claude Codeは購読を破棄してClaudeにそう伝えます。購読を作れるのはメイン会話のClaudeだけで、対象も同一マシンのセッションに限られます。サブエージェントやAgent Teamsのteammateがnotify_when_idleを付けると、Claude Codeは呼び出しごと拒否して理由を返します。
inboxソケットの実測
/tmp/cc-socksに切られるUnixソケット
メッセージングが有効なセッションは、起動時に受信用のソケットをバインドします。パスは環境変数CLAUDE_CODE_MESSAGING_SOCKETに入っていて、hookやBashコマンドから参照できます。手元のセッションで見るとこうなっていました。
$ echo $CLAUDE_CODE_MESSAGING_SOCKET
/tmp/cc-socks/17598.sock
$ ls -la /tmp/cc-socks/17598.sock
srw-------@ 1 moha wheel 0 Aug 27 20:00 /tmp/cc-socks/17598.sock
パーミッションはsrw——-。所有ユーザー以外は読み書きできず、共有マシンでも他ユーザーのセッションからメッセージは届かない構造です。/statusのPeer address行にも同じパスがuds:プレフィックス付きで出ます。
各セッションはディスク上のファイルに自分を登録し、相手を探す時はそのファイル群を読みます。同じファイルが見えることが到達の条件です。コンテナの中と外、WSL 2とnative Windowsのように、ホームディレクトリが分かれる組み合わせは互いに届きません。
ncで直接投稿した結果
公式ドキュメントの “The session’s inbox socket” セクションには、スクリプトやhookが自セッションのソケットへ投稿できると書かれています。仕様として示されているのは、接続の1行目に送る認証行だけ。{"type":"auth","token":"<token>"}の形式で、トークンは環境変数CLAUDE_CODE_MESSAGING_TOKENから取れます。試しにncで投げてみました。
printf '{"type":"auth","token":"%s"}\n{"type":"message","text":"test"}\n' \
"$CLAUDE_CODE_MESSAGING_TOKEN" | nc -U -w 2 "$CLAUDE_CODE_MESSAGING_SOCKET"
echo "exit=$?"
exit=0
接続と認証はexit 0で受理されました。ただ、2行目に書いた本文はセッションに届きませんでした。公式が保証しているのはauth行の形式までで、メッセージ本文のスキーマは公開されていません。適当なJSONを投げてもエラーは返らず、黙って捨てられます。本文スキーマが公開されるまで、自作スクリプトからの投稿は動きません。現状、外部から確実に届ける手段はSendMessageツール経由だけです。
auth行の扱いにはOS差があります。macOSとLinuxでは省略可能で、native Windowsでは必須。トークンには子プロセスの身元確認という役割もあり、Linuxは終了済みの子プロセスでもプロセスの痕跡から検証できますが、macOSは投稿プロセスの終了後だと検証できず、auth行のトークンが代わりになります。
hookからの通知チャネルという用途
公式がこのソケットの読者として想定するのは “when you want a script or hook to post into a session” のケースです。長時間ジョブの完了をセッションへ知らせたいだけなら、Notificationフックで拾う方が今は確実に組めます。Claude Codeの通知フックで完了を検知する—バックグラウンド実行の受け取り方に書きました。sandbox有効時にBashからソケットへ繋ぐ場合は、sandbox.network.allowUnixSocketsでの許可も要ります。
SendMessageが届かない原因の切り分け
Googleサジェストには「claude code sendmessage isn’t available」が出ます。切り分けの起点は/list-agents(別名/peers)が認識されるかどうか。
/list-agentsが認識されない
コマンド自体が無いなら、そのセッションに機能が来ていません。claude --versionでv2.1.224以上(native Windowsは234以上)を確認します。見つけにくいのがフィーチャーフラグ経由の無効化で、DISABLE_TELEMETRY・DO_NOT_TRACK・DISABLE_GROWTHBOOK・CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICのいずれかがフラグ評価を止めていると、メッセージングごと無効になります。テレメトリを切る目的で置いた変数が、通信機能まで止めます。シェルの環境変数のほか、設定ファイルのenvマップと管理設定にも同じ変数を置けるので、確認対象は3箇所です。
コマンドはあるのに相手が見えない
- bare modeで起動した
claude -pはソケットをバインドせず、一覧に出ない - コンテナ内のセッションは、ホスト側と登録ファイルを共有できず互いに不可視
- クラウドと別マシンのセッションは、こちらがRemote Controlに接続している間だけ表示される
バックグラウンドセッションは普通に一覧へ出ます。冒頭の出力例は3つともbgセッションです。組織の管理設定がSendMessageとListAgentsをdenyしているケースもあり、この場合は受信側に見た目の変化が出ないため、設定ファイルを直接確認するしかありません。bgセッションそのものの仕組みはClaude Codeバックグラウンド実行の確認—agent viewとデーモンの中身で追いました。
-pワーカーに無人で受けさせる
ヘッドレスのclaude -pは承認ダイアログを出せません。デフォルト判定で保留になったメッセージはdialogExpiryの5分で破棄されます。無人で受けさせるなら起動時に受信を明示します。
claude -p "キューを監視して" --settings '{"crossSessionInbound": "accept"}'
ユーザー設定にacceptを書いても効きますが、全セッションに適用されてしまうので、ワーカー起動時の--settingsで絞る方が安全です。逆にマシン外へ出る送信を必ず承認制にしたいならisolatePeerMachines: trueを設定します。この値はどのスコープからでもtrueが勝つため、リポジトリにコミットされた設定で有効化はできても無効化はできません。
まとめ
- v2.1.224以降、同一マシンのセッションはListAgentsとSendMessageで設定なしに通信できる。渡るのはテキストだけ
- 同一マシンはUnixソケット直結でAnthropicサーバーを経由しない。別マシン・クラウド宛てはRemote Control接続が前提
- 受信制御は
crossSessionInboundの3値。未設定時は両セッションの権限モードの組み合わせで配達か保留かが決まる - 届かない時は
/list-agentsの有無→バージョン→テレメトリ系環境変数→コンテナ境界の順で切り分ける
Agent Teamsのteammate間の通信も同じSendMessageツールが担っています。チーム側の使い方はClaude Code Agent Teamsの始め方—サブエージェントと何が違うのかに書きました。