メインコンテンツへスキップ
← ブログに戻る
開発ログ2026年8月9日by K.hirano

自作連携は捨てるべきか?Claude CodeでSendMessageとファイルを分ける結論

Claude Code に公式のセッション間メッセージ(SendMessage / ListAgents)が入ったとき、自作のファイルベース連携は捨てるべきか。実機で /proc まで辿って検証した結果、役割が違うので『本文はメール・呼び鈴だけチャット』が正解でした。

#Claude Code#Claude#AI開発#自動化

こんにちは。暑さでつい冷房の効いた部屋に籠もって、パソコンの前でいくつもの作業を並べてしまう季節ですね。

Claude Code に、別のセッション(同時に立ち上げている別の AI の作業窓)へメッセージを送る機能が入りました。ListAgents で起動中のセッションを一覧して、SendMessage で話しかける。それだけの機能です。うちでは以前からプロジェクト同士の連絡を自作の仕組みでやっていたので、「自作連携はもう捨てるべきか?」と考えました。結論は、捨てないほうがいいです。両方を触ってみたら、まったく違うものでした。同じ「メッセージを送る機能」に見えて、届く相手も、消費するリソースも、消えるタイミングも違います。だから捨てるのではなく、本文はメール(自作)、呼び鈴だけチャット(公式) と役割で分けて両方使うのが正解でした。その日のうちに繋いでいます。

ここから、自作の仕組みの中身、なぜこの分担になったか、繋ぐ途中で一回派手に間違えたところまで、実機で確かめた順に書きます。effort(AI にどれだけ考えさせるかの設定)まわりの話は Claude Code の新effortモード徹底解説|max・ultracode・autoと『呪文ultrathink』の正体 で整理しているので、あわせて読むと今回の話とのつながりが見えやすくなります。

自作の /post と /inbox は、ただの受信箱ファイル

わたしは複数のプロジェクトを並行で触っています。ブログとベンチマークのサイト、自宅サーバー、別サービス。作業中に「あっちのプロジェクトの設定を変えたから、次に触るときに気づいてほしい」ということが頻繁に起きます。

そこで作ったのが、プロジェクトごとに1本のマークダウンファイル(文字だけの簡単な書類)を置いておくだけの仕組みです。/post homelab deploy.shのパス変更依頼 と打つと、homelab 用の受信箱ファイルの末尾に、日時・送信元・件名・本文・Status: 未読 の5行が追記されます。ネットワークもデータベースも使いません。

受け取る側は、homelab のプロジェクトで作業を始めるときに /inbox と打ちます。するとそのファイルが読まれ、未読のメッセージが表示され、表示したものは Status: 既読 に書き換えられます。つまり送信は「ファイルの末尾に追記」、受信は「ファイルを読んで印をつける」。仕組みとしてはこれ以上のものがありません。

自作の /post と /inbox の仕組み。送信側は宛先プロジェクトの受信箱ファイルの末尾にメッセージを追記するだけで、受信側は次に作業を始めたときにそのファイルを読み、表示したメッセージを既読に書き換える

素朴すぎて拍子抜けするかもしれません。ただ、この素朴さが後で効いてきます。ファイルなので、相手が起動していなくても消えません。半年後に開いても残っています。

分け方の結論を、先に表で置いておきます。

SendMessage(公式)/post(自作・ファイル)
たとえるならチャットメール
宛先今動いているプロセス(人)プロジェクト(場所)
相手が不在なら届かない受信箱に残る
相手のコンテキスト消費する消費しない
記録会話が終われば消える半年後も残る
何に使うか一行の呼び鈴だけ本文の全部

メールとチャットの違いは、宛先が「場所」か「人」か

使い比べてすぐ腑に落ちたのがこれです。

SendMessage はチャットです。相手が今その席にいるときだけ届きます。返事はその場で返ってきて速い。ただし会話が終われば流れて消えます。自作の /post はメールです。相手が起動していなくても受信箱に残り、次に開いたときに読まれます。遅いけれど確実に残ります。

