Claude Code statusline完全ガイド——コンテキスト・コスト・レート制限を1行監視する設定術

Claude Code statusline完全ガイド——コンテキスト・コスト・レート制限を1行監視する設定術

Claude Codeのステータスライン(statusline)をゼロから設定する方法を解説。コンテキスト圧迫・レート制限切れ・コスト超過に気づかず作業が止まる困りごとを、実際に動くbash/jqスクリプト付きで解消する。

エンジニアのゆとです。

Claude Codeで集中して作業していたら、急に Compacting conversation... が始まって手が止まる。あるいは、納期直前のクライアント案件でコマンドを打ったら「5時間のレート制限に達しました」と言われて詰む。

どっちも「気づかないうちにリソースを使い切っていた」というのが本質だ。/context/status を都度打てば確認できるが、思考の流れを切ってまで確認する人は少ない。この「うっすら不安だけど確認が面倒」を解消するのが、Claude Code の statusline(ステータスライン)機能だ。

この記事では、公式ドキュメントの仕様を裏取りしながら、実際に動くbash/jqスクリプトと、フリーランスで複数クライアント案件を掛け持ちする自分が実際に使っている構成を紹介する。


そもそも statusline とは何か

statusline は、Claude Code の入力欄の下に常時表示されるカスタマイズ可能な1行(または複数行)のバーだ。自分でシェルスクリプトを用意しておくと、Claude Code がそのスクリプトに JSON データを渡して実行し、標準出力に書いた内容がそのままバーとして表示される。

重要な特性が2つある。

  1. APIトークンを消費しない — statusline はローカルで実行されるスクリプトの結果を表示しているだけで、Claude本体への問い合わせではない。何回更新されても課金には影響しない
  2. イベント駆動で更新される — 新しいアシスタントメッセージの後、/compact 完了後、パーミッションモードの変更時、vimモード切り替え時に自動実行される。更新は300msでデバウンスされるので、連続更新で暴発することもない

つまり「常時監視のダッシュボードを、コストゼロで置ける」という機能だ。使わない理由がない。


なぜフリーランスエンジニアほどstatuslineの設定が必須なのか

ここが競合記事があまり触れていない部分だと思う。個人開発や趣味で使う分には、statuslineがなくても「なんとなく」で回せる。だが、複数クライアントの案件を並行して抱えるフリーランスの働き方だと、statuslineなしの運用は普通に事故る。

事故パターン1: コンテキスト圧迫に気づかず作業が飛ぶ

長時間のセッションでコンテキストウィンドウが埋まってくると、ある瞬間に自動 /compact が走る。要約されること自体は仕組みとして正しいが、「直前まで詰めていた細かい実装方針」が要約で欠落することがある。事前にコンテキスト残量が見えていれば、キリのいいところで自分から /compact するか、CLAUDE.mdに状態を書き出してから休憩に入れる。見えていないと、勝手に要約が走って「あれ、さっき決めたエラーハンドリングの方針どこいった」となる。

事故パターン2: レート制限に納期直前で気づく

Pro/Maxプランには5時間ローリングウィンドウと7日間ウィンドウのレート制限がある。rate_limits.five_hour.used_percentagerate_limits.seven_day.used_percentage は、実は最初のAPIレスポンスが返ってきた後からJSONに乗ってくる値で、statuslineに出していない限り、制限に当たるまで自分の消費率を知る手段がほとんどない。クライアントAの案件で消費した分がクライアントBの納期直前にツケとして回ってくる、というのは複数案件持ちなら一度は経験する。

事故パターン3: セッションコストが後から怖くなる

cost.total_cost_usd はセッション単位の推定コストだ。従量課金のAPIキーで運用している場合、これを見ずに長時間セッションを回すと、あとで請求を見て青ざめることになる。案件ごとにコストを把握しておきたい個人事業主にとって、これは実務上のニーズに近い。

3つとも共通しているのは「情報自体はJSONの中に存在するのに、見る習慣がないから事故る」という構造だ。statuslineは、この「見る習慣」を自動化する仕組みとして機能する。


最速セットアップ: /statuslineコマンドで自動生成

一番手軽なのは /statusline コマンドに自然言語で欲しい内容を伝える方法だ。Claude Code が ~/.claude/ にスクリプトを生成し、設定も自動で書き換えてくれる。

/statusline show model name and context percentage with a progress bar

「削除したい」「元に戻したい」場合も同じコマンドで済む。

/statusline delete

まずはこれで試して、物足りなくなったら次の手動設定に進むのがいい流れだ。自分も最初の1週間は自動生成のまま使って、そこから欲しい情報を足していった。


