Tailscaleで2台のPCのClaude CodeとCodexをつなぐ検討:IP探索は消えるがセッションへの割り込みは残る

開発claude-code-tools

Tailscale で2台の Claude Code と Codex をつなぐ検討

Mac と Windows の2台で、Claude Code と Codex を使っている。 片方のセッションからもう片方へ連絡するための cross-machine-message スキルを作っている途中で、ふと思った。 Tailscale を入れれば、こんな仕組みを作り込まなくても普通に通信できるのではないか。

そのまま Claude Code に聞いてみた。 返ってきたのは「通信の土台としてはかなり楽になる。ただ、Tailscale が解決するのは『相手の機械にどう届くか』だけ」という答えだった。

いまのスキルは何に手間をかけているのか

今のスキルは、LAN の中で Windows から Mac へ直接送る。 Mac 上の小さな HTTP サーバーが本文を受け取り、tmux のペインに貼る仕組みである(作った経緯は別のPCのClaude Codeに話しかける記事に書いた)。

手間がかかっているのは、送る前に「Mac がどこにいるか」を探す部分だ。 Mac の IP は DHCP で変わる。 Wi-Fi と有線で口が2つあり、口ごとに IP が違う。 macOS のプライベート Wi-Fi アドレスのせいで、機器番号(MAC アドレス)まで変わる。

そのためスキルには、IP の総当たり、機器番号の照合、SSH のホスト鍵の指紋による本物確認が積み重なっている。 2-1-b の節はまるごと、2-1 の節もその一部が、この確認の話である。

Tailscale で消えるもの、残るもの

Claude Code の整理では、Tailscale を入れると 2-1 と 2-1-b のほぼ全部が要らなくなる。 端末に固定の IP と MagicDNS の名前が付くので、Mac を探す必要そのものが無くなる。

消えるのは次の4つである。

  • IP の探索(送信スクリプトの自動探索、前回の接続先の記録、--pin による登録)。MagicDNS の名前で固定できる
  • 機器番号とホスト鍵の指紋による本物確認。tailnet の端末認証が代わりに保証する
  • 「同じ LAN にいる」という前提。外出先やテザリングでもつながる
  • SSH の接続元の制限。LAN のアドレス範囲を、tailnet のアドレス範囲に置き換える

一方で、次の3つは残る。

  • Mac の受信サーバーの自動起動。LaunchAgent に登録しておらず、Mac を再起動すると止まる
  • 動いているセッションへの注入。Mac 側は tmux への注入で、相手がアイドルのときしか届かない。Windows 側には受け口が無い
  • Codex には、動いているセッションへ話しかける口がそもそも無い

並べてみると、Tailscale が肩代わりするのは「どの機械に届けるか」の層だけだと分かる。 届いた本文を走っているセッションの入力欄へどう差し込むか、という層は今のまま必要になる。

割り込まずに、相手の機械で使い切りで動かす

「いちばん効く」として挙がったのは、別の使い方だった。 動いているセッションに割り込むのをやめて、相手の機械で新しく使い切りの実行をさせ、結果だけを受け取る。

ssh <mac> 'cd ~/git_repo/xxx && claude -p "…"'   # Codex なら codex exec "…"

この形なら、注入もアイドル判定も要らない。 話しかける口の無い Codex も、codex exec ならこの形に乗る。

ただし制約もある。 Tailscale SSH のサーバーは Windows に対応していない、というのが Claude Code の認識で、これはまだ一次情報で確かめていない。 Mac から Windows へ同じことをするには、Windows の OpenSSH Server を有効にする必要がある。 どれも案の段階で、まだ1つも試していない。

「入っていない」は誤りだった

Claude Code から最初に返ってきた答えは、この Windows 機にはまだ Tailscale が入っていない、というものだった。 ところが、進捗メモに残った実測では、Tailscale 1.102.2 はインストール済みで、サービスも Running だった。 which tailscale が空を返したのは、コマンドが PATH に無かっただけである。

入ってはいたが、つながってもいなかった。 tailscale status は Tailscale is starting と unexpected state: NoState を出し、終了コード1で終わった。

同じ症状は、7月5日にリモートデスクトップのために Tailscale を検討したときにも出ていた。 その日は手順書のレビューもしていた。 当時の見立ては、Run unattended を設定していないためにサインイン待ちになっている、というものだった。

Mac 側に Tailscale が入っているかどうかは、まだ確かめていない。

明日に回した9項目

今日はここで切り上げ、進捗メモと、明日のセッションに貼るプロンプトを Claude Code に作らせた。 プロンプトは、ダウンロードフォルダにテキストファイルで置いてもらった。 2つのファイルがディスク上にあることまでは確かめてもらったが、コミットはまだしていない。

進捗メモの状態は「進行中」で、残りは9項目ある。

  • Windows: Tailscale にサインインして Connected にし、Run unattended を有効にする
  • Windows: IP と MagicDNS 名を控える
  • Mac: Tailscale を入れて同じアカウントでログインし、IP と名前を控える
  • 管理コンソールで、両機の key expiry を無効にする
  • Windows → Mac: tailnet の名前で SSH が通るか確かめる
  • 送信スクリプトの宛先を MagicDNS 名にして、LAN 用のブリッジが tailnet 経由でも届くか確かめる
  • Windows → Mac: claude -p と codex exec の使い切り実行が通るか確かめる
  • Tailscale SSH サーバーが Windows 非対応かどうかを一次情報で確かめ、Mac → Windows 方向の手段を決める
  • 検証の結果を、cross-machine-message スキルへ反映する案にまとめる(IP 探索の節を縮め、使い切り実行の経路を足す)

最後の項目には注意書きがある。 スキルの本体は別のセッションで作っている最中なので、反映する前に私へ確認を取る、という内容だ。

学び

  • Tailscale が楽にするのは「相手の機械にどう届くか」までだった。スキルでいちばん面倒な IP 探索の層は消えるが、動いているセッションへの割り込みは別の問題として残る
  • コマンドが PATH に無いことと、入っていないことは別だった。サービスの状態とインストール先まで見て、ようやく「入っているが、つながっていない」と分かった
#Tailscale#Claude Code#Codex#SSH#tmux#ネットワーク