Claude Code 状态列进阶攻略:配额倒数、缓存效率、隐藏字段全部接上

上一期状态列教学我们用了 5 个字段,但你知道吗,Claude Code 偷偷丢了 34 个字段给你,85% 的数据你根本没碰过。今天直接升级——配额剩多少、几分钟后恢复、缓存有没有在帮你省钱,全部加上去,5 步搞定。

一、成果预览

先看完成品。升级后的状态列一共三行:

第一行:模型名 Opus 4.6,旁边 1M 是 context 窗口大小,v2.1.84 是版本号,repo 名称,git 分支。绿色 +1304 是这个 session 加了 1304 行代码,红色 -118 删了 118 行。2M 1A 2D 代表 2 个文件被改、1 个新增、2 个删除。

第二行:进度条换成圆形,4% 代表 context 窗口才用了 4%。费用 12.06 美元,经过时间 8 小时 10 分钟。重点是配额区块——5h 4% 是 5 小时配额用了 4%,括号里 0h 31m 是倒数计时,告诉你 31 分钟后重置。7 天配额用了 22%,大约 20 小时 31 分后重置。

第三行:缓存命中率 97%,累计输入 221.7K 个 token、输出 121.9K,API 等待时间 47 分 45 秒,占总时间 9%。最后 cur 是当前这轮的明细。

二、隐藏字段揭秘

Claude Code 每次回复完丢给你的 JSON 有多大?完整抓出来数了一下,34 个字段。上一期我们只用了 5 个。今天不是 34 个全部都接,有些是重复的或很少用到的。挑了最实用的 6 大块:配额限制、缓存效率、token 追踪、版本号、代码增减量、git 文件统计。

其中最救命的是配额那块。如果你有 Pro 或 Max 订阅,这个一定要装。

三、第 1 步:配额倒数计时

用 Pro 或 Max 的人应该都被限速过。最痛苦的不是被限速本身,是你不知道什么时候才会恢复,要自己上 Anthropic 网站去查,有时候还查不到。

Claude Code 在 JSON 里面有两组配额数据。rate_limits.five_hour 是 5 小时的滚动配额,seven_day 是 7 天的。每一组都有一个 used_percentage 百分比,和一个 resets_at 重置时间。resets_at 是 Unix timestamp,我们把它转成「还剩几小时几分钟」就好。

倒数计时函数

Bash
fmt_countdown() {
  local reset_at=$1
  local now=$(date +%s)
  local diff=$(( reset_at - now ))
  if [ "$diff" -le 0 ]; then echo "now"; return; fi
  local h=$(( diff / 3600 ))
  local m=$(( (diff % 3600) / 60 ))
  printf "%dh %dm" "$h" "$m"
}

date +%s 抓现在的 Unix timestamp,用 resets_at 减掉就得到剩余秒数,再转成小时和分钟。如果已经过了重置时间就直接显示 now

抓取配额字段

Bash
RATE_5H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
RATE_7D=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
RESET_5H=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
RESET_7D=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')

RATE_5H 抓的是 5 小时配额的使用百分比,就是状态列上显示 5h 4% 那个数字。RESET_5H 是这个配额的重置时间,就是括号里 (0h 31m) 的来源。下面两行一样,只是换成 7 天的配额。

注意:这边用 // empty 不是 // 0。因为如果你不是 Pro 或 Max 用户,这些字段根本不会存在。用 empty 的话变量会是空的,后面判断到是空的就不会显示,不会报错。

颜色判断函数

写一个 color_pct 函数,超过 80% 就红色、超过 50% 黄色、其他绿色,这样配额快爆的时候直接变红色:

Bash
color_pct() {
  local val=$1
  if [ "$val" -ge 80 ]; then echo "$RED"
  elif [ "$val" -ge 50 ]; then echo "$YELLOW"
  else echo "$GREEN"; fi
}

显示逻辑

Bash
if [ -n "$RATE_5H" ]; then
  R5_INT=$(printf "%.0f" "$RATE_5H")
  R5_C=$(color_pct "$R5_INT")
  L2="${L2}${SEP}${DIM}5h${RESET} ${R5_C}${R5_INT}%${RESET}"
  if [ -n "$RESET_5H" ] && [ "$RESET_5H" != "null" ]; then
    R5_CD=$(fmt_countdown "$RESET_5H")
    L2="${L2} ${DIM}(${R5_CD})${RESET}"
  fi