手動でフル設定する: ステップバイステップ

自分で完全にコントロールしたい場合の手順を書く。

ステップ1: JSONを受け取るスクリプトを書く

Claude Code は stdin 経由でスクリプトにJSONデータを送ってくる。jq コマンド(未インストールなら brew install jq などで入れる)でパースするのが定番だ。

~/.claude/statusline.sh として保存する。

#!/bin/bash
# Claude Code が stdin に送ってくるJSONデータを読み取る
input=$(cat)

# jq でフィールドを抽出する
MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
# "// 0" はフィールドが null の場合のフォールバック
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

echo "[$MODEL] 📁 ${DIR##*/} | ${PCT}% context"

ステップ2: 実行権限を与える

chmod +x ~/.claude/statusline.sh

ステップ3: settings.jsonに登録する

~/.claude/settings.json(プロジェクト単位で設定する場合は .claude/settings.json)に statusLine フィールドを追加する。

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

type"command" 固定。command にはスクリプトパスだけでなく、インラインのシェルコマンドも直接書ける。試しにモデル名とコンテキスト割合だけをワンライナーで出す場合はこうなる。

{
  "statusLine": {
    "type": "command",
    "command": "jq -r '\"[\\(.model.display_name)] \\(.context_window.used_percentage // 0)% context\"'"
  }
}

padding は左右の余白(デフォルト0)、refreshInterval を秒数で指定すると、イベント駆動に加えて一定間隔でも再実行される(経過時間の表示など、時間ベースの値を扱う場合に設定する)。

Claude Code の settings.json 完全ガイド 2026——スコープ・チーム設定・パーミッション管理を整理する
Claude Code の settings.json 完全ガイド 2026——スコープ・チーム設定・パーミッション管理を整理するsettings.json の4スコープ(管理/ローカル/プロジェクト/ユーザー)と settings.local.json の分離方法、チーム開発での permissions 設計、CLAUDE.md との違いを公式ドキュメントベースで整理。2026年6月版。読む →

stdinで渡されるJSONの全体像

スクリプトが受け取れる主なフィールドを整理しておく。公式ドキュメントに載っている全フィールドのうち、実用上よく使うものだけに絞った。

フィールド内容
model.display_name現在のモデル表示名(例: Opus)
workspace.current_dir現在の作業ディレクトリ
workspace.git_worktreegit worktree名(worktree内で作業している場合のみ)
cost.total_cost_usdセッションの推定コスト(USD)
cost.total_duration_msセッション開始からの経過時間
context_window.used_percentageコンテキストウィンドウの使用率(%)
rate_limits.five_hour.used_percentage5時間レート制限の消費率(%)。Pro/Maxのみ、最初のAPIレスポンス後に出現
rate_limits.seven_day.used_percentage7日レート制限の消費率(%)
session_idセッション固有のID(キャッシュのキーに使える)
effort.level現在のeffortレベル(low/medium/high/xhigh/max)
pr.numberpr.review_state現在のブランチに紐づくPR番号とレビュー状態
worktree.branchworktreeセッションのブランチ名

context_window.used_percentagerate_limits.* は、セッション開始直後は null になりうる。スクリプト側で // 0// empty のフォールバックを必ず入れておかないと、-- のような空表示になったりスクリプトエラーで真っ白になったりする。

context_window の割合は入力トークン(input_tokens + cache_creation_input_tokens + cache_read_input_tokens)だけから計算されていて、出力トークンは含まれない。/context コマンドの表示と若干ズレることがあるのは、この計算タイミングの違いによるものなので、バグではない。


実践レシピ集

用途別に、実際に動くスクリプトをまとめる。全部bashで書いているが、公式ドキュメントにはPython/Node.js版も用意されているので、好みで置き換えて構わない。

コンテキスト使用率を色つきプログレスバーで表示する

閾値で色を変えると、視界の端で気づける。70%未満は緑、70〜89%は黄、90%以上は赤にする例。

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)

GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'

if [ "$PCT" -ge 90 ]; then COLOR="$RED"
elif [ "$PCT" -ge 70 ]; then COLOR="$YELLOW"
else COLOR="$GREEN"; fi

FILLED=$((PCT / 10)); EMPTY=$((10 - FILLED))
printf -v FILL "%${FILLED}s"; printf -v PAD "%${EMPTY}s"
BAR="${FILL// /█}${PAD// /░}"

echo -e "[$MODEL] ${COLOR}${BAR}${RESET} ${PCT}%"

