Claude Media
CLAUDE_CODE_BRIDGE_SESSION_IDでRemote Control接続元を特定する

CLAUDE_CODE_BRIDGE_SESSION_IDでRemote Control接続元を特定する

Bash/hookサブプロセスに自動セットされる環境変数から、Remote Control経由のセッションをスクリプトで特定する方法をまとめます。

このTipsでできること

Remote Control接続中のセッションでBashコマンドやhookを実行すると、そのサブプロセスにCLAUDE_CODE_BRIDGE_SESSION_IDという環境変数が自動的にセットされます。この変数を読めば、スクリプト側から「いまどのセッションで実行されているか」をリンク付きで特定できます。ローカル実行とRemote Control実行を区別する通知スクリプトや、実行結果にセッションへの戻りリンクを添えるSessionEnd hookを書くときに使います。

CLAUDE_CODE_BRIDGE_SESSION_IDとは何か

CLAUDE_CODE_BRIDGE_SESSION_IDは、セッションがRemote Control接続を持っている間だけ、BashツールとHookコマンドのサブプロセスにセットされます。接続が終わると変数は削除されます。値はセッションのclaude.ai/codeURLに現れるものと同じsession_形式のIDです。Claude Code v2.1.199以降が対象です。

v2.1.289のRemote Control接続中セッションで、BashツールからIDを読んだ実際の出力は次のとおりです(IDの後半は伏せています)。

echo "BRIDGE=[${CLAUDE_CODE_BRIDGE_SESSION_ID:-未設定}] REMOTE=[${CLAUDE_CODE_REMOTE:-未設定}] PROJ=[${CLAUDE_PROJECT_DIR:-未設定}]"
BRIDGE=[session_01XXXXXXXXXXXXXXXXXXXXXX] REMOTE=[未設定] PROJ=[未設定]

出力から読み取れる点が2つあります。接続中のローカルセッションではCLAUDE_CODE_BRIDGE_SESSION_IDにsession_形式のIDが入り、CLAUDE_CODE_REMOTEは未設定のままです。そしてBashツールの中ではCLAUDE_PROJECT_DIRも未設定でした。後者はBashツールには渡らず、hookコマンドなどの起動時に渡る変数なので、Bashツールで確かめても空に見えます。

やり方 — Bash/hookからセッションURLを組み立てる

もっとも単純な使い方は、スクリプトの中で変数の有無を見て分岐することです。

if [ -n "$CLAUDE_CODE_BRIDGE_SESSION_ID" ]; then
  echo "Remote Control経由: https://claude.ai/code/${CLAUDE_CODE_BRIDGE_SESSION_ID}"
else
  echo "ローカル実行"
fi

hookコマンドから使う場合も同じ変数を読むだけです。たとえばBashの実行後に外部へ通知するhookで、実行したセッションへのリンクを本文に含められます。

#!/bin/bash
SESSION_URL=""
if [ -n "$CLAUDE_CODE_BRIDGE_SESSION_ID" ]; then
  SESSION_URL="https://claude.ai/code/${CLAUDE_CODE_BRIDGE_SESSION_ID}"
fi
curl -s -X POST "$WEBHOOK_URL" \
  -d "{\"text\": \"Bashコマンドが実行されました ${SESSION_URL}\"}"

Remote Controlでスマホから走らせているセッションでBashを実行したときだけ、通知にセッションへの戻りリンクが付きます。ローカルのターミナルから直接実行している間は変数が未設定なので、SESSION_URLは空文字のままです。通知本文からリンクが自然に消えます。

hookの登録は他のhookと変わりません。上のスクリプトをnotify-bash.shとして保存し、プロジェクトの.claude/settings.jsonに登録する例です。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/notify-bash.sh"
          }
        ]
      }
    ]
  }
}

${CLAUDE_PROJECT_DIR}は、hookスクリプトの置き場所を絶対パスに固定するための別の環境変数です。hookプロセスにはRemote Controlの有無に関係なく渡ります。

クラウドセッションかローカルかで読む変数が変わる

同じ「セッションを特定したい」という目的でも、実行場所によって読むべき変数が違います。Remote Controlはローカルで動くセッションをブラウザやスマホから操作する仕組みで、クラウドセッションとは実行場所が別です。

くらべる

読む変数の使い分け

BRIDGE

ローカル + Remote Control

CLAUDE_CODE_BRIDGE_SESSION_IDを読みます。Bash/hookのサブプロセスにだけ入り、接続が終わると消えます。Remote Control未接続のローカルCLIでは、どちらの変数も未設定です。

REMOTE

クラウドセッション

CLAUDE_CODE_REMOTE_SESSION_IDを読みます。claude.ai/code上で動くセッション自身が、トランスクリプトへのリンクを組み立てるための変数です。

両方の環境で同じスクリプトを使うなら、判定の順序は次のとおりです。

手順

環境を判定する順序

  1. 1

    CLAUDE_CODE_REMOTEを見る

    "true"ならクラウドセッションです。CLAUDE_CODE_REMOTE_SESSION_IDを読みます。

  2. 2

    CLAUDE_CODE_BRIDGE_SESSION_IDを見る

    クラウドでなければ、この変数の有無を確かめます。値があればRemote Control接続中のローカルセッションです。

  3. 3

    どちらも空ならローカル実行として扱う

    リンクを付けずに処理を進めます。

複数のセッションを並行して動かしていて、名前や見た目で区別したい場合はClaude Codeでセッションを見分ける方法も参照してください。

Remote Control自体が使えないと変数も現れない

変数はRemote Controlの接続を前提にしているので、Remote Controlが使えない構成では最初から値が入りません。公式のRequirementsには、次の条件が並んでいます。

前提条件

変数が現れなくなる条件

  • サブスクリプションとログイン

    Pro、Max、Team、Enterpriseプランが対象で、APIキーでは使えません。TeamとEnterpriseでは、オーナー(Owner)がClaude Code admin settingsでRemote Controlのトグルを先に有効にしている必要があります。

  • 接続先のAPIエンドポイント

    Amazon Bedrock、Google CloudのAgent Platform、Microsoft Foundryでは使えません。ANTHROPIC_BASE_URLをapi.anthropic.com以外のホスト(LLMゲートウェイやプロキシ)に向けている場合と、企業向けのClaude apps gatewayでサインインしている場合も対象外です。

  • フィーチャーフラグの取得を止める環境変数

    CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICまたはDISABLE_GROWTHBOOKを設定すると使えません。DISABLE_TELEMETRYとDO_NOT_TRACKだけなら使えます(v2.1.283以降。組織がTrusted Devicesを要求する場合は解除が必要)。

  • ワークスペースの信頼

    信頼していないディレクトリではclaude remote-controlが信頼してよいかを尋ねます。ホームディレクトリでは信頼が保存されないので、質問が毎回戻ります。

これらに当たる環境で「スクリプトがセッションを検知できない」と感じたら、変数名の綴りより先にRemote Controlそのものが有効かを確かめると切り分けが早く済みます。接続自体が確立できない、あるいは頻繁に切れる場合の切り分けはRemote Controlに接続できないときの見分け方と対処を参照してください。

接続が切れたあと、変数はどうなるか

変数は接続が有効な間だけ存在するので、切断の挙動がそのままスクリプトの見え方になります。公式のLimitationsには、状況ごとの挙動が次のように書かれています。

  • ネットワーク障害が続いたとき: 対話セッションは、障害が続く限り再試行して、回復すると自動で再接続します。サーバーモード(claude remote-control)は約10分で諦めてプロセスが終了するので、起動し直します
  • HTTP 403が返り続けたとき: 接続済みの対話セッションは最大3分間再試行し、それを超えると切断します。VPNやネットワークの切り替え後に起こりえます
  • ターミナルを閉じたとき: ローカルプロセスが止まるとセッションはオフラインになります。サーバーモードでは、--continueまたは--session-idで止めたセッションを呼び戻せます(v2.1.200以降。停止から約4時間以内が対象です)

放置による自動切断のタイミングはRemote Controlが20分放置で切断される原因と回避策にまとめています。

環境変数の継承に関する注意点

hookプロセスは基本的に親プロセスの環境変数をそのまま引き継ぎます。例外は2つあります。Claude Codeがすべてのサブプロセスから取り除くOTEL_*のエクスポーター変数と、CLAUDE_CODE_SUBPROCESS_ENV_SCRUBを1にしたときに取り除かれる変数です。

SCRUBを有効にすると、Bashツール・hook・MCP stdioサーバーのサブプロセスから、Claude Codeが資格情報と認識する変数が消えます。認識は変数名と値の形で行われます。APIキーやパスワードを含むURLだけでなく、NPM_TOKENのように名前が資格情報らしい変数も対象です。一方でGITHUB_TOKENとプロキシ設定は残ります。v2.1.251以降はCLAUDE_CONFIG_DIRも除去対象です。CLAUDE_CODE_BRIDGE_SESSION_IDは除去対象として挙がっていないので、SCRUBを有効にした環境でも読み取りに影響しません。

HTTP形式のhookでヘッダーに環境変数を載せる場合は事情が変わります。headersの値は$VAR_NAMEや${VAR_NAME}で変数を参照できますが、allowedEnvVarsに列挙した変数だけが解決され、ほかは空文字になります。CLAUDE_CODE_BRIDGE_SESSION_IDをWebhookヘッダーに含めるなら、allowedEnvVarsへの追記を忘れると常に空のヘッダーが送られます。

よくある質問

CLAUDE_CODE_BRIDGE_SESSION_IDの値は外部に送っても問題ないか

値はセッションのIDで、そこからセッションのURLをそのまま組み立てられます。そのため、社内向けの通知チャネルなど、送信先は限定しておくのが無難です。

Bashツール以外(ステータスラインなど)でも同じ変数を読めるか

公式docsにある記載は、Bashツールとhookコマンドのサブプロセスです。ステータスラインなど別の仕組みで起動されるプロセスへの扱いは載っていません。用途が異なる箇所で使う場合は、まずecho $CLAUDE_CODE_BRIDGE_SESSION_IDで実際に値が入るかを確認してから組み込みます。

v2.1.199より前のバージョンでは代わりに何を使うか

CLAUDE_CODE_BRIDGE_SESSION_ID自体がv2.1.199で追加された変数なので、それより前のバージョンに直接の代替手段はありません。まずclaude --versionで手元のバージョンを確認し、古い場合はアップデートしてから組み込みます。なおv2.1.79で先に導入されたのはVSCode拡張の/remote-controlで、CLI(ターミナル)のRemote Controlとは別の導入時期です。

よくあるつまずき

  • 一度読んだ値を使い回す: 接続が切れると変数も消えるので、hookの中で値をキャッシュせず、サブプロセスのたびに読み直す前提で書きます
  • --spawn worktreeで起動したサーバー: オンデマンドで作られるセッションごとに別のgit worktreeが割り当てられますが、変数はセッションを指すIDで、worktreeのパスは分かりません。作業中のworktreeのパスが必要なときは、hook入力JSONのcwdフィールドを読みます

まとめ

通知やログにセッションへの戻りリンクを残す用途なら、CLAUDE_CODE_BRIDGE_SESSION_IDは使うたびに読み直す前提で組みます。接続が切れた後に古いIDを引きずらず、ローカル実行では自然にリンクなしの出力になります。

この記事を共有:XはてブLinkedIn