SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-26

VPSにClaude CodeのstatusLineを設定する方法

Claude CodeのstatusLineでスクリプトの標準出力をプロンプト下に表示します。hostname、ディレクトリ、gitブランチ、modelを出し、接続先のサーバーを取り違える事故を防ぎます。

Claude Code のステータスラインに表示される内容

Claude Code のステータスラインは、プロンプトの下に表示される行です。作成したスクリプトの出力を表示します。settings.json に statusLine ブロックを追加し、コマンドを指定します。Claude Code はそのコマンドを実行し、セッションの状態を JSON として標準入力から渡します。コマンドが標準出力に書き込んだ内容が表示されます。

これがすべての仕様です。スクリプトは標準入力から JSON を読み取り、標準出力にテキストを出力します。スクリプトは自分のマシン上で実行され、出力内容がモデルに送信されることはありません。そのため、トークンは消費しません。

プロジェクトが1つだけの laptop では、装飾にすぎません。サーバーが3台ある場合は、安全策になります。すべての Claude Code セッションは、どの terminal でも同じように見えます。そのため、ラベルのない SSH ウィンドウが4つあると、移行先を誤ったサーバーにしてしまう可能性があります。hostname で始まるステータスラインを表示すれば、この種類のミスを防げます。

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 件送信します。これでプロンプトの下のバーに、サーバーの短いホスト名が表示されます。空欄のままの場合、問題はスクリプトではなく、設定または信頼ダイアログにあります。下記の「statusline が空欄のままになる理由」を参照してください。

2026 年 8 月時点では、オプションのキーが 3 つあります。padding は文字単位の水平方向の余白を追加し、デフォルトは 0 です。refreshInterval は通常のトリガーに加えて、コマンドを N 秒ごとに再実行します。最小値は 1 です。これは、セッションがアイドル状態の間に時計などの変化する情報を表示する場合にのみ使用します。hideVimModeIndicator は、独自のスクリプトで vim モードをすでに描画している場合に、組み込みの -- INSERT -- テキストを非表示にします。

ステータスラインスクリプトはどのデータを受け取るか

このページを含め、どこかで読んだフィールド一覧をそのまま信頼しないでください。使用しているバージョンが実際に送るオブジェクトを取得します。標準入力をファイルに保存する一時的なスクリプトを作成します。

cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.sh

statusLine.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 ブランチ、モデル名を表示します。各フィールドにフォールバックがあるため、空の 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 経由で行い、// empty を付加します。そのため、キーの名前が変更または削除されていても空文字列になり、次の行でデフォルト値が設定されます。ディレクトリは workspace.current_dir、cwd、$PWD の順にフォールバックします。ブランチは単独の git ではなく git -C "$DIR" から取得するため、常に bar が表示しているディレクトリと一致します。

保存したら、実行可能にします。

chmod +x ~/.claude/statusline.sh

実行ビットは必須です。Claude Code はコマンドを shell 経由で実行するため、+x のないスクリプトは Permission denied で失敗します。stdout は出力されず、目に見えるエラーもないまま行が空白になります。

jq はコマンドラインで JSON を解析しますが、新規インストール直後の Ubuntu server にはありません。

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も出力されません。このテストに合格するスクリプトは、フィールド名が変更されても動作します。スクリプトにとって、名前が変更されたフィールドと存在しないフィールドは同じ事象だからです。

表示内容

statusline は組み込みのフッターバッジの上に独立した行として表示され、フッターバッジを置き換えません。正常に動作している場合、1 行に次の内容が表示されます。短いホスト名をシアンで表示し、その後にホームディレクトリを ~ に省略した作業ディレクトリを表示します。対象ディレクトリが git リポジトリの場合は、続けてブランチ名を黄色で表示します。最後に、モデル名を減光して表示します。4 つの要素に色を付けた、web-01 ~/api main Opus に近い表示になります。

