カテゴリー / 使い方の基本

Claude Code ステータスラインの設定手順と自作の考え方

この記事の目次

ステータスラインを最短で有効にする手順

この記事のBash手順はmacOS/Linux向けです。Windowsは公式のWindows向け手順を参照してください。

settings.json の statusLine に type: command と実行したいコマンドを1つ書けば有効になります。ステータスラインは、Claude Codeの入力欄の下に出る表示欄です。権限確認やヘルプの表示中は一時的に隠れることがあります。表示内容は、自分で用意したスクリプトの出力がそのまま使われます。

仕組みは単純です。Claude Codeがセッションの情報をJSONでスクリプトに渡し、スクリプトが標準出力に書いた文字列が表示されます。公式ドキュメントの2026年10月11日確認時点では、設定の保存で自動反映され、会話の更新などで再実行されます。連続する更新は300msでまとめられます。会話のない間も更新したい場合は、任意の refreshInterval(最小1秒)を検討できます。

最小のスクリプトを置いて指す

最初は中身を読まず、固定の文字列を出すだけのスクリプトで配線を確かめます。

#!/bin/bash
echo "statusline ok"

これを ~/.claude/statusline.sh に保存し、実行権限を付けます。

chmod +x ~/.claude/statusline.sh

個人用なら ~/.claude/settings.json に次を書きます。すでに他の設定がある場合は、既存の項目を消さずに statusLine だけを追記してください。

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}

設定を保存して statusline ok が見えれば、配線は完了です。表示が出ない場合は、後半の逆引き表で原因を切り分けられます。

なお、/statusline コマンドに「モデル名とブランチを出したい」のように自然言語で頼むと、Claude Code自身がスクリプトを作って設定まで書く方法もあります。ただ、生成されたスクリプトが何を読んでいるかを追えないと、後で直せません。本記事は、中身を自分で理解して直せる状態を目標にしています。

どのファイルに書くか

置き場所は、誰と共有するかで決めます。

置き場所 共有範囲 向いている場面
~/.claude/settings.json 自分の全プロジェクト 個人の好みの表示
.claude/settings.json リポジトリを使うチーム 全員に同じ表示を出したい
.claude/settings.local.json 自分のそのプロジェクトだけ 個人用の上書き、Git管理に含めない

迷ったときは、ユーザー設定から始めます。設定ファイル全般の優先順位や書き方は、settings.jsonの解説記事にまとめています。

渡されるJSONをダンプして確認する

スクリプトの標準入力をファイルへ書き出し、その中身を自分の目で開けば、自分の環境にどんなJSONが渡ってきているか分かります。公式のフィールド一覧を先に読むより、手元の実データを見てから表示項目を選ぶほうが、版の違いによる食い違いを避けられます。

用意するのは、受け取ったJSONをそのまま保存するだけのスクリプトです。

#!/bin/bash
cat > /tmp/statusline-dump.json
echo "dumping"

~/.claude/statusline-dump.sh として保存して、実行権限を付けます。

chmod +x ~/.claude/statusline-dump.sh

~/.claude/settings.json の statusLine.command を "~/.claude/statusline-dump.sh" に変えます。設定を保存してClaude Codeで1回やりとりすると、/tmp/statusline-dump.json が作られます。ダンプを外部へ共有する場合は、パスなどを確認してからにしてください。

中身は、別のターミナルを開いて確認します。

cat /tmp/statusline-dump.json

jq が入っていれば、整形して読めます。

jq . /tmp/statusline-dump.json

見るべき点は3つあります。1つ目は、モデルや作業ディレクトリに当たる値が、どの階層のどの名前で入っているかです。2つ目は、値が空や null になっている項目がないかです。会話の開始直後は、まだ値が埋まっていない項目があっても不思議ではありません。3つ目は、このあと使う項目のスペルです。手でコピーして使えば、打ち間違いを減らせます。

