Claude Code Claude Code effort設定 jq settings.json シェルスクリプト ステータスライン ターミナルカスタマイズ

Claude Codeのステータスラインに、いま使っているモデル名と reasoning effort、そしてレート制限の消費率を出したい。settings.jsonにスクリプトを1本足すだけで実現できますが、実際に組むと「あるはずのフィールドがモデルによって丸ごと消える」「使用率が小数で来て色分けの比較が落ちる」あたりでつまずきます。完成したスクリプトと、その回避方法を書きます。

結論から言うと、モデル名・effort・レート制限の3つはすべて表示できます。ただしモデル別の週次枠だけは出せません。その理由も後半で説明します。

この記事はステータスラインを既に動かしている前提で、表示項目を増やす話に絞ります。有効化そのものの手順は扱いません。

完成した表示

実際の表示がこれです。左からモデル名、effort、カレントディレクトリ、コンテキスト使用率、5時間枠と7日枠のレート制限使用率。

Opus 5 effort:high ctx 5% 5h 21% / 7d 36% と表示されたステータスライン

gitリポジトリ内で作業しているときは、ディレクトリの右にブランチ名も入ります。上の画像はホームディレクトリで撮ったので出ていません。

スクリプトの全文

~/.claude/statusline.shとして保存し、chmod +xで実行権限を付けます。

#!/bin/bash
# Claude Code ステータスライン
# stdin から JSON を受け取り、1行のステータス文字列を stdout に出力する

input=$(cat)

# モデル表示名(例: Opus 5, Sonnet 5)
model=$(echo "$input" | jq -r '.model.display_name // "unknown"')

# reasoning effort レベル(low/medium/high/xhigh/max)
# モデルが effort 非対応の場合はフィールド自体が存在しないので "-" にする
effort=$(echo "$input" | jq -r '.effort.level // "-"')

# カレントディレクトリ(ホーム配下は ~ に短縮)
dir=$(echo "$input" | jq -r '.workspace.current_dir // .cwd // ""')
dir="${dir/#$HOME/~}"

# gitブランチ(リポジトリでなければ空)
branch=$(git -C "$(echo "$input" | jq -r '.workspace.current_dir // .cwd')" branch --show-current 2>/dev/null)

# コンテキスト使用率
ctx=$(echo "$input" | jq -r '.context_window.used_percentage // empty')

# レート制限の使用率(Pro/Max購読者のみ。非購読者は rate_limits ごと存在しない)
# 小数(例: 23.5)で来るので round で整数に丸めてから使う
rl5=$(echo "$input" | jq -r '(.rate_limits.five_hour.used_percentage // empty) | round')
rl7=$(echo "$input" | jq -r '(.rate_limits.seven_day.used_percentage // empty) | round')

# ANSIカラー(256色)
C_MODEL=$'\033[38;5;209m'   # オレンジ: モデル名
C_EFFORT=$'\033[38;5;140m'  # 紫: effort
C_DIR=$'\033[38;5;110m'     # 水色: ディレクトリ
C_GIT=$'\033[38;5;107m'     # 緑: ブランチ
C_DIM=$'\033[38;5;244m'     # グレー: 区切りや補助情報
C_WARN=$'\033[38;5;179m'    # 黄: 使用率が高め(50%超)
C_ALERT=$'\033[38;5;203m'   # 赤: 使用率が危険域(80%超)
C_RESET=$'\033[0m'

# 使用率の数値に応じた色を返す(50%超で黄、80%超で赤、それ以下はグレー)
rate_color() {
  if [ "$1" -gt 80 ]; then
    printf '%s' "$C_ALERT"
  elif [ "$1" -gt 50 ]; then
    printf '%s' "$C_WARN"
  else
    printf '%s' "$C_DIM"
  fi
}

# 組み立て
out="${C_MODEL}${model}${C_RESET} ${C_DIM}|${C_RESET} ${C_EFFORT}effort:${effort}${C_RESET}"
out+=" ${C_DIM}|${C_RESET} ${C_DIR}${dir}${C_RESET}"
[ -n "$branch" ] && out+=" ${C_DIM}|${C_RESET} ${C_GIT}${branch}${C_RESET}"
[ -n "$ctx" ] && out+=" ${C_DIM}| ctx ${ctx}%${C_RESET}"
# レート制限は 5h / 7d をまとめて表示
if [ -n "$rl5" ] || [ -n "$rl7" ]; then
  out+=" ${C_DIM}|${C_RESET}"
  [ -n "$rl5" ] && out+=" $(rate_color "$rl5")5h ${rl5}%${C_RESET}"
  [ -n "$rl5" ] && [ -n "$rl7" ] && out+=" ${C_DIM}/${C_RESET}"
  [ -n "$rl7" ] && out+=" $(rate_color "$rl7")7d ${rl7}%${C_RESET}"
fi

printf '%s' "$out"

settings.jsonへの登録方法はClaude Codeのステータスラインをカスタマイズする設定方法に書いたとおりですが、レート制限を出すならrefreshIntervalを足してください。