赤くなった瞬間に「そろそろキリをつけよう」と判断できる。これだけでcompactの不意打ちがかなり減った。

レート制限を先読みして「詰む」前に気づく

自分がフリーランスとして一番助けられているのがこれだ。5時間・7日の両ウィンドウを1行に出す。

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
# "// empty" は rate_limits が未出現の場合、何も出さない
FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')

RED='\033[31m'; YELLOW='\033[33m'; RESET='\033[0m'

fmt_limit() {
  local pct=$1
  local label=$2
  local p=$(printf '%.0f' "$pct")
  if [ "$p" -ge 80 ]; then echo -e "${RED}${label}:${p}%${RESET}"
  elif [ "$p" -ge 50 ]; then echo -e "${YELLOW}${label}:${p}%${RESET}"
  else echo "${label}:${p}%"; fi
}

LIMITS=""
[ -n "$FIVE_H" ] && LIMITS="$(fmt_limit "$FIVE_H" "5h")"
[ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }$(fmt_limit "$WEEK" "7d")"

[ -n "$LIMITS" ] && echo -e "[$MODEL] | $LIMITS" || echo "[$MODEL]"

5時間ウィンドウが80%を超えたら赤くする。ここが赤くなったタイミングで「このタスクは今のセッションで終わらせるか、次のリセットまで待つか」を判断する。案件を掛け持ちしていると、この判断を後回しにした結果、一番忙しい時間帯に制限に当たるということが普通に起きる。事前に見えているだけで、対応の選択肢が増える。

Claude Codeの429エラー(Rate Limit)、使用量制限との違いを公式ドキュメントで切り分けた
Claude Codeの429エラー(Rate Limit)、使用量制限との違いを公式ドキュメントで切り分けたClaude Codeで429エラーが出ても、それはプランの月内制限とは別物。使用量制限・APIレート制限・529オーバーロードの違いを公式ドキュメントで整理し、原因別の対処法とヘッダー活用法をまとめた。読む →

コストと経過時間を追跡する

従量課金のAPIキーで運用している場合、これがないと請求書を見て初めて驚くことになる。

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

COST_FMT=$(printf '$%.2f' "$COST")
DURATION_SEC=$((DURATION_MS / 1000))
MINS=$((DURATION_SEC / 60))
SECS=$((DURATION_SEC % 60))

echo "[$MODEL] 💰 $COST_FMT | ⏱️ ${MINS}m ${SECS}s"

cost.total_cost_usd はクライアント側の推定値であり、実際の請求額と完全一致するとは限らない点は認識しておく。あくまで「今どれくらい使っているか」の目安として見る。

Claude Codeのトークン消費を半減させた10の実践テクニック——MAXプランでも油断するとすぐ上限に達する
Claude Codeのトークン消費を半減させた10の実践テクニック——MAXプランでも油断するとすぐ上限に達するClaude Code MAXプランでもトークン消費は無制限ではない。CLAUDE.mdの最適化、/compact活用、Plan Mode、サブエージェント設計など、実測データ付きで節約術を解説。読む →

git worktree・ブランチを出して案件の取り違えを防ぐ

複数クライアントの案件を worktree で並行管理していると、「今どの案件のディレクトリで作業しているか」を見失うことがある。git ブランチと worktree名をまとめて表示すると、この事故を防げる。

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
WORKTREE=$(echo "$input" | jq -r '.worktree.name // empty')

GREEN='\033[32m'; MAGENTA='\033[35m'; RESET='\033[0m'

if git rev-parse --git-dir > /dev/null 2>&1; then
    BRANCH=$(git branch --show-current 2>/dev/null)
    STAGED=$(git diff --cached --numstat 2>/dev/null | wc -l | tr -d ' ')
    MODIFIED=$(git diff --numstat 2>/dev/null | wc -l | tr -d ' ')

    GIT_STATUS=""
    [ "$STAGED" -gt 0 ] && GIT_STATUS="${GREEN}+${STAGED}${RESET}"
    [ "$MODIFIED" -gt 0 ] && GIT_STATUS="${GIT_STATUS}${GREEN}~${MODIFIED}${RESET}"

    WT_LABEL=""
    [ -n "$WORKTREE" ] && WT_LABEL=" ${MAGENTA}[wt:${WORKTREE}]${RESET}"

    echo -e "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH $GIT_STATUS${WT_LABEL}"
else
    echo "[$MODEL] 📁 ${DIR##*/}"
fi