ダンプには、この記事で扱わない項目も含まれます。トークン残量の見方は目的が別なので、残量の確認方法の記事に譲ります。ここでは、表示したい項目を自分で選べれば十分です。

確認が済んだらダンプ用のスクリプトは外し、次の節の表示用スクリプトに差し替えます。ダンプ用のままだと、毎回ファイルへ書き込み続けます。

どの項目を、どう取り出して表示すればよいのか?

ダンプで見つけた項目を、スクリプト内で変数に取り出して echo で組み立てます。モデル名(model.display_name)と作業ディレクトリ(workspace.current_dir)は、公式の例でも使われる代表的な項目です。実際の名前はダンプで確かめます。

jqがある場合の最小例

jq はJSONから値を取り出すコマンドです。次の内容で ~/.claude/statusline.sh を上書きし、実行権限を保ちます。statusLine.command を "~/.claude/statusline.sh" に戻して設定を保存してください。

#!/bin/bash
if ! command -v jq >/dev/null 2>&1; then
  echo "statusline"
  exit 0
fi
input=$(cat)
if ! printf '%s' "$input" | jq -e 'type == "object"' >/dev/null 2>&1; then
  echo "statusline"
  exit 0
fi
model=$(printf '%s' "$input" | jq -r '.model | if type == "object" then .display_name else null end | if type == "string" then . else "?" end')
dir=$(printf '%s' "$input" | jq -r '(.workspace | if type == "object" then .current_dir else null end) as $dir | if ($dir | type) == "string" and $dir != "" then $dir elif (.cwd | type) == "string" then .cwd else "" end')
echo "[$model] ${dir##*/}"

