Skip to content

Repository files navigation

cchud

Claude Code 状态栏小兽 —— 一只会随状态切换姿势的像素小兽,外加上下文 / 用量 / 模型 / 花费一目了然。

cchud 是给 Claude Code 用的 statusLine 脚本。它从 stdin 读取 Claude Code 传入的会话 JSON,输出三行带颜色的终端状态栏。

效果

cchud 状态栏预览

上图为同一脚本在六种状态下的实际输出:思考中 / 跑命令 / 翻找文件 / 联网搜索 / 敲键盘(橙色,小兽站立,头顶 badge 区分在干什么)与等你输入(绿色,小兽蜷缩低头打盹)。

显示内容:

  • 小兽姿势 + 颜色 + 头顶 badge —— 当前在干什么:思考 ? / 跑命令 >_ / 翻找 / 搜索 @ / 敲键盘 I / 等你 zᶻ,注册实时状态源后还有黄色的等确认 !。默认读会话日志的最后一个有意义事件推断(比看文件 mtime 更准,详见状态推断的原理与限制);注册实时状态源后改由 hooks 即时驱动。
  • ctx —— 上下文窗口占用百分比。
  • 5h / 7d —— 5 小时 / 7 天用量额度,带重置倒计时()。
  • 进度条颜色 —— 绿(<60%) / 黄(60-85%) / 红(≥85%)。
  • 尾行 —— 待办完成数(✓3/5)、模型名、本次花费、累计时长。待办兼容两套机制:新版 Task 系统TaskCreate/TaskUpdate 事件流,正序重放重建任务与状态)优先,没有再回落老版 TodoWrite 快照。此外若有「比主日志更新的活动子代理日志」(<主会话id>/subagents/agent-*.jsonl),优先取它的待办,否则用主会话自己的。

安装

需要本机有 Node.js(任意较新版本即可,脚本无依赖)。

把仓库克隆到任意位置:

git clone https://github.com/x-wink/cchud.git

然后编辑 ~/.claude/settings.json,加入 statusLine 字段。

macOS / Linux

{
  "statusLine": {
    "type": "command",
    "command": "/path/to/cchud/hud.sh",
    "refreshInterval": 2
  }
}

记得给启动器加可执行权限:chmod +x /path/to/cchud/hud.sh

Windows

直接用 node 调用 hud.js(注意 JSON 里反斜杠要转义):

{
  "statusLine": {
    "type": "command",
    "command": "node \"C:\\path\\to\\cchud\\hud.js\"",
    "refreshInterval": 2
  }
}

保存后重启 Claude Code(或新开会话)即可生效。

提醒(可选)

notify.js 可在 Claude Code 需要你时弹桌面通知 + 播提示音,方便你挂着别的事时被叫回来。它借助 Claude Code 的两类钩子,并用不同提示音区分场景,凭声音即可分辨:

钩子 触发时机 提示音(Windows)
Stop 答完、把控制权交还给你 完成铃声 Ring01.wav
Notification 需要你授权 / 等待你输入 前台提示音 Windows Foreground.wav

Notification 事件的具体事由(如「需要授权使用 Bash」)由 Claude Code 通过 stdin 的 message 给出,直接作通知正文。

跨平台:Windows 用 PowerShell WinRT Toast + 系统提示音,macOS 用 osascript,Linux 用 notify-send + paplay

settings.json 里和 statusLine 同级加入 hooks(两类指向同一个脚本,脚本内部按事件类型自动区分):

{
  "hooks": {
    "Stop": [
      { "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\notify.js\"" }] }
    ],
    "Notification": [
      { "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\notify.js\"" }] }
    ]
  }
}

通知里会带上当前项目目录名,多个会话同时跑时一眼能认出是哪个项目在叫你。Windows 上若通知没弹出,检查「设置 → 系统 → 通知」与「专注助手 / 勿扰模式」是否屏蔽了通知(提示音不受勿扰影响,仍会响)。