worktree名がマゼンタで出ていると、「今このセッションはメインの作業ツリーではなく、並行タスク用のworktreeだ」と一目で分かる。案件Aの修正のつもりで打ったコマンドが案件Bのworktreeに入っていた、という凡ミスが物理的に見えるようになる。

Claude Code × Git Worktreeで並列開発する——AIに複数タスクを同時進行させる実践ガイド
Claude Code × Git Worktreeで並列開発する——AIに複数タスクを同時進行させる実践ガイドClaude Codeの-wフラグとGit Worktreeを使い、複数の開発タスクをコンフリクトなしに同時実行する手順を解説。ブランチ戦略・セッション管理・実践的なワークフロー設計まで。読む →

複数行にまとめる

1行にすべて詰め込むと視認性が落ちる。echo を複数回呼べば、その分だけ行が増える。1行目にモデル・ディレクトリ・gitブランチ、2行目にコンテキスト・コスト・経過時間、という構成が自分の定番だ。

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
PCT=$(echo "$input" | jq -r '.context_window.used_percentage // 0' | cut -d. -f1)
DURATION_MS=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')

CYAN='\033[36m'; GREEN='\033[32m'; YELLOW='\033[33m'; RED='\033[31m'; RESET='\033[0m'

if [ "$PCT" -ge 90 ]; then BAR_COLOR="$RED"
elif [ "$PCT" -ge 70 ]; then BAR_COLOR="$YELLOW"
else BAR_COLOR="$GREEN"; fi

FILLED=$((PCT / 10)); EMPTY=$((10 - FILLED))
printf -v FILL "%${FILLED}s"; printf -v PAD "%${EMPTY}s"
BAR="${FILL// /█}${PAD// /░}"

MINS=$((DURATION_MS / 60000)); SECS=$(((DURATION_MS % 60000) / 1000))

BRANCH=""
git rev-parse --git-dir > /dev/null 2>&1 && BRANCH=" | 🌿 $(git branch --show-current 2>/dev/null)"

echo -e "${CYAN}[$MODEL]${RESET} 📁 ${DIR##*/}$BRANCH"
COST_FMT=$(printf '$%.2f' "$COST")
echo -e "${BAR_COLOR}${BAR}${RESET} ${PCT}% | ${YELLOW}${COST_FMT}${RESET} | ⏱️ ${MINS}m ${SECS}s"

出力イメージはこんな感じになる。

[Opus] 📁 my-app | 🌿 feature/auth-refactor
█████████░ 87% | $2.14 | ⏱️ 42m 18s

コンテキストバーが赤に近づいてきたら、そろそろ区切りをつけるサインだ。


重い操作はキャッシュする

git statusgit diff は、リポジトリが大きくなると実行に時間がかかることがある。statuslineスクリプトはメッセージのたびに実行されるので、遅いコマンドをそのまま毎回叩くとステータスラインの更新自体が遅延する。

キャッシュファイル名には session_id を使うのが公式推奨のやり方だ。プロセスID($$)は呼び出しごとに変わってしまうためキャッシュとして機能しないが、session_id はセッションの間ずっと安定していて、かつセッションごとに一意になる。

#!/bin/bash
input=$(cat)

MODEL=$(echo "$input" | jq -r '.model.display_name')
DIR=$(echo "$input" | jq -r '.workspace.current_dir')
SESSION_ID=$(echo "$input" | jq -r '.session_id')

CACHE_FILE="/tmp/statusline-git-cache-$SESSION_ID"
CACHE_MAX_AGE=5