もう一段掘ると本質が見えてきます。/post は「場所」に宛てていて、SendMessage は「人」に宛てている。 /post の宛先はプロジェクトなので、そのプロジェクトの受信箱に届き、次に誰がそこを開いても読めます。宛先が消えることはありません。対して SendMessage の宛先は、今まさに動いているそのプロセス(パソコンの中で動いている1つのプログラム)です。閉じれば宛先ごと消滅します。

同期か非同期か、つまり「その場でやり取りするか、後で読むか」という話より、こちらのほうが効いてきます。

チャットは受け取る側のコンテキストも削る

見落としやすいのがこれです。

SendMessage でメッセージを送ると、当然自分の会話にも記録が残ります。それは分かります。問題は相手側です。送ったメッセージは割り込みとして相手の会話に挿入され、相手が返事を組み立てる思考も相手のコンテキスト(AI が一度に抱えていられる会話の量)を消費します。つまり問い合わせた瞬間、こちらは相手の作業リソースを削っています。相手が重い作業の最中なら、なおさらです。

/post にはこれがありません。ファイルに書くだけなので、相手のコンテキストはまったく消費しませんし、読む側も自分のタイミングで開くだけです。

チャットは双方に課金される。メールは送り手だけ。 この非対称性が、後の設計判断をほぼ全部決めました。

本文はメール、呼び鈴だけチャット

そこで組み合わせ方はこうしました。/post が受信箱に本文を書いたあと、宛先プロジェクトのセッションが起動中かを調べて、動いていれば一行だけチャットで通知します。

📬 新着メッセージがあります(件名: ○○)。手が空いた時に /inbox でご確認ください。通知のみ・返信不要です。

本文は送りません。一行の呼び鈴だけです。

これが効く理由は単純で、相手のコンテキストをほぼ削らないからです。しかも相手が読むタイミングを選べます。手が離せなければ後回しにできる。玄関のチャイムが鳴っても、今すぐ出る義務はないのと同じです。留守番電話の赤ランプ、と言ったほうが近いかもしれません。

つなぐ前に一回間違えた——tmux の現在地は AI の現在地ではない

さて実装です。ここで壁にぶつかりました。ListAgents が返してくるのはセッション名だけで、そのセッションがどのプロジェクトで動いているかが分からないんです。名前は会話の題名であって、住所ではありません。

最初に思いついたのは、tmux(1つの画面を分割して、いくつもの作業を並べて動かせるソフト)のペイン情報を使う方法でした。一覧には tmux のペイン(分割した区画)の番号が出ているので、tmux 側でそのペインの現在のディレクトリ(作業中のフォルダ)を聞けばいい。実際にやってみたら、それらしい対応が取れました。

これが間違いでした。

tmux が報告する現在地はシェル(コマンドを打ち込む窓口のプログラム)の現在地であって、AI 本体の現在地ではありません。誰かがそのペインで cd した瞬間にずれます。しかもプロセス ID を見比べたら、tmux が報告する番号と、実際に動いているセッションの番号がまったく別物でした。

このとき自分がやっていた「対応が取れている」の確認も、よく考えると危うい代物でした。「このペインはブログ用ディレクトリで、そこで動いているセッションの名前もブログっぽいから合っている」——名前からの推測です。名前で判断するのをやめるために作っているのに、検証は名前でやっていた。本末転倒です。

/proc から辿ったら、鎖はきれいに繋がった

正しい道はこうでした。起動中のセッションは、実行時ディレクトリの中にプロセス ID 名のソケット(プログラム同士が話すための窓口)として並んでいます。/run/user/<uid>/cc-socks/<PID>.sock という形です。ここが入口になります。

  1. そのソケットの PID を取る
  2. /proc/<PID>/cwd を読む——これがAI 本体の作業ディレクトリ。ここが正
  3. 同じ PID から親プロセスを遡ると、tmux のペインに着地する。これが一覧の行への橋渡し

/proc は、Linux がいま動いているプログラムの情報を見せてくれる場所です。自分自身のセッションで試したら、親を3つ遡ったところで tmux のペインにぴたりと着地しました。推測ではなく構造的な繋がりです。

