← knym.net

Claude Code のステータスラインにモデル名と利用上限(セッション/週間)を常時表示させた

·11 min read
Claude Code開発環境カスタマイズAI

Claude Code で長い作業をしていると、気づかないうちにセッション上限に達して「リセットまで数時間動かせない」という状態になることがある。/usage で使用状況は確認できるが、作業のたびに開くのは面倒だし、開いていない間にじわじわ上限へ近づいてしまう。

Claude Code の /status Usage タブ。使用率は見られるが、毎回開いて確認するのは手間

そこで statusLine をカスタマイズして、モデル名・セッション上限・週間上限を画面下部に常時表示するようにした。
これなら「そろそろ区切ってコミットし、次のセッションに移る」という判断が、ステータスバーを見るだけでできる。

完成形

プロンプト下に「Fable 5 | Session 99% (01:10) | Week 30%」と常時表示されるステータスライン

Fable 5 | Session 58% (13:40) | Week 59% (7/9(Thu) 00:00) | Fable 83% | AI

仕組み

Claude Code の statusLinetype: "command" を指定すると、任意のシェルコマンドの出力をステータスバーに表示してくれる。コマンドには JSON が stdin で渡され、model.display_namerate_limits.five_hour.used_percentage といった情報を jq で取り出せる。

/status の Usage タブと同じレートリミット情報が JSON の rate_limits フィールドから取れるので、これを常時表示に回す。

Claude Code に作らせる(手っ取り早い方)

自分でファイルを置くのが面倒なら、次のプロンプトをそのまま Claude Code に貼れば、以下で解説するスクリプトと同じものを作って設定まで済ませてくれる。

Claude Code の statusLine を設定して。~/.claude/statusline-command.sh を新規作成し、
~/.claude/settings.json の statusLine に登録して、実行権限も付けて。

statusLine には JSON が stdin で渡される。半角の | 区切りで左から順に表示して:

1. モデル名 … .model.display_name(シアン)
2. Session … .rate_limits.five_hour.used_percentage を整数%、
   .rate_limits.five_hour.resets_at(epoch秒)を HH:MM にして「Session 58% (13:40)」
3. Week … .rate_limits.seven_day.used_percentage と .resets_at(epoch秒)で
   「Week 59% (7/9(Thu) 00:00)」。曜日は LANG=C の英語表記にする
4. Fable … .model.id に fable を含むときだけ、.rate_limits.model_scoped[] の中で
   display_name が fable のものの .utilization を「Fable 83%」
5. カレントディレクトリ名 …  .workspace.current_dir(無ければ .cwd)の basename(青)

各使用率は 60% で黄・80% で赤に色付け。値が取れない項目は表示しない(jq の // empty でフォールバック)。
色は ANSI エスケープ、出力は printf。% はフォーマット誤爆を避けて %% にエスケープすること。

スクリプト(完成版)

~/.claude/statusline-command.sh を作成する。これがそのまま動く最終形。

#!/bin/sh
# Claude Code statusLine
# 表示: 1) モデル名  2) セッション上限(5h)+リセット時刻  3) 週間上限(7d)+リセット日時
#       4) Fable枠(Fable使用時のみ)  5) ディレクトリ名
 
input=$(cat)
 
model_name=$(echo "$input" | jq -r '.model.display_name')
model_id=$(echo "$input" | jq -r '.model.id')
cwd=$(echo "$input" | jq -r '.workspace.current_dir // .cwd')
dir_name=$(basename "$cwd")
session_pct=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
session_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
week_pct=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
week_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
fable_pct=$(echo "$input" | jq -r '[.rate_limits.model_scoped[]? | select(.display_name | test("fable"; "i")) | .utilization][0] // empty')
 
# ANSI カラーコード
cyan="\033[0;36m"
blue="\033[0;34m"
green="\033[0;32m"
yellow="\033[0;33m"
red="\033[0;31m"
reset="\033[0m"
 
# 使用率に応じた色(60%で黄、80%で赤)
color_for() {
  if [ "$1" -ge 80 ]; then printf '%s' "$red"
  elif [ "$1" -ge 60 ]; then printf '%s' "$yellow"
  else printf '%s' "$green"; fi
}
 
out="${cyan}${model_name}${reset}"
 
# セッション上限(5時間枠)+ リセット時刻
if [ -n "$session_pct" ]; then
  s_int=$(printf "%.0f" "$session_pct")
  s_color=$(color_for "$s_int")
  if [ -n "$session_reset" ]; then
    reset_hm=$(date -r "$session_reset" +%H:%M 2>/dev/null)
    out="$out | ${s_color}Session ${s_int}%% (${reset_hm})${reset}"
  else
    out="$out | ${s_color}Session ${s_int}%%${reset}"
  fi
fi
 
# 週間上限(7日枠)+ リセット日時
if [ -n "$week_pct" ]; then
  w_int=$(printf "%.0f" "$week_pct")
  w_color=$(color_for "$w_int")
  if [ -n "$week_reset" ]; then
    week_reset_str=$(LANG=C date -r "$week_reset" '+%-m/%-d(%a) %H:%M' 2>/dev/null)
    out="$out | ${w_color}Week ${w_int}%% (${week_reset_str})${reset}"
  else
    out="$out | ${w_color}Week ${w_int}%%${reset}"
  fi
fi
 
# Fable 使用時のみ、モデル別枠(model_scoped)の Fable 使用率
case "$model_id" in
  *fable*)
    if [ -n "$fable_pct" ]; then
      f_int=$(printf "%.0f" "$fable_pct")
      f_color=$(color_for "$f_int")
      out="$out | ${f_color}Fable ${f_int}%%${reset}"
    fi
    ;;