セッション開始時(resume を含む)、新しい assistant メッセージの到着時、/compact の完了後、permission mode の変更時、vim mode の切り替え時、および refreshInterval の間隔を設定した場合はその間隔ごとに、行がスクリプトを再実行します。更新は 300 ms のデバウンス処理が行われるため、変更が短時間に集中してもスクリプトは 1 回だけ実行されます。autocomplete、help menu、permission prompt の表示中はバーが非表示になり、その後再び表示されます。

ホスト名を最初に表示する理由

複数のサーバーでエージェントを実行していると、現在位置を知らせるのは端末だけですが、端末の表示は信頼できません。tmux のペイン内から別の ssh 接続を開いても、ウィンドウタイトルに古い名前が残ることがあります。移動したことを認識していない shell がタイトルを設定しているためです。VPS 上の分離した tmux セッションで Claude Code を実行する状態にして、1 日後に再接続すると、画面上ではビルドサーバーと本番サーバーを区別できないことがあります。

ステータスラインは異なります。Claude Code 自体が、セッションごとに、そのセッションが保持するデータから表示するためです。誤ったペインから引き継がれたり、更新されない shell プロンプトによって古いままになったりすることはありません。表示されるのは、エージェントがファイルを書き込んでいるサーバーです。

サーバーごとに色を割り当て、表示内容を読む前に識別できるようにします。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 回のキー入力の違いですが、影響はインシデント全体を左右するほど異なります。残りの表示幅を使う価値があるのは、モデルとブランチです。モデルは再開したセッションを示し、ブランチはエージェントが main にコミットしようとしているかどうかを示します。

小さい画面では、これらすべてがさらに重要になります。代わりに使えるウィンドウタイトルがないためです。その構成であれば、スマートフォンから Claude Code を操作するを参照してください。

スクリプトを高速に保つ

スクリプトはアシスタントのすべてのメッセージで実行されます。また、Claude Code は新しい更新が届くと、実行中の処理をキャンセルします。そのため、スクリプトが遅いと古いテキストが表示されたり、何も表示されなかったりします。

各 jq 呼び出しのコストは数ミリ秒です。遅くなるのは git の部分です。キャッシュが空の状態で大規模なリポジトリに対して git status を実行すると、数百ミリ秒かかります。上記のスクリプトでは、意図的に git status を避け、git branch --show-current を呼び出しています。これは .git/HEAD を読み取り、すぐに結果を返します。

より負荷の高い処理を追加する場合は、結果をファイルにキャッシュし、数秒ごとに更新してください。セッションをキーにしてファイルを管理します。

CACHE="/tmp/statusline-$(field '.session_id')"

session_id を使用し、$$ は使用しないでください。$$ はスクリプトのプロセス ID です。呼び出しごとに変わるため、これをキーにしたキャッシュは常にミスし、毎回すべての処理コストが発生します。session_id はセッション全体で一定であり、セッションごとに異なります。そのため、2 つのリポジトリで実行している 2 つの Claude Code セッションが、互いのキャッシュ済みブランチ名を読み取ることはありません。セッションは設計上このように分離されています。一方のセッションから別のセッションへ処理を渡すには、意図的な操作が必要です。そのための機能が、ある Claude Code セッションから別のセッションへメッセージを送信する です。

もう 1 つ、把握しておくべき制限があります。tput cols は statusline スクリプト内では動作しません。Claude Code は出力を取得するだけで、スクリプトを端末に接続しないため、幅を検出する対象がありません。Claude Code は v2.1.153 以降、コマンドの実行前に COLUMNS と LINES の環境変数を設定します。表示量を決める必要がある場合は、$COLUMNS を読み取ってください。

ステータスラインが空白のままになる場合

何も表示されない。 ls -l ~/.claude/statusline.sh で実行ビットを確認し、上記のモック入力を使ってスクリプトを手動で実行します。シェルでは行が出力されるのに Claude Code では表示されない場合は、claude --debug から確認します。これはセッションで最初にステータスラインを実行したときの終了コードと stderr を記録します。