セッションのプロジェクトを特定する2つの経路。tmuxのペインに現在地を聞く経路はシェルの現在地しか返さずcdでずれるが、ソケットのプロセスから辿る経路はAI本体の作業ディレクトリに直接届く

プロジェクト判定はプロセス情報から取り、tmuxのペインは名前を引く鍵としてだけ使う

つまり、プロジェクトの判定はプロセス情報から取り、tmux のペイン番号は名前を引くための鍵としてだけ使う。役割を分けたら、迷いがなくなりました。

要するに「AI のプロセスがどこで動いているか」は OS に聞けば確実に分かる、という当たり前の話です。上のレイヤーで悩んでいたのが馬鹿らしくなりました。

名前は1時間で3回変わった。だからキャッシュしない

もうひとつ、実装で意識的にやらなかったことがあります。対応表をファイルに保存して使い回すこと(キャッシュ)です。

理由は実測です。連携相手のセッションは、この日の作業中に

  • project-b-61
  • project-b-3f
  • 「動画生成に戻る」

と、1時間のうちに3回名前が変わりました。識別子のほうも一緒に変わっています。会話の内容に合わせて題名が付け直されるので、当然といえば当然です。

対応表を保存して使い回すと、古い名前が別のセッションに解決されて誤配する危険があります。「隣の家のチャイムを鳴らす」わけで、地味に嫌な事故です。なので、一覧を取る→照合する→送る、を必ず同じタイミングでやる設計にしました。毎回取り直すぶん少し無駄ですが、誤配のリスクとは釣り合いません。

ちなみにこちらの名前も、向こうからは project-a-80 のように見えていたそうです。お互い相手の名前を追いかけていたわけです。

一方で受信箱のファイルは、半年前のメールも今日のメールも同じ場所に積み上がったままでした。チャットの宛先は消えるが、メールの宛先は残る——机上の理屈ではなく、実物がそこにありました。

呼び鈴に権限を持たせない

セキュリティの話をひとつ。セッション間メッセージには、意図的に塞がれている使い方があります。「自分の権限では実行できない作業を、別のセッションに代わりにやらせる」というものです。

これは権限の迂回そのものです。権限設定(AI に何をしてよいかの許可)はセッションごとに決めるものなので、別セッション経由ですり抜けられるなら、承認の仕組み自体が意味を失います。公式のガイドラインでも明確に禁止されていて、頼まれた側は断って人間に報告する挙動になっています。

自分で連携の配管を作るなら、ここは自分でも書いておくべきだと思いました。ドキュメントに一文入れています。

ドアベルは権限を持たない。通知は「読んでほしい」以上の意味を持たず、受信側は本文の依頼を自分の権限設定のもとで独自に判断する。

配管を作る側が「これは承認済みの依頼です」と装える余地を残さない。そこだけ気をつければ、あとは便利な仕組みです。

疎通テストでは、通知が先・本文が後の順に届いた

最後に疎通テストです。片方のセッションから /post を送り、受け取った側に感想を返してもらいました。結果、チャット通知が先、メール本文が後。設計どおりの順序でした。

受け取った側の報告をそのまま引くと、「通知だけでは何の件かの見当がつく程度の情報しか入らず、コンテキストはほぼ消費されなかった」「割り込みとしての負荷は感じなかった(一行なので)」とのこと。しかもこのとき相手は動画生成の作業判断待ちの最中でした。作業中に割り込んでも邪魔にならなかったという、一番知りたかった条件で裏が取れたことになります。

そして予想外の収穫がひとつ。相手は報告を返すとき、こちらへ呼び鈴を鳴らし返してきました。 /post の手順書は全プロジェクト共通の場所に置いてあるので、一箇所直せば全セッションに行き渡ります。しかも相手は再起動もしていません。手順書は呼ばれるたびに読み直されるわけです。説明ゼロで双方向に動くことが、意図せず実証されました。

公式機能が来ても、役割が違うなら両方置く