cache_is_stale() {
    [ ! -f "$CACHE_FILE" ] || \
    [ $(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$CACHE_FILE" 2>/dev/null || echo 0))) -gt $CACHE_MAX_AGE ]
}

if cache_is_stale; then
    if git rev-parse --git-dir > /dev/null 2>&1; then
        BRANCH=$(git branch --show-current 2>/dev/null)
        echo "$BRANCH" > "$CACHE_FILE"
    else
        echo "" > "$CACHE_FILE"
    fi
fi

BRANCH=$(cat "$CACHE_FILE")
[ -n "$BRANCH" ] && echo "[$MODEL] 📁 ${DIR##*/} | 🌿 $BRANCH" || echo "[$MODEL] 📁 ${DIR##*/}"

git情報を5秒だけキャッシュし、それより新しい呼び出しはキャッシュファイルを読むだけにしている。大きめのモノレポで作業している場合、これをやるかどうかでステータスラインの体感速度がかなり変わる。


自分でスクリプトを書きたくない場合

コミュニティ製のOSSツールもある。ccstatusline は TUI で設定できるツールで、GitHub Star数もそれなりに集まっている。テーマ選択や表示項目のオン/オフをGUI感覚で操作できるので、「まず動くものが欲しい、カスタマイズは後で」という場合は選択肢になる。

自分はスクリプトを直接書く派だが、理由は単純で、レート制限の色分け閾値のような「自分の働き方に合わせた微調整」をしたいからだ。OSSツールの標準設定で満足できるなら、それで十分だと思う。無理に自作にこだわる必要はない。


よくあるトラブルと対処法

ステータスラインが何も表示されない

まず chmod +x を忘れていないか確認する。次に、スクリプトが標準エラー出力(stderr)ではなく標準出力(stdout)に書いているか確認する。手元のターミナルで直接実行してみるのが早い。

echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/home/user/project"},"context_window":{"used_percentage":25},"session_id":"test-session"}' | ~/.claude/statusline.sh

これで意図した出力が出るなら、スクリプト自体は問題ない。表示されない場合は claude --debug で終了コードとstderrを確認する。

ワークスペーストラストを未承認のままだと statusline skipped · restart to fix と出て動かない。Claude Codeを再起動してトラストダイアログを承認すれば直る。

-- や空欄が表示される

context_window.used_percentagerate_limits.* は、セッションの最初のAPIレスポンスが返るまで null のままだ。// 0// empty のフォールバックを入れているか見直す。数回やり取りしても空のままなら、Claude Codeを再起動する。

コンテキスト割合が /context の表示とズレる

バグではない。used_percentage は入力トークンのみ(キャッシュ含む)から計算されていて、/context は別のタイミング・別の計算式で出している。どちらも「おおよその目安」として扱えばよく、厳密な一致を求める値ではない。


まとめ

  • statuslineはAPIトークンを消費しないローカル実行の仕組みで、/statusline コマンドか手動設定(~/.claude/settings.jsonstatusLine フィールド)で有効化できる
  • フリーランスで複数案件を掛け持ちする働き方では、コンテキスト圧迫・レート制限切れ・コスト超過という3つの「気づかない事故」を防ぐ実務上の意味がある
  • context_window.used_percentagerate_limits.five_hour/seven_day.used_percentagecost.total_cost_usdworktree.name あたりを組み合わせておけば、案件の取り違えとリソース切れの両方を先読みできる
  • 遅いgitコマンドは session_id をキーにキャッシュして、ステータスラインの体感速度を落とさないようにする
  • 自作が面倒なら ccstatusline のようなOSSツールで最低限のカスタマイズから始めてもいい

statuslineは地味な機能だが、「気づかないうちに詰む」を防ぐという意味では、Claude Codeの安定運用に直結する設定だと思う。まだ設定していない場合は、まず /statusline コマンドで自動生成させるところから始めてみてほしい。


関連記事

Claude Code の settings.json 完全ガイド 2026——スコープ・チーム設定・パーミッション管理を整理する
Claude Code の settings.json 完全ガイド 2026——スコープ・チーム設定・パーミッション管理を整理するsettings.json の4スコープ(管理/ローカル/プロジェクト/ユーザー)と settings.local.json の分離方法、チーム開発での permissions 設計、CLAUDE.md との違いを公式ドキュメントベースで整理。2026年6月版。読む →
Claude Codeの429エラー(Rate Limit)、使用量制限との違いを公式ドキュメントで切り分けた
Claude Codeの429エラー(Rate Limit)、使用量制限との違いを公式ドキュメントで切り分けたClaude Codeで429エラーが出ても、それはプランの月内制限とは別物。使用量制限・APIレート制限・529オーバーロードの違いを公式ドキュメントで整理し、原因別の対処法とヘッダー活用法をまとめた。読む →
Claude Code × Git Worktreeで並列開発する——AIに複数タスクを同時進行させる実践ガイド
Claude Code × Git Worktreeで並列開発する——AIに複数タスクを同時進行させる実践ガイドClaude Codeの-wフラグとGit Worktreeを使い、複数の開発タスクをコンフリクトなしに同時実行する手順を解説。ブランチ戦略・セッション管理・実践的なワークフロー設計まで。読む →
Claude Codeのトークン消費を半減させた10の実践テクニック——MAXプランでも油断するとすぐ上限に達する
Claude Codeのトークン消費を半減させた10の実践テクニック——MAXプランでも油断するとすぐ上限に達するClaude Code MAXプランでもトークン消費は無制限ではない。CLAUDE.mdの最適化、/compact活用、Plan Mode、サブエージェント設計など、実測データ付きで節約術を解説。読む →
← 記事一覧に戻る