モデル名が文字列でなければ ?、作業ディレクトリが文字列でなければ空文字を使います。${dir##*/} はパスの末尾のフォルダ名だけを残す書き方で、[Opus] my-project のような1行になります。

jqがない場合の最小例

jq が未導入でも、python3 が入っていれば同じことができます。

#!/usr/bin/env python3
import json, os, sys

try:
    data = json.load(sys.stdin)
except (ValueError, OSError):
    print("statusline")
    sys.exit(0)
if not isinstance(data, dict):
    print("statusline")
    sys.exit(0)

model_data = data.get("model")
model = model_data.get("display_name") if isinstance(model_data, dict) else None
model = model if isinstance(model, str) else "?"
workspace = data.get("workspace")
cwd = workspace.get("current_dir") if isinstance(workspace, dict) else None
if not isinstance(cwd, str) or not cwd:
    cwd = data.get("cwd")
cwd = cwd if isinstance(cwd, str) else ""
print(f"[{model}] {os.path.basename(cwd)}")

Python版は ~/.claude/statusline.py として保存し、実行権限を付けます。

chmod +x ~/.claude/statusline.py

statusLine.command を "~/.claude/statusline.py" に変更して設定を保存します。command -v python3 で依存を確認してください。以下のブランチ追加・キャッシュ例はjq版を選んだ場合の手順です。戻すときはスクリプトと statusLine.command の両方をjq版へ戻します。

jq版はjqが無い場合に固定の statusline を出します。Python版はpython3自体が無いと起動できません。依存を用意できない場合は、最初の固定文字列だけの構成にとどめます。

項目を1つ足してみる

練習として、gitのブランチ名を足します。ブランチ名はJSONには頼らず、コマンドで取ります。jq版の最後の行を次のように変えます。

先に command -v git でgitが使えるか確認してください。

branch=$(git -C "$dir" branch --show-current 2>/dev/null)
echo "[$model] ${dir##*/} ${branch:+($branch)}"

${branch:+($branch)} は、ブランチ名が取れたときだけ括弧つきで出す書き方です。gitリポジトリでない場所では何も足されないので、表示は崩れません。保存してClaude Codeで1回やりとりし、表示が変わったことを確かめたら、足した行を消して元に戻してみてください。足し引きを両方やっておくと、この先の改造が怖くなくなります。

自作・/statusline・ccstatuslineの比較

自分で直したいなら自作、まず形を見たいなら /statusline、見た目を設定画面で整えたいなら ccstatusline が候補です。決め手は、依存を増やしたくないか、見た目をどこまで作り込むか、保守を誰が担うかの3点です。

比較軸 自作(statusLine.command) /statusline コマンド ccstatusline
入口 スクリプトと設定を自分で書く 自然言語で頼むと生成される 配布元の手順で導入する
追加の依存 自分で選ぶ(シェルのみも可) 生成内容による 配布元の手順による
直しやすさ 全行を自分で把握できる 生成後は自作と同じ扱い 設定画面や設定ファイル側で調整する
保守 自分で行う 自分で行う 配布元の更新に追随する

自作と /statusline の列は、公式ドキュメントの説明に基づいています。ccstatusline の列は一般的な説明にとどめているので、導入前に配布元のREADMEで対応環境と設定方法を確認します。見た目の豊富さのように、横並びで根拠を示せない軸は表に入れていません。

選び方の目安は次のとおりです。

  • 表示を1〜2項目にとどめて長く使うなら、自作が軽く済みます。
  • 何を表示できるか見当がつかないうちは、/statusline で土台を作り、出力された中身を読んでから使います。
  • 色や並びを画面上で試行錯誤したいなら、ccstatusline のような既製品が合います。その代わり、更新への追随は配布元任せです。

どれを選んでも、仕組みの根は同じ statusLine 設定です。あとから乗り換えることもできます。

表示されない・古いまま・崩れるときの逆引き

症状ごとに、確認する場所はほぼ決まっています。まず、設定で指定したスクリプトを手で単体実行します。ダンプがまだ無い場合は、合成JSONで配線を確認できます。

printf '%s\n' '{"model":{"display_name":"Test"},"workspace":{"current_dir":"/tmp"}}' | ~/.claude/statusline.sh

jq版なら [Test] tmp が出れば単体実行は成功です。Python版を選んだ場合は、同じ入力の指し先を ~/.claude/statusline.py に読み替えます。

症状 実行する確認
何も表示されない(空出力) プロジェクトのtrust(信頼確認)が済んでいるか確認し、ダンプ済みのJSONを流し込んで手で実行する。~/.claude/statusline.sh < /tmp/statusline-dump.json で1行出るかを見る
値が古いまま やりとりを1回挟む。ダンプ用に差し替え、ファイルの更新時刻が動くかを見る
文字化け、色が出ない 端末の文字コードがUTF-8かを確認する。~/.claude/statusline.sh < /tmp/statusline-dump.json | cat -v で制御文字(^[[ など)が出力に含まれているかを見る
スクリプトが動かない ls -l ~/.claude/statusline.sh で実行権限を確認する。command -v jq(Python版は command -v python3)で依存の有無を確認する。head -1 ~/.claude/statusline.sh で先頭のshebangを確認する(Python版なら保存先を .py に読み替える)

権限確認やヘルプ表示中の一時非表示は異常ではありません。単体実行では出るのに、それ以外でも画面に出ないときは、settings.json の記述や置き場所を疑います。JSONの括弧やカンマの抜けも、原因になりえます。設定ファイルが複数ある場合は、別のファイルが同じ項目を上書きしていないかも見ます。

OSごとの差にも注意が要ります。macOSとLinuxでは、date や stat のオプションが異なることがあります。Windowsでは、コマンドがどのシェルで実行されるかによって .sh がそのまま動かない場合があるため、自分の環境でどのシェルが使われるかを確かめます。原因が公式で確認できないものは、この表では確認の手順だけを挙げています。

重い処理のキャッシュで軽さを保つ

重さへの備えは、スクリプトの側で入れます。時間のかかる処理を毎回は走らせないこと、そして入力の異常時に固定表示へ戻せる範囲を決めることの2点です。

失敗時の備え

入力が想定と違うとスクリプトが途中で止まり、空になることがあります。上の例は欠測・null・型違いに代替値を使い、不正JSONには固定の statusline を出します。ただし、Python自体が起動できない場合や権限の問題まで救済するものではありません。空出力の切り分けは、逆引き表の1行目で行います。

表示を飾る機能もあります。公式ドキュメントには、色づけ(ANSIエスケープ)や複数行、リンクの埋め込み(OSC 8)を扱う記述があります。ただし、端末アプリによって対応が分かれ、版によっても変わりえます。まず1行・単色で安定させ、そこから1つずつ足す順で進めます。

重い処理をキャッシュする

git の呼び出しは、大きなリポジトリでは時間がかかることがあります。表示のたびに実行するのでなく、数秒間は前回の結果を使い回します。

jq版を選んでいる場合は、次の内容で ~/.claude/statusline.sh を上書きします。設定の指し先はそのままです。モデル名・作業ディレクトリ・ブランチ名を表示します。

#!/bin/bash
if ! command -v jq >/dev/null 2>&1; then
  echo "statusline"
  exit 0
fi
input=$(cat)
if ! printf '%s' "$input" | jq -e 'type == "object"' >/dev/null 2>&1; then
  echo "statusline"
  exit 0
fi
model=$(printf '%s' "$input" | jq -r '.model | if type == "object" then .display_name else null end | if type == "string" then . else "?" end')
dir=$(printf '%s' "$input" | jq -r '(.workspace | if type == "object" then .current_dir else null end) as $dir | if ($dir | type) == "string" and $dir != "" then $dir elif (.cwd | type) == "string" then .cwd else "" end')
sid=$(printf '%s' "$input" | jq -r '.session_id | if type == "string" then . else "" end')
cache=""
if [[ "$sid" =~ ^[A-Za-z0-9_-]+$ ]]; then
  cache="${TMPDIR:-/tmp}/statusline-branch-$sid"
fi
now=$(date +%s)
ts=""
cached_dir=""
if [ -n "$cache" ]; then
  ts=$(head -n1 "$cache" 2>/dev/null)
  cached_dir=$(sed -n 3p "$cache" 2>/dev/null)
fi
if [[ "$ts" =~ ^[0-9]{1,10}$ ]]; then
  ts=$((10#$ts))
else
  ts=0
fi
if [ "$cached_dir" = "$dir" ] && [ "$ts" -le "$now" ] && [ $((now - ts)) -lt 5 ]; then
  branch=$(sed -n 2p "$cache")
else
  branch=$(git -C "$dir" branch --show-current 2>/dev/null)
  if [ -n "$cache" ]; then
    printf '%s\n%s\n%s\n' "$now" "$branch" "$dir" > "$cache"
  fi
fi
echo "[$model] ${dir##*/} ${branch:+($branch)}"

キャッシュはセッションIDごとに保存し、同じ作業ディレクトリのときだけ再利用します。同じセッションで別のディレクトリへ移った場合や時刻が壊れている場合は取り直します。セッションIDが欠けている場合はキャッシュしません。5秒という長さは、鮮度と軽さのつり合いで自分で決める値です。ブランチ切り替え直後に古い名前が数秒残ることは、仕様として許容します。

まとめ

次の一歩は1つだけに絞ります。いま使っているスクリプトに、表示項目を1つ足してください。ダンプで自分のJSONを確認し、取り出して、足し、確かめて、必要なら戻す。この流れを一度通せば、ステータスラインは自分で改造できる道具になります。

表示を整えたあとに自動化を広げたくなったら、hooksの解説とskillsの解説が次の読みどころです。ステータスラインが「見る」ための仕組みなのに対し、こちらは「動かす」ための仕組みです。

生成AIのツールは、設定を足すほど自分の手で管理する範囲も増えます。何を自作し、どう安全に育てるかを仲間と学びながら進めたい方には、学習コミュニティ「AI駆動ラボ」があります。月額1,980円から参加でき、自分の手でAIを使えるようになることを目的とした学びの場です。提供内容と最新の料金は、公開ページに掲載されています。