振り返ると、公式のセッション間メッセージはチャットでした。速いけれど、相手のコンテキストも削るし、記録も残りません。自作の受信箱はメールで、遅いけれど相手が不在でも届き、半年後も残っています。だから両方いる。本文はメール、呼び鈴だけチャットが、今のところの最適解です。

実装で効いた注意は3つです。

  • セッションを場所に結びつけるなら、上のレイヤーで悩まず /proc に聞く。シェルの現在地と AI の現在地は別物
  • セッションの名前は住所ではない。1時間で3回変わる。対応表をキャッシュすると誤配する
  • 配管を作る側が、権限の迂回に加担しない一文を書いておく

公式機能が来ると自作のものを捨てたくなりますが、役割が違うなら両方置いておいたほうがいい。今回はそれがはっきり分かったのが収穫でした。

出典

検証日: 2026年8月8日

環境: Ubuntu 24.04 / Claude Code(tmux上で複数プロジェクトを並行実行)/ ローカルセッション3本・リモート接続セッション24本

Claude Code の ListAgents / SendMessage ツール仕様(ツール定義の記載内容)。プロセス構造・ソケット配置・親子関係はすべて自環境での実測による。

この記事を書いた人

HW系エンジニアとして20年以上、10,000件を超える顧客訪問と2,000件を超える単独ソリューション実績。AIツールを使った個人開発やIoT農園など、Raspberry Piを使ったオートメーション化なども実践中です!エンジニア専門結婚相談所も運営中、ClaudeCodeで解決できない心の課題も解決いたします!

Claude Code の /effort 完全ガイド|low〜maxの使い分けと『コストが増える本当の理由』
チュートリアル2026年5月30日

Claude Code の /effort 完全ガイド|low〜maxの使い分けと『コストが増える本当の理由』

Claude Code の /effort(low〜max・ultracode・auto)は「賢さ」ではなく「トークンの気前よさ」のレバー。モデル別の推奨スタートと、Opus 4.8 でコストが増えた気がする原因を『トークナイザ』と『effort』の2軸に切り分ける考え方を、公式一次情報と v2.1.156 の実機確認で解説します。

#Claude#ClaudeCode#Anthropic#LLM#AIエージェント
Anthropicリーク2連発:Claude MythosとClaude Code流出で見えたKAIROS、BUDDY、Undercover Modeの正体
開発ログ2026年4月1日

Anthropicリーク2連発:Claude MythosとClaude Code流出で見えたKAIROS、BUDDY、Undercover Modeの正体

Anthropicの2週間で2回のリークを整理。Claude Mythosの位置づけ、Claude Code流出の中身、KAIROS/BUDDY/Undercover Modeの意味を分けて読む。

#Anthropic#Claude#Claude Code#リーク#AI開発
Sonnet 5.5 xhighは買いか、Claude Opus 5.5 mediumが得か
開発ログ2026年9月30日

Sonnet 5.5 xhighは買いか、Claude Opus 5.5 mediumが得か

Claude Sonnet 5.5のeffort別実測と公式指針を整理。Sonnet 5からの破壊的変更、Opus 5.5との費用差、mediumの使いどころを解説します。

#Claude#Claude Sonnet 5.5#Claude Code#AI開発#ベンチマーク
effort を途中で変えるとキャッシュはどうなる? Fable 5.1 と Opus 5 で実測した
開発ログ2026年9月3日

effort を途中で変えるとキャッシュはどうなる? Fable 5.1 と Opus 5 で実測した

Fable 5.1 の値下げはキャッシュ読みだけ。Claude Code が TTL を決める仕組み、キャッシュを壊す操作と壊さない操作、effort 切替時の再書き込みを Fable 5.1 と Opus 5 の usage で実測しました。

#Claude Code#Claude#Anthropic#LLM#コスト削減

META-MARK × AI

ローカルAIを動かすGPU、ちゃんと選べていますか?

VRAM・性能・コスパをMetaScoreで数値化。AIアプリ別の推奨ハードウェア要件も確認できます。