デバッグログに Status line command skipped: workspace trust not accepted と表示される。 ステータスラインは shell command を実行するため、hooks と同じ workspace trust のゲートが適用されます。そのディレクトリで trust ダイアログを承認するまで、コマンドは実行されません。これは VPS でよく発生します。新しく clone したディレクトリは、Claude Code がまだ認識していないためです。そのディレクトリで Claude Code を再起動し、ダイアログを承認します。

すべて空白で、disableAllHooks が設定されている。 settings.json の "disableAllHooks": true はステータスラインも無効にします。これも同じ shell-execution gate です。削除するか、false に設定します。

行に null と表示される。 jq selector が存在しない、または null の key に到達しています。jq -r は null を4文字の null として出力します。テキストには // empty、数値には // 0 を追加します。

スクリプトを編集した直後に行が空白になる。 non-zero で終了するコマンドや、何も出力しないコマンドがあると、行は空白になります。よくある原因は [ -n "$BRANCH" ] && LINE="..." のような最後の行です。branch が空の場合に終了コード 1 で終了し、そのスクリプト全体の終了コードになります。printf を最後に置くか、exit 0 を追加します。

\e]8;; などの escape code がバーにそのまま表示される。 echo -e の代わりに printf '%b' を使用します。クリック可能な OSC 8 リンクには、それをサポートする terminal も必要です。また、tmux や SSH がシーケンスを除去する場合があるため、リモートマシンでは通常の色指定のほうが安全です。

行の右側が切れる。 system notifications と verbose-mode token counter が右側から同じ行を使用するため、terminal の幅が狭いと重なった部分が失われます。出力を短くします。バー上の数値ではなく、使用量を正確に集計する方法については、Claude Code が token を数える方法を参照してください。

FAQ

Claude Code のステータスライン設定はどこにありますか?

settings.json 内の statusLine ブロックにあり、type を "command" に設定し、command をスクリプトパスまたはシェルコマンドに設定します。ユーザー設定は ~/.claude/settings.json にあり、そのマシン上のすべてのプロジェクトに適用されます。プロジェクト設定はリポジトリ内の .claude/settings.json にあり、そのディレクトリではこちらが優先されます。設定は自動的に再読み込みされますが、変更が表示されるのは次の更新トリガーが発生した後です。たとえば、次のメッセージ送信後に反映されます。

Claude Code のステータスラインが空白なのはなぜですか?

原因のほとんどは、次の4つです。スクリプトに実行ビットがないため、シェルが Permission denied を返し、stdout に何も出力されません。ワークスペースの信頼確認ダイアログが承認されておらず、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" でディレクトリを渡してください。これにより、ブランチが常にバーに表示しているディレクトリと一致します。

ステータスラインはトークンを消費しますか?セッションが遅くなりますか?

トークンは消費しません。スクリプトはローカルで実行され、その出力がモデルに送信されることはないためです。速度は利用者側で管理する必要があります。コマンドはすべての assistant メッセージで、300 ms のデバウンスを伴って実行されます。新しい更新が到着すると、Claude Code は実行中の処理をキャンセルするため、スクリプトの実行に丸1秒かかる場合は古い内容が表示されます。大規模なリポジトリでは git status を避け、時間のかかる処理は session_id をキーにしてファイルへキャッシュしてください。

サーバーごとに異なるステータスラインを表示するにはどうすればよいですか?

スクリプトは1つにして、マシンの情報を読み取らせてください。上記のスクリプトは $HOSTNAME を hostname -s にフォールバックして表示します。そのため、同じファイルを各サーバーにコピーすれば、それぞれの名前を正しく表示できます。また、チェックサムの色分けにより、各ホスト名に固有の色を割り当てられます。特定のサーバーだけ異なるレイアウトが必要な場合は、そのサーバーで作業するリポジトリのプロジェクト設定に statusLine ブロックを配置してください。そのディレクトリでは、プロジェクト設定がユーザー設定より優先されます。