fi

倒数计时放在括号里,最后看起来像这样:5h 78% (1h 23m)。以后被限速你看一眼就知道还要等多久。7 天配额一模一样的写法,改成 seven_day7d 就好。

四、第 2 步:缓存效率监控

Claude Code 每次 call API,会把你的 context 打包送出去。但如果上次送过的内容没变,它可以从缓存里读,不用重新送。重点来了——从缓存读的 token,价格只有新输入的十分之一。差 10 倍。所以缓存命中率越高你就越省钱。但问题是,你现在完全看不到这个数字。

Claude Code 在 JSON 里给你三个数字:cache_read_input_tokens 是从缓存读的,cache_creation_input_tokens 是新写进缓存的,input_tokens 是完全新的输入。三个加起来是总数,cache_read 除以总数就是命中率。

Bash
CACHE_READ=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // empty')
CACHE_CREATE=$(echo "$input" | jq -r '.context_window.current_usage.cache_creation_input_tokens // empty')
CUR_INPUT=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // empty')

CACHE_HIT=""
if [ -n "$CACHE_READ" ] && [ -n "$CUR_INPUT" ] && [ "$CUR_INPUT" != "0" ]; then
  CACHE_TOTAL=$((CACHE_READ + CUR_INPUT + ${CACHE_CREATE:-0}))
  if [ "$CACHE_TOTAL" -gt 0 ]; then
    CACHE_PCT=$((CACHE_READ * 100 / CACHE_TOTAL))
    CACHE_C=$(color_pct "$((100 - CACHE_PCT))")
    CACHE_HIT="${DIM}cache${RESET} ${CACHE_C}${CACHE_PCT}%${RESET}"
  fi
fi

注意 color_pct "$((100 - CACHE_PCT))",它是用 100 减去命中率。因为命中率越高越好,缓存 90% 的时候 100 减 90 等于 10,小于 50 所以显示绿色。反过来缓存只有 20% 就会变红色,提醒你效率很差。

小技巧:如果缓存命中率长期偏低,可能是你的对话太短或太碎,缓存来不及建立。试着把相关的问题集中在同一个 session 里处理。

五、第 3 步:Token 追踪 + API 效率

Claude Code 在 JSON 里有 total_input_tokenstotal_output_tokens,是整个 session 从头到现在累计吃了多少 token。

Bash
TOTAL_IN_TOKENS=$(echo "$input" | jq -r '.context_window.total_input_tokens // empty')
TOTAL_OUT_TOKENS=$(echo "$input" | jq -r '.context_window.total_output_tokens // empty')
API_DURATION_MS=$(echo "$input" | jq -r '.cost.total_api_duration_ms // 0')

total_api_duration_ms 是所有 API call 花的时间加总。用它除以 total_duration_ms,你就知道这个 session 有多少时间在等 API 回应。一般大概是 8% 到 15%,如果超过 20% 就代表你这个 session 很密集地在跟 Claude 互动。

但 token 数字动不动就几十万,直接显示 202100 很难读。写个函数把它转成 202.1K,超过一百万就显示 1.2M

Bash
fmt_tokens() {
  local t=$1
  if [ -z "$t" ] || [ "$t" = "null" ]; then echo "0"; return; fi
  if [ "$t" -ge 1000000 ]; then
    printf "%.1fM" "$(echo "scale=1; $t / 1000000" | bc)"
  elif [ "$t" -ge 1000 ]; then
    printf "%.1fK" "$(echo "scale=1; $t / 1000" | bc)"
  else
    echo "$t"
  fi
}

这边用到 bc 做小数运算,bash 本身不支持小数所以要借用它。macOS 内建就有,不用另外装。

六、第 4 步:视觉升级 + 信息扩充

圆形进度条

上一期的进度条是方块 ████████░░,10 格。把它改成圆形,格数从 10 改成 15,分辨率更高:

Bash
BAR_W=15
FILLED=$((PCT * BAR_W / 100)); EMPTY=$((BAR_W - FILLED))
BAR=""
for i in $(seq 1 $FILLED); do BAR="${BAR}${BAR_COLOR}●${RESET}"; done
for i in $(seq 1 $EMPTY); do BAR="${BAR}${DIM}●${RESET}"; done