"refreshInterval": 30

レート制限は時間経過で回復する値です。この指定が無いとプロンプトを打ったときにしか再描画されず、待っている間に回復した分が反映されません。

effortは非対応モデルだとフィールドごと消える

effortは.effort.levelで取れます。値はlowmediumhighxhighmax。セッション途中で/effortを実行して変更した場合もその場で追従します。

注意点は、effortに対応していないモデルではこのフィールド自体がJSONに存在しないことです。値が空文字やnullで来るのではなく、キーごと無くなります。だから// "-"のフォールバックが要ります。これを書かないと、モデルを切り替えたときにeffort:と中身が空のまま表示されて壊れて見えます。

同じ理屈でrate_limitsも、Claude.aiのPro/Max購読者にしか入りません。さらに購読していても、セッション最初のAPIレスポンスが返るまでは現れません。five_hourseven_dayは独立して欠けることがあるので、片方だけ存在するケースも想定しておく必要があります。上のスクリプトで区切りの/を条件付きで出しているのはそのためです。

使用率は小数で来るので丸めてから比較する

レート制限のused_percentage23.5のような小数で来ます。そのまま出すと5h 23.5%と桁が伸びて幅が安定しません。それ以上に困るのが色分けで、bashの[ "$1" -gt 80 ]は整数しか扱えないため、小数を渡すとinteger expression expectedでエラーになります。

jq側で| roundを通しておくと、表示の幅と色分けの比較がまとめて片付きます。

rl5=$(echo "$input" | jq -r '(.rate_limits.five_hour.used_percentage // empty) | round')

括弧の位置が要点です。// emptyを先に評価してからroundに渡すことで、キーが無いときはemptyが伝播して空文字になり、値があるときだけ丸められます。

なお// emptyと使用率0の組み合わせは、はじめ「0が消えるのでは」と疑って別の書き方をしていました。実際に確かめると消えません。jqの//演算子が右辺を返すのは左辺がfalsenullのときだけで、数値の0はそのまま通ります。手元でused_percentageを0にしたJSONを流すと5h 0% / 7d 0%と正しく出ました。if ... then ... else empty endで書き直す必要はありません。

確認は「欠けたJSON」で行う

スクリプト単体にJSONを流して動作確認する手順自体は前回の記事に書きました。effortとレート制限を扱う場合に足すべきなのは、正常系ではなくフィールドが欠けたJSONで試すことです。

試すべきパターンは4つあります。effortを抜いたもの、rate_limitsごと抜いたもの、seven_dayだけ入れたもの、使用率を0にしたもの。

# rate_limits ごと欠けたケース
echo '{"cwd":"/Users/foo","model":{"display_name":"Haiku"},"workspace":{"current_dir":"/Users/foo"}}' | ~/.claude/statusline.sh

# seven_day だけ存在するケース
echo '{"cwd":"/Users/foo","model":{"display_name":"Opus 5"},"workspace":{"current_dir":"/Users/foo"},"rate_limits":{"seven_day":{"used_percentage":41.2}}}' | ~/.claude/statusline.sh

正常系だけ通して満足すると、モデルを切り替えた瞬間に区切り線だけが並ぶ表示になります。ステータスラインはエラーを出さず黙って崩れるので、欠損パターンを先に潰しておくのが確実です。

モデル別の週次枠は表示できない

Claude Codeで/statusを実行すると、モデル別の週次使用量が出ます。同じものをステータスラインに出そうとしましたが、これはできませんでした。

ステータスラインのスクリプトに渡されるJSONのrate_limitsfive_hourseven_dayの2つだけで、モデル別の内訳を持つキーが用意されていないためです。seven_dayは全モデル合算の週次枠なので、特定モデルの消費量ではありません。

ステータスラインのスクリプトは、Claude Code本体が組み立てたJSONを受け取って表示するだけの立場です。本体が内部で持っていても、JSONに入れて渡してもらえない値は取りようがありません。モデル別の内訳が見たいときは/statusを使う、という切り分けになります。

表示できる項目の早見表

項目 JSONのパス 備考
モデル名 .model.display_name 「Opus 5」のように世代まで入る。.model.idならモデルID
effort .effort.level 非対応モデルではキーごと存在しない
コンテキスト使用率 .context_window.used_percentage 残量はremaining_percentage
レート制限(5時間) .rate_limits.five_hour.used_percentage Pro/Max限定。小数
レート制限(7日) .rate_limits.seven_day.used_percentage 全モデル合算。モデル別は取得不可
リセット時刻 .rate_limits.five_hour.resets_at Unix epoch秒
セッション累計コスト .cost.total_cost_usd USD
カレントディレクトリ .workspace.current_dir
fast mode .fast_mode 真偽値
出力スタイル .output_style.name

ステータスラインをまだ有効にしていない場合や、設定したのに表示されない場合はClaude Codeのステータスラインをカスタマイズする設定方法を先に見てください。