esac
 
# ディレクトリ名
out="$out | ${blue}${dir_name}${reset}"
 
printf "$out"

実行権限を付けておく。

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

settings.json の設定

~/.claude/settings.json に statusLine の設定を追加する。新しいセッションを開くと反映される。

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

実装でハマったところ

printf "$out"% が化ける $out98% のような文字列が入っていると、% がフォーマット指定子として解釈されてエラーになる。文字列を組み立てる段階で %% にエスケープしておく必要がある(上のスクリプトで ${s_int}%% としているのはこのため)。

曜日の全角で幅がずれる 週間上限のリセット日時に曜日を出したくて、最初は LANG=ja_JP.UTF-8 で「(木)」と日本語表記にした。が、全角文字はターミナルによって幅計算がずれることがある。LANG=C の英語表記「(Thu)」に落ち着いた。区切りも半角 | だけにしておくのが無難。

使用率が取れないタイミングがある セッション開始直後、最初のメッセージを送る前は rate_limits が空になる。すべて // empty でフォールバックし、値がある項目だけ表示するようにしてある。

Fable 枠は「あるときだけ」出す 手元の JSON には five_hourseven_day しか来ておらず、Fable 専用のフィールドが見当たらなかった。実行バイナリを grep してスキーマを探すと、rate_limitsmodel_scoped という配列が定義されていた。

model_scoped: [
  {
    "display_name": "Fable",   // サーバーが付けるモデル枠のラベル
    "utilization": 83.4,       // 使用率
    "resets_at": "..."         // リセット日時
  }
]

スキーマの説明に "present only when the server emits them"(サーバーが出すときだけ存在する)とあるとおり、常に来るフィールドではない。「存在すれば表示する」という防御的な書き方にしておけば、枠が配信されるようになった時点で自動的に現れる。

なお JSON にどんなフィールドが来ているか確認したいときは、スクリプト先頭に echo "$input" > /tmp/statusline-debug.json を一時的に足して覗くのが手っ取り早い。

Context 使用率ではなく「利用上限」を出す理由

最初はセッション上限ではなく コンテキストウィンドウの使用率context_window.used_percentage)を表示していた。トークン残量が見えるので便利ではある。

「Fable 5 | Context 44% | knym-school-biz」と表示していた初期版

しばらく運用して気づいたのは、実際に作業を止められるのはコンテキストではなく利用上限(rate limit)の方だということ。コンテキストは逼迫しても要約(compact)が走って続行できるが、セッション上限が 100% になると You've used 100% of your session limit と表示され、リセット時刻まで手が止まる。止まるものを出したほうが実用的なので、表示を rate_limits に切り替えた。

運用してみて

Session が黄色(60%)になったら「そろそろ区切りを意識する」、赤(80%)になったら「作業を切り上げて git commit まで済ませる」。この判断がステータスバーを見るだけでできるようになった。リセット時刻も並んでいるので、「あと少しで復活するから休憩にしよう」という切り替えもしやすい。

特に複数のサブエージェントを走らせる長いセッションでは、気づかないうちに上限が近づいていることが多い。常時表示にしてからは、そこで焦らされることがなくなった。

「limitに近づいた時はcommitするように教えて」とプロンプトで入れとけば、いい感じに教えてくれて便利。