用 Claude Code 写代码的时候,我日常任务都是使用的 GLM Coding Plan,也算是支持国产了。用了 Coding Plan 就忍不住想看到每次消耗了多少 Token,每次想知道用量,都得打开浏览器,登录智谱的控制台,然后刷新,像是一个看着太阳不断落山的小丑。
所以我就想着把 GLM 的用量能不能直接搬到终端里——就在 Claude Code 的状态栏上,一眼就能看到。
先装 claude-hud
claude-hud 是 Claude Code 的一个状态栏插件,能在终端底部实时显示上下文使用量、Git 状态、工具活动等信息。它是整个方案的基础——提供了 statusline 的渲染框架,我只需要往里面塞 GLM 的数据就行。
安装很简单,在 Claude Code 里依次执行:
/plugin marketplace add jarrodwatts/claude-hud
/plugin install claude-hud
/claude-hud:setup
装完重启 Claude Code,底部就会出现状态栏。这时候显示的还是 Claude 原生的信息:上下文进度条、模型名称、Git 分支之类的。
核心思路
claude-hud 的 statusline 本质上是一个脚本:Claude Code 每隔约 300ms 把会话数据通过 stdin 传给脚本,脚本处理后输出到 stdout,Claude Code 再渲染到终端底部。
所以我写了一个 wrapper 脚本,它做了三件事:
- 调 GLM 的 API 拿配额数据——Token 使用百分比、重置时间、MCP 调用限制
- 把 GLM 数据塞进 claude-hud 的输出里——橙色高亮,一眼就能看到
- 加了 Skills 计数和 Agent 计数——知道当前加载了多少技能、有几个后台 Agent 在跑
为了让 API 不被频繁调用(毕竟每 300ms 就触发一次脚本),我加了 5 分钟的文件缓存。只有缓存过期了才重新请求,否则直接读本地文件。这样既实时又不浪费请求。
配置步骤
第一步:创建 wrapper 脚本
把下面的脚本保存到 ~/.claude/statusline-wrapper.sh,然后加上执行权限:
chmod +x ~/.claude/statusline-wrapper.sh
脚本内容比较长,贴在文章最后了。核心逻辑就是:调 GLM 配额 API → 缓存结果 → 合并 claude-hud 输出 → 最终显示。获取用量的 API 完全使用的都是官网服务(可自己查看源码),和在官网直接访问查看没有任何差异。
第二步:修改 Claude Code 配置
编辑 ~/.claude/settings.json(或 settings.local.json),把 statusline 指向 wrapper 脚本:
{
"statusline": {
"enabled": true,
"script": "~/.claude/statusline-wrapper.sh"
}
}
如果之前已经有 statusline 配置,把 script 字段改成 wrapper 的路径就行。
第三步:替换你自己的 API Key
脚本里有一行是 GLM 的 API Key:
_glm_key="你的API Key"
去 智谱开放平台 的 API Keys 页面拿到你自己的 Key 替换进去。
第四步:重启 Claude Code
退出当前会话,重新启动,底部状态栏就会出现 GLM 的用量信息了。
最终效果
状态栏上你会看到类似这样的信息:
GLM | Token: 62% 15:30 100% 2026/04/03 00:00 | MCP: 45% | 1 CLAUDE.md | 10 MCPs | 42 Skills
逐项解释一下:
- Token: 62% 15:30 — 第一个 Token 限额已用 62%,15:30 重置
- 100% 2026/04/03 00:00 — 第二个 Token 限额还没用,明天凌晨重置
- MCP: 45% — MCP 调用限额用了 45%
- 1 CLAUDE.md | 10 MCPs — claude-hud 原生的配置计数
- 42 Skills — 当前加载的技能数量
橙色显示,在终端里非常醒目。
缓解 Token 焦虑
用了几天下来,最大的感受就是:确定性消除焦虑。
以前每次长时间使用 Claude Code,心里总有个声音:“还够不够用?” 现在瞟一眼状态栏就知道了。62% 的时候安心干活,85% 的时候开始收尾,95% 的时候赶紧保存上下文。从容多了。
而且缓存机制让这个功能几乎零成本——5 分钟更新一次,不会拖慢终端,不会浪费 API 调用。
完整脚本
以下是 ~/.claude/statusline-wrapper.sh 的完整代码,可直接使用,因为系统差异不能直接使用的,可以让 Claude Code 略微修改下即可
#!/bin/bash
# Status line wrapper: first line GLM quota, second line cloud script, remaining lines from claude-hud
input=$(cat)
# GLM API Key quota (cached 5min, output as first line)
_glm_cache="/tmp/glm_quota_cache.txt"
_glm_ttl=300
_glm_key="你的API Key"
if [ -f "$_glm_cache" ] && [ $(( $(date +%s) - $(stat -f %m "$_glm_cache") )) -lt $_glm_ttl ]; then
glm_output=$(cat "$_glm_cache")
else
glm_output=$(curl -sf --max-time 5 "https://bigmodel.cn/api/monitor/usage/quota/limit" \
-H "Authorization: Bearer $_glm_key" -H "Content-Type: application/json" 2>/dev/null \
| python3 -c "
import sys,json
from datetime import datetime
try:
d=json.load(sys.stdin).get('data',{}).get('limits',[])
tks=[x for x in d if x.get('type')=='TOKENS_LIMIT']
tm=' '.join([f'{x[\"percentage\"]}%' for x in d if x.get('type')=='TIME_LIMIT'])
parts=[]
if tks:
items=[]
for i,x in enumerate(tks):
pct=f'{x[\"percentage\"]}%'
t=datetime.fromtimestamp(x['nextResetTime']/1000)
if i==0:
items.append(pct+' '+t.strftime('%H:%M'))
else:
items.append(pct+' '+t.strftime('%Y/%m/%d %H:%M'))
parts.append('Token:'+' '.join(items))
if tm: parts.append('MCP:'+tm)
print('\033[38;5;208mGLM | '+' | '.join(parts)+'\033[0m')
except: pass
" 2>/dev/null)
[ -n "$glm_output" ] && echo "$glm_output" > "$_glm_cache"
fi
# Cloud script output (second line)
cloud_output=$(echo "$input" | /Users/apple/Downloads/statusline-cloud.sh 2>/dev/null)
# Claude-hud output (all lines)
plugin_dir=$(ls -d "$HOME"/.claude/plugins/cache/claude-hud/claude-hud/*/ 2>/dev/null | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n | tail -1)
hud_output=$(echo "$input" | /usr/local/Cellar/node/25.2.1/bin/node "${plugin_dir}dist/index.js" 2>/dev/null)
# Extract HUD line 3 (e.g. "1 CLAUDE.md | 10 MCPs") and rest (line 4+)
# Strip leading/trailing ANSI codes and whitespace from hud_line3
hud_line3=$(echo "$hud_output" | sed -n '3p' | sed 's/^\(\x1b\[[0-9;]*m\)*//;s/\(\x1b\[[0-9;]*m\)*$//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
hud_rest=$(echo "$hud_output" | tail -n +4)
# Count available skills (cached per session, deduplicated across all sources)
_skill_cache="/tmp/skill_count_cache.txt"
if [ -f "$_skill_cache" ]; then
_skill_count=$(cat "$_skill_cache")
else
_skill_count=$({
ls "$HOME/.claude/skills/" 2>/dev/null | grep -v '^\.'
find "$HOME/.claude/plugins" -name "SKILL.md" 2>/dev/null | sed 's|/SKILL.md||' | xargs -I{} basename {}
find "$HOME/.claude/plugins" -name "*.md" -path "*/commands/*" 2>/dev/null | xargs -I{} basename {} .md
ls "$HOME/.claude/commands/" 2>/dev/null | sed 's|\.md$||'
} | sort -u | wc -l | tr -d '[:space:]')
echo "$_skill_count" > "$_skill_cache"
fi
skill_str="\033[0;35m${_skill_count} Skills\033[0m"
# Count waiting agents (other claude processes, real-time)
_agent_count=$(( $(pgrep -x claude | wc -l) - 1 ))
if [ "$_agent_count" -gt 0 ]; then
agent_str="\033[0;34m${_agent_count} Agents\033[0m"
else
agent_str=""
fi
# Output: cloud → GLM+HUD_line3+Skills (merged one line) → HUD rest, filter blank lines
{
if [ -n "$cloud_output" ]; then
echo "$cloud_output"
fi
# Merge GLM (orange), HUD line 3, skill count, and agent count into one line
_extra="${skill_str}"
[ -n "$agent_str" ] && _extra="${_extra} ${agent_str}"
if [ -n "$glm_output" ] && [ -n "$hud_line3" ]; then
echo -e "${glm_output} ${hud_line3} ${_extra}"
elif [ -n "$glm_output" ]; then
echo -e "${glm_output} ${_extra}"
elif [ -n "$hud_line3" ]; then
echo -e "${hud_line3} ${_extra}"
else
echo -e "${_extra}"
fi
if [ -n "$hud_rest" ]; then
echo "$hud_rest"
fi
} | perl -ne 'my $c=$_; $c=~s/\e\[[\d;]*m//g; print unless $c=~/^\s*$/'
不确定性才是焦虑的根源。把数字放在眼前,焦虑就消散了大半。