Claude CodeのVPSステータスライン設定方法
Claude CodeのstatusLineでスクリプトを実行し、標準出力にホスト名、ディレクトリ、gitブランチ、モデルを表示します。接続先を間違えない設定例を紹介します。
Claude Code のステータスラインに表示される内容
Claude Code のステータスラインは、プロンプトの下に表示される行です。作成したスクリプトの出力を表示します。settings.json に statusLine ブロックを追加し、コマンドを指定します。Claude Code はそのコマンドを実行し、セッションの状態を JSON として標準入力に渡します。コマンドが標準出力に書き込んだ内容が表示されます。
これがすべての仕様です。スクリプトは標準入力から JSON を読み取り、標準出力にテキストを書き込みます。スクリプトは自分のマシン上で実行されます。出力内容がモデルに送信されることはないため、トークンも消費しません。
プロジェクトが 1 つだけのラップトップでは、装飾にすぎません。サーバーが 3 台ある環境では、安全策になります。すべてのターミナルで Claude Code のセッション表示は同じです。そのため、ラベルのない SSH ウィンドウが 4 つあると、移行作業を誤ったサーバーで実行しやすくなります。ホスト名で始まるステータスラインを表示すれば、この種のミスを防げます。
settings.json で statusLine 設定を記述する場所
ユーザー設定の ~/.claude/settings.json に記述します。この設定は、そのマシン上のすべてのプロジェクトに適用されます。リポジトリ内の .claude/settings.json にプロジェクト設定を記述することもできます。この場合、そのディレクトリではプロジェクト設定が優先されます。
{
"statusLine": {
"type": "command",
"command": "~/.claude/statusline.sh"
}
}type は常に "command" です。command の値は shell を介して実行されるため、スクリプトのパスまたは通常のコマンドを指定できます。スクリプトを書く前に、まず接続が機能することを確認します。
{
"statusLine": {
"type": "command",
"command": "hostname -s"
}
}Claude Code を起動し、メッセージを 1 件送信します。プロンプトの下にあるバーに、サーバーの短いホスト名が表示されます。空のままの場合、問題はスクリプトではなく設定または trust ダイアログにあります。下記の「statusline が空白のままになる理由」を参照してください。
2026 年 8 月時点では、オプションのキーが 3 つあります。padding は文字単位の水平方向の間隔を追加し、デフォルト値は 0 です。refreshInterval は通常のトリガーに加えて、コマンドを N 秒ごとに再実行します。最小値は 1 です。この設定は、行に時計など、セッションがアイドル状態でも変化する内容を表示する場合に限って使用します。hideVimModeIndicator は、独自のスクリプトですでに vim mode を表示している場合に、組み込みの -- INSERT -- テキストを非表示にします。
ステータスラインスクリプトはどのようなデータを受け取りますか?
このページを含め、どこかで読んだフィールド一覧を信用しないでください。使用中のバージョンが実際に送信するオブジェクトを取得します。標準入力をファイルに保存する一時的なスクリプトを作成します。
cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.shstatusLine.command をそのファイルに指定し、セッションを開始して、メッセージを 1 件送信します。バーには captured と表示されます。次に、受信した内容を確認します。
jq . /tmp/statusline-input.jsonこれで、使用中のビルドにおける正確な構造がわかります。更新によって内容が変わった場合も、いつでも同じ手順を繰り返せます。
2026 年 8 月時点で文書化されている安定した部分は、フラットなキーではなく、ネストされたオブジェクトです。model には id と display_name が含まれます。workspace には current_dir と project_dir が含まれます。current_dir は現在のセッションの場所、project_dir はセッションを起動した場所です。セッション中に作業ディレクトリを変更すると、この 2 つは異なります。トップレベルの cwd には、workspace.current_dir と同じ値が入ります。context_window にはトークン数と、事前計算された used_percentage が含まれます。cost には total_cost_usd と経過時間のカウンターが含まれます。session_id はセッション中は変わらず、セッション間では一意です。これは後でキャッシュする際に重要です。
次の 3 つのルールに従うと、スキーマが変更されてもスクリプトを動作させ続けられます。
キーが null ではなく、存在しない場合があります。 vim、agent、pr、worktree、effort は、対応する機能が有効な場合にのみ現れます。vim モードが無効な状態で jq -r を使って .vim.mode を読み取ると、文字列 null がそのまま出力され、バーには null と表示されます。すべてのセレクターに // empty を追加すると、キーがない場合は何も出力されません。
値が初期状態では null の場合があります。 最初の API 応答が返る前は context_window.used_percentage と context_window.current_usage が null です。また、/compact の後は、次の呼び出しで再び値が設定されるまで current_usage が null に戻ります。そのため、バーにコンテキストの割合を表示する場合は // 0 が必要です。これを指定しないと、各セッションの最初の数秒間は null を読み取ることになります。その数値をバーに表示する前に、コンテキストウィンドウが実際にどのように埋まるかを確認しておくと役立ちます。
git ブランチは JSON に含まれません。 ブランチを報告するフィールドはありません。バーに表示されるブランチは、スクリプト自体が git を実行して取得したものです。
エラーではなく縮退する statusline スクリプト
これはそのままコピーして貼り付けられるバージョンです。hostname、作業ディレクトリ、git ブランチ、model name を表示します。すべてのフィールドにフォールバックがあるため、空の JSON オブジェクトでも使用可能な行を生成します。
#!/bin/bash
# ~/.claude/statusline.sh
input=$(cat)
# Read one field. Prints nothing when the key is missing or null.
field() { printf '%s' "$input" | jq -r "$1 // empty" 2>/dev/null; }
HOST=$(hostname -s 2>/dev/null)
[ -z "$HOST" ] && HOST="host"
DIR=$(field '.workspace.current_dir')
[ -z "$DIR" ] && DIR=$(field '.cwd')
[ -z "$DIR" ] && DIR="$PWD"
MODEL=$(field '.model.display_name')
[ -z "$MODEL" ] && MODEL="claude"
SHORT="$DIR"
if [ -n "$HOME" ]; then
case "$DIR" in
"$HOME") SHORT="~" ;;
"$HOME"/*) SHORT="~/${DIR#"$HOME"/}" ;;
esac
fi
BRANCH=""
if git -C "$DIR" rev-parse --git-dir >/dev/null 2>&1; then
BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)
[ -z "$BRANCH" ] && BRANCH="detached"
fi
CYAN=$'\033[36m'
YELLOW=$'\033[33m'
DIM=$'\033[2m'
RESET=$'\033[0m'
LINE="${CYAN}${HOST}${RESET} ${SHORT}"
[ -n "$BRANCH" ] && LINE="${LINE} ${YELLOW}${BRANCH}${RESET}"
LINE="${LINE} ${DIM}${MODEL}${RESET}"
printf '%s\n' "$LINE"すべての読み取りは field を経由します。field は // empty を追加するため、キーの名前が変更された場合や削除された場合でも空文字列になり、次の行でデフォルト値が設定されます。ディレクトリは workspace.current_dir、cwd、$PWD の順にフォールバックします。ブランチは単独の git ではなく git -C "$DIR" から取得します。そのため、ブランチは常に statusline に表示されているディレクトリと一致します。
保存したら、実行可能にします。
chmod +x ~/.claude/statusline.sh実行ビットは必須です。Claude Code はこのコマンドをシェル経由で実行するため、+x がないスクリプトは Permission denied で失敗します。標準出力も生成されず、表示行はエラーを表示しないまま空白になります。
jq はコマンドラインで JSON を解析します。新規インストールした Ubuntu サーバーにはインストールされていません。
sudo apt update && sudo apt install -y jq次に、上記の最初の settings.json ブロックを使用して、設定の参照先をこのスクリプトに変更します。
信頼する前にスクリプトをテストする
手動で 2 回実行します。最初は通常のセッションオブジェクトを使います。
echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.shホスト名、続いて /srv/api、その後に Opus が表示されます。マシン上の /srv/api はおそらく Git リポジトリではないため、ブランチは表示されません。
次に、劣化テストを行います。これは省略されがちなテストです。
echo '{}' | ~/.claude/statusline.sh空のオブジェクトは、スキーマ変更によって渡される可能性がある最悪のケースです。それでも行は、ホスト名、$PWD から取得した現在のディレクトリ、モデル名が入る箇所の claude を表示します。クラッシュせず、null も表示されません。このテストに合格するスクリプトは、フィールド名が変更された場合でも動作します。スクリプトにとって、名前が変更されたフィールドと存在しないフィールドは同じ事象だからです。
表示される内容
ステータスラインは組み込みのフッターバッジの上に専用の行として表示され、フッターバッジを置き換えません。正常に動作する構成では、1 行に、シアン色の短いホスト名、ホームディレクトリを ~ に省略した作業ディレクトリ、ディレクトリが git リポジトリの場合は黄色のブランチ名、薄く表示されたモデル名が順に並びます。4 つの要素に色を付けると、web-01 ~/api main Opus に近い表示になります。
セッション開始時(resume を含む)、新しい assistant メッセージの到着時、/compact の完了後、permission mode の変更時、vim mode の切り替え時、および refreshInterval の間隔を設定している場合はその間隔ごとに、行がスクリプトを再実行します。更新には 300 ms のデバウンスが適用されるため、変更が短時間に集中してもスクリプトは 1 回だけ実行されます。autocomplete 中、ヘルプメニュー表示中、permission prompt 表示中はバーが非表示になり、その後再表示されます。
ホスト名を最初に表示する理由
複数のサーバーでエージェントを実行している場合、自分がどこにいるかを伝えるのはターミナルだけですが、ターミナルの表示は誤ることがあります。tmux のペイン内から 2 つ目の ssh 接続を開くと、ウィンドウタイトルに古い名前が残ることがあります。タイトルを設定したシェルが、接続先の変更を認識していないためです。VPS 上の分離した tmux セッションで Claude Code を実行したままにすると、翌日に再接続したとき、画面上ではビルドサーバーと本番サーバーを区別できないことがあります。
ステータスラインは異なります。Claude Code 自体が、セッションごとに、そのセッションが保持するデータからステータスラインを描画するためです。誤ったペインから継承されたり、更新されないシェルプロンプトによって古いまま残ったりすることはありません。表示されるのは、エージェントがファイルを書き込んでいるサーバーです。
サーバーごとに色を割り当てると、表示内容を読む前にサーバーを識別できます。LINE= の代入の上に、次の 2 行を追加します。
CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")次に、${CYAN} の代わりに ${HOST_COLOR} を使用します。cksum はホスト名のチェックサムを出力します。そのため、同じ名前は常に 31 から 36 の範囲、つまり赤からシアンまでの同じ色に対応します。同じスクリプトを各サーバーにコピーすれば、それぞれのサーバーが自分自身を表示します。
ディレクトリを表示する理由も同じです。/srv/api と /srv/api-staging は、ssh コマンドでは 1 回のキー入力の違いですが、影響としてはインシデント全体の差になります。残りの 2 つとして表示幅を割く価値があるのは、モデルとブランチです。モデルは再開したセッションを示し、ブランチはエージェントが main にコミットしようとしているかどうかを示します。
画面が小さい場合は、ウィンドウタイトルに頼れないため、これらの情報がさらに重要になります。その構成を使用している場合は、スマートフォンから Claude Code を操作するを参照してください。
スクリプトを高速に保つ
スクリプトは assistant のメッセージごとに実行されます。また、Claude Code は新しい更新が届くと、実行中の処理をキャンセルします。そのため、スクリプトが遅いと古いテキストが表示されたり、何も表示されなかったりします。
jq の各呼び出しには数ミリ秒かかります。遅くなるのは git の部分です。大規模なリポジトリでキャッシュが空の場合、git status には数百ミリ秒かかります。上記のスクリプトでは、意図的に git status を避け、git branch --show-current を呼び出しています。git branch --show-current は .git/HEAD を読み取り、すぐに結果を返します。
より負荷の高い処理を追加する場合は、結果をファイルにキャッシュし、数秒ごとに更新してください。セッションをキーにしてファイルを管理します。
CACHE="/tmp/statusline-$(field '.session_id')"session_id を使用し、$$ は使用しないでください。$$ はスクリプトのプロセス ID です。呼び出しごとに異なるため、これをキーにしたキャッシュは常にミスし、毎回すべての処理コストが発生します。session_id はセッション全体で安定しており、セッションごとに異なります。そのため、異なるリポジトリで実行している 2 つの Claude Code セッションが、互いのキャッシュ済みブランチ名を読み取ることはありません。
もう 1 つ、知っておくべき制限があります。tput cols は statusline スクリプト内では機能しません。Claude Code は出力を取得するだけで、スクリプトを端末に接続しないため、幅を検出する対象がありません。v2.1.153 以降では、Claude Code がコマンドの実行前に COLUMNS と LINES の環境変数を設定します。表示量を決める必要がある場合は、$COLUMNS を読み取ってください。
ステータスラインが空白のままになる理由
何も表示されません。 ls -l ~/.claude/statusline.sh で実行ビットを確認し、上記のモック入力を使ってスクリプトを手動で実行します。シェルでは行が表示されるのに Claude Code では表示されない場合は、claude --debug から確認します。このファイルには、セッションで最初にステータスラインを実行したときの終了コードと標準エラー出力が記録されます。
デバッグログに Status line command skipped: workspace trust not accepted と表示されます。 ステータスラインはシェルコマンドを実行するため、フックと同じワークスペース信頼ゲートの対象になります。そのディレクトリに対する信頼ダイアログを承認するまで、コマンドは実行されません。これは VPS でよく発生します。新しく clone したディレクトリは、Claude Code がまだ認識していないためです。そのディレクトリで Claude Code を再起動し、ダイアログを承認します。
すべて空白で、disableAllHooks が設定されています。 settings.json の "disableAllHooks": true もステータスラインを無効にします。これも同じシェル実行ゲートを制御する設定だからです。削除するか、false に設定します。
行に null と表示されます。 jq のセレクターが存在しない、または null のキーに到達しています。jq -r は null を null という 4 文字で出力します。テキストには // empty、数値には // 0 を追加します。
スクリプトを編集した直後に行が空白になります。 終了ステータスが 0 以外のコマンドや、何も出力しないコマンドがあると、行は空白になります。よくある原因は [ -n "$BRANCH" ] && LINE="..." のような最後の行です。分岐が空の場合に終了ステータス 1 となり、スクリプト全体の終了ステータスになります。最後は printf にするか、exit 0 を追加します。
エスケープコードが \e]8;; のようなリテラル文字列としてバーに表示されます。 echo -e ではなく printf '%b' を使用します。クリック可能な OSC 8 リンクには、それをサポートする端末も必要です。また、tmux や SSH がシーケンスを削除することがあります。そのため、リモートホストでは通常の色表示のほうが安全です。
行の右側が切れます。 システム通知と verbose モードのトークンカウンターが右側から同じ行を使用するため、端末の幅が狭いと表示が重なります。出力を短くします。バー上の数値ではなく使用量を正確に確認する方法については、Claude Code がトークンを数える方法を参照してください。
FAQ
Claude Code のステータスライン設定はどこにありますか?
settings.json に statusLine ブロックとして設定します。type を "command" に設定し、command にはスクリプトのパスまたはシェルコマンドを指定します。ユーザー設定は ~/.claude/settings.json にあり、そのマシン上のすべてのプロジェクトに適用されます。プロジェクト設定はリポジトリ内の .claude/settings.json にあり、そのディレクトリではこちらが優先されます。設定は自動的に再読み込みされますが、変更が表示されるのは次の更新トリガーが発生したときだけです。たとえば、次のメッセージを送信したときです。
Claude Code のステータスラインが空なのはなぜですか?
ほぼすべてのケースは、次の 4 つの原因に当てはまります。スクリプトに実行ビットがないため、シェルが Permission denied を返し、標準出力に何も出力されません。ワークスペースの信頼ダイアログを承認していないため、claude --debug が Status line command skipped: workspace trust not accepted を記録します。disableAllHooks が true であり、同じ条件によりステータスラインが無効になっています。または、スクリプトが 0 以外の終了コードで終了しているため、行が空になります。まず手動でテストしてください。echo '{}' | ~/.claude/statusline.sh は何らかの内容を出力する必要があります。
ステータスラインの JSON には git ブランチが含まれますか?
いいえ。JSON には、モデル、ワークスペースのディレクトリ、コンテキストウィンドウの数値、コストなどのセッション状態が含まれます。git に関する情報は含まれません。バーに表示するブランチは、独自のスクリプトから git branch --show-current を呼び出して取得します。JSON の git -C "$DIR" からディレクトリを渡してください。これにより、ブランチがバーに表示されているディレクトリと常に一致します。
ステータスラインはトークンを消費したり、セッションを遅くしたりしますか?
トークンは消費しません。スクリプトはローカルで実行され、その出力がモデルに送信されることはないためです。速度の管理は利用者の責任です。コマンドはアシスタントのメッセージごとに 300 ms のデバウンス付きで実行されます。新しい更新が届くと Claude Code は実行中の処理をキャンセルするため、スクリプトに 1 秒かかると古い内容が表示されます。大規模なリポジトリでは git status を避け、時間のかかる処理は session_id をキーにしたファイルへキャッシュしてください。
サーバーごとに異なるステータスラインを表示するにはどうすればよいですか?
スクリプトは 1 つだけ用意し、マシンの情報を読み取らせてください。上記のスクリプトは hostname -s をフォールバックとして $HOSTNAME を表示します。そのため、同じファイルを各サーバーにコピーしても、それぞれのサーバーを正しく識別できます。チェックサムの色分けにより、各ホスト名に固有の色も割り当てられます。特定のサーバーで異なるレイアウトが必要な場合は、そのサーバー上で作業するリポジトリのプロジェクト設定に statusLine ブロックを配置してください。そのディレクトリでは、プロジェクト設定がユーザー設定より優先されます。