换成 就好了。填满的用亮色,空的用 DIM 暗色。

版本号、Context 大小、代码增减

Bash
VERSION=$(echo "$input" | jq -r '.version // empty')
CTX_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size // empty')
LINES_ADD=$(echo "$input" | jq -r '.cost.total_lines_added // empty')
LINES_DEL=$(echo "$input" | jq -r '.cost.total_lines_removed // empty')

版本号 v1.0.80 放在模型名旁边,灰色小字。context 窗口大小超过一百万就显示 1M,不然就 200Klines_addedlines_removed 用绿色 +235 红色 -50 表示,一眼知道这个 session 的产出量。

Git 文件统计

上一期只显示分支名,现在加上改了几个文件、新增几个、删了几个:

Bash
GIT_M=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
GIT_A=$(git ls-files --others --exclude-standard 2>/dev/null | wc -l | tr -d ' ')
GIT_D=$(git diff --diff-filter=D --name-only 2>/dev/null | wc -l | tr -d ' ')

黄色 3M 代表 3 个 modified,绿色 1A 是 1 个 added,红色 2D 是 2 个 deleted。以后 git status 都不用打了,看一眼状态列就知道。

七、第 5 步:完整脚本 + 测试

完整脚本放在 YouTube 视频描述栏的链接。在复制之前,先了解一下整体结构,这样之后想改任何东西都知道去哪里改。

整个脚本分成三大块:

  • 工具函数(最上面):color_pct 判断颜色、fmt_dur 格式化时间、fmt_countdown 算倒数、fmt_tokens 转 token 单位。这些你不用动,除非你想改颜色的阈值。
  • 字段抓取(中间):每一行就是一个 jq 去捞一个字段。想加新字段?来这边加一行就好。
  • 三行输出(最下面):L1 是第一行、L2 是第二行、L3 是第三行。想改第二行的内容?找到 L2 那段改就好。不想看缓存命中率?把 CACHE_HIT 那段拿掉。完全看你自己想要什么配置。

用模拟数据测试

把完整脚本贴到 ~/.claude/statusline.sh,整个取代掉上次的版本。然后用模拟数据跑一下:

Bash
echo '{"model":{"display_name":"Opus 4.6 (1M context)"},"version":"1.0.80","workspace":{"current_dir":"/Users/matt/my-project"},"cost":{"total_cost_usd":0.84,"total_duration_ms":1398000,"total_api_duration_ms":243000,"total_lines_added":235,"total_lines_removed":50},"context_window":{"used_percentage":35,"context_window_size":1000000,"total_input_tokens":202100,"total_output_tokens":4500,"current_usage":{"input_tokens":1500,"cache_read_input_tokens":65500,"cache_creation_input_tokens":498}},"rate_limits":{"five_hour":{"used_percentage":16,"resets_at":'$(($(date +%s)+8100))'},"seven_day":{"used_percentage":41,"resets_at":'$(($(date +%s)+345600))'}}}' | ~/.claude/statusline.sh

三行全部出来。context 35% 所以进度条是绿色,5 小时配额 16% 也是绿色,倒数大概 2 小时 15 分。缓存命中率 97%,超绿的,代表大部分 token 都从缓存读,钱花得很值。

你可以把 used_percentage 改成 85 试试看,进度条和配额都会变红色警告你。

八、JSON 字段速查表

类别 字段 jq 路径
配额 5 小时使用百分比 .rate_limits.five_hour.used_percentage
配额 5 小时重置时间 .rate_limits.five_hour.resets_at
配额 7 天使用百分比 .rate_limits.seven_day.used_percentage
缓存 缓存读取 token .context_window.current_usage.cache_read_input_tokens
缓存 缓存写入 token .context_window.current_usage.cache_creation_input_tokens
缓存 新输入 token .context_window.current_usage.input_tokens
Token 累计输入 token .context_window.total_input_tokens
Token 累计输出 token .context_window.total_output_tokens
效率 API 总耗时 .cost.total_api_duration_ms
版本 Claude Code 版本号 .version
Context 窗口大小 .context_window.context_window_size
代码 新增行数 .cost.total_lines_added
代码 删除行数 .cost.total_lines_removed