实时状态源(hooks,可选)

默认的状态推断靠扫会话日志,受「落盘时机」限制——比如思考内容要整块结束才写入,思考期间状态栏拿不到任何新信息。state.js 提供另一条实时链路:注册为一组 Claude Code 钩子后,Claude Code 会在事件发生的瞬间同步调用它,它把「此刻在干嘛」写进 ~/.cchud/state/<会话id>.jsonhud.js 发现该文件后即优先采用(日志推断退为兜底)。收益:

  • 按下回车立刻进入「思考中」——不用等任何内容落盘;
  • 工具执行前就切好姿态——PreToolUse 带确切工具名,长命令全程姿态正确;
  • 新增黄色「等确认 !」状态——等你授权 / 等你输入时整只小兽变黄提醒你,这是日志推断给不了的。

settings.jsonhooks 里把下列事件都指向 state.jsStop / Notification 与 notify.js 并存,同一事件的 hooks 数组可以放多个命令)。全部加 "async": true:钩子在后台跑、完全不阻塞 Claude Code 主流程——代价是极小概率相邻事件写入乱序、状态短暂偏差,下个事件自然纠正,对状态展示这种「尽力而为」的用途是正确取舍:

{
  "hooks": {
    "UserPromptSubmit": [{ "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }] }],
    "PreToolUse":       [{ "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }] }],
    "PostToolUse":      [{ "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }] }],
    "SessionStart":     [{ "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }] }],
    "SessionEnd":       [{ "hooks": [{ "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }] }],
    "Stop": [
      { "hooks": [
        { "type": "command", "command": "node \"C:\\path\\to\\cchud\\notify.js\"" },
        { "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }
      ] }
    ],
    "Notification": [
      { "hooks": [
        { "type": "command", "command": "node \"C:\\path\\to\\cchud\\notify.js\"" },
        { "type": "command", "command": "node \"C:\\path\\to\\cchud\\state.js\"", "async": true }
      ] }
    ]
  }
}

细节与兜底(实现见 state.js / hud.jsresolveState):

  • 用户中断 / 秒取消不触发任何钩子,hook 状态会停在忙态。hud.js 用日志里的中断标记(比 hook 事件新即回休息)和 60 秒悬挂超时兜底,行为与纯日志推断一致。
  • 状态文件比日志旧超过 10 分钟视为钩子失联(如中途卸载),自动退回日志推断;超过 24 小时的陈旧状态文件会被顺手清理。
  • 状态目录可用 stateDir 配置(CCHUD_STATE_DIR / 配置文件同名字段)。

自定义称呼与文案

小兽的称呼、状态栏两种状态文本、通知标题/正文都可自定义。称呼默认为 小螃蟹。解析优先级:CLI 参数 > 环境变量 > 配置文件 > 默认值

字段 默认值 用途
name 小螃蟹 称呼,用于通知标题里的 {name}
busyLabel 吭哧吭哧 … 状态栏「忙碌」文本
idleLabel zᶻ ✓ 等你 状态栏「等你」文本
waitLabel 等确认 … 状态栏「等授权/等输入」文本(需注册实时状态源
doneTitle {name} · 等你了 通知标题(答完)
doneBody 答完了,回来看看 ✓ 通知正文(答完)
needTitle {name} · 需要你 通知标题(需要授权/等待输入)
needBody 需要你处理一下 通知正文兜底(Claude 未给 message 时)

配置文件(推荐,一次配置两个脚本共用):把 cchud.config.example.json 复制为 cchud.config.json(脚本同目录)或 ~/.cchud.json,按需修改。也可用 --config <path> 或环境变量 CCHUD_CONFIG 指定路径。

命令行参数(写进 settings.json 的 command 里):

"command": "node \"C:\\path\\to\\cchud\\hud.js\" --name 大龙虾 --idle-label \"钳子等你~\""

环境变量CCHUD_NAMECCHUD_BUSY_LABELCCHUD_IDLE_LABEL 等(字段名大写下划线)。

状态推断的原理与限制

未注册实时状态源时,小兽的姿态通过读取会话日志(transcript)的最后一个有意义事件推断——而非看文件 mtime:

  • assistant 调 Bash → 跑命令 >_;调 Read/Grep/Glob 等 → 翻找中 ;调 WebSearch/WebFetch → 搜索中 @;调 Edit/Write 等 → 敲键盘 I;仅思考或调其他工具 → 思考中 ?;给出完整文字回复 → 休息中 zᶻ
  • 工具结果(tool_result)会被跳过、回溯到对应的工具调用判断姿态;中断标记 [Request interrupted by user…] 会被识别为「休息中」。
  • 同一轮里「开场白文字」与随后的工具调用是分开落盘的两条记录:只有 stop_reason 为收尾(end_turn)的文字才算「答完 → 休息中」;若仍是 tool_use(或记录尚未写完),说明后面还要继续调工具,判为忙——避免长任务里开场白先落盘、工具调用还没落盘时误判成休息

建议开启定期刷新(refreshInterval

Claude Code 的状态栏默认只在「有新助手消息」时刷新——你提交消息这个动作本身不触发刷新。所以不加配置时,从你发消息到 Claude 开始响应的这段时间,状态栏会冻结在上一帧(看起来像「装睡」)。在 statusLine 里加上 refreshInterval(单位秒,最小 1)让它定期重绘即可解决(安装示例里已包含)。

已知限制(受 Claude Code 机制约束,非脚本能完全消除)

  1. 短操作的姿态只会一闪而过:assistant 消息要整条生成完才落盘,读一个文件、跑一条快命令这类毫秒级动作,对应姿态往往来不及显示。只有长任务(耗时命令、大范围检索)才会稳定停在对应姿态。
  2. 「正在等待响应」与「提交后秒取消」无法即时区分:Claude Code 取消时既不触发任何 hook,也不在日志留下可识别痕迹,两者的日志状态完全一致。为避免秒取消后永久卡在「思考中」,脚本采用兜底——一条用户输入悬挂超过 60 秒仍无任何响应跟进,即判定为已取消 / 久挂并回到「休息中」(claude --resume 回来也借此自愈)。代价是秒取消后需等这段时间才回休息;阈值在 hud.jsIDLE_AFTER_MS 可调。

调试

不接 Claude Code 时,可手动喂一段假 JSON 预览效果:

echo '{"context_window":{"used_percentage":42},"rate_limits":{"five_hour":{"used_percentage":63}},"model":{"display_name":"Opus 4.8"},"cost":{"total_cost_usd":1.23}}' | HUD_FAKE_STATE=busy node hud.js

环境变量 HUD_FAKE_STATE=busy|idle|bash|read|web|edit|wait 可强制小兽进入指定状态,方便调试。

模拟钩子事件验证实时状态源(CCHUD_STATE_DIR 可把状态文件指到临时目录):

echo '{"hook_event_name":"PreToolUse","session_id":"test","tool_name":"Bash"}' | node state.js
cat ~/.cchud/state/test.json   # {"state":"bash","event":"PreToolUse","tool":"Bash","ts":…}

生成预览页面(README 顶部的 preview.png 即截自此页面的终端元素):

node tools/preview.js   # 输出 tools/preview.html,用浏览器打开即可预览两种状态

终端建议

状态栏用到真彩色 ANSI(38;2;r;g;b)和 Unicode 方块字符。在 Windows Terminal、VS Code 集成终端、iTerm2 等现代终端显示最佳;老式 conhost(cmd.exe 默认窗口)可能配色或对齐不理想。

License

MIT

About

Claude Code 状态栏小兽:随状态切换姿势,显示上下文/用量/模型/花费

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages