ClaudeCodeRGB:用ESP32给Claude Code做个物理状态灯
灿若繁星先生 Lv6

作为一个 Claude Code 重度用户,我经常遇到一个问题:Claude Code 在后台跑着,我切去做别的事,回来一看不知道它跑完了没有。 于是我做了一个小玩意——用 ESP32 开发板 + RGB 灯,做一个物理状态指示灯。绿灯亮着说明空闲,蓝灯闪烁说明正在思考,黄灯闪烁说明在等你确认……一眼就知道该不该切回终端了。

项目已开源:GitHub - canyuda/ClaudeCodeRGB

背景

Claude Code 是 Anthropic 推出的 CLI 编程助手,通过终端交互。在日常使用中有几个痛点:

  1. 状态不直观 — 需要切回终端才能看到 Claude 是在思考、等权限、还是已经完成
  2. 多任务场景 — 同时开着多个 Claude Code 会话时,无法快速定位哪个需要关注
  3. 等待焦虑 — 不知道任务跑到哪了,频繁切窗口打断工作流

解决方案很朴素:做一个物理灯,不同颜色代表不同状态,放在桌面上随时可见。

整体架构

系统的数据流非常简单:

1
Claude Code Hooks → Python 脚本 (串口通信) → ESP32-C3 → RGB LED

分三层:

  1. Arduino 固件claude_rgb.ino)— 运行在 ESP32-C3 上,监听串口的 STATE:xxx 命令,控制 RGB 灯的颜色和闪烁模式
  2. Python Hook 脚本claude_rgb_hook.py)— 注册为 Claude Code 的 Hook,接收状态事件,映射为灯效指令,写入串口
  3. 一键部署脚本 — 自动完成 Hook 注册、串口配置、Claude Code settings 合并

LED 状态映射

这是整个项目的核心设计——Claude Code 的每个状态对应一种灯效:

Hook 事件 状态 灯效
SessionStart / SessionEnd idle(空闲) 🟢 绿灯常亮
UserPromptSubmit running(思考中) 🔵 蓝灯慢闪(500ms)
PreToolUse tool(调用工具) 🟣 紫灯快闪(150ms)
PermissionRequest / Notification ask(等待确认) 🟡 黄灯快闪(250ms)
PostToolUseFailure error(执行出错) 🔴 红灯快闪(100ms)
Stop done(完成) 🟢 绿灯常亮

一个典型的 Claude Code 工作流中,灯光会这样变化:

1
2
3
4
5
6
7
8
9
10
11
12
13
空闲 → 绿灯
↓ 你提交 prompt
思考中 → 蓝灯慢闪
↓ Claude 调用工具(读文件、执行命令等)
工具调用 → 紫灯快闪
↓ 回到思考
思考中 → 蓝灯慢闪
↓ 需要你确认权限
等待确认 → 黄灯快闪
↓ 你批准后继续
思考中 → 蓝灯慢闪
↓ 任务完成
完成 → 绿灯

硬件准备

整个项目的硬件成本不到 25 块钱:

硬件 价格 说明
ESP32-C3 SuperMini 模块 ~10 元 核心开发板,Type-C 接口
共阴极 RGB LED 模块(带 4P 杜邦线) ~12 元 电子积木,即插即用
Type-C 数据线 ~2 元 供电 + 串口通信

接线方式:

1
2
3
4
5
ESP32-C3       RGB 模块
GPIO2 → R(红色)
GPIO3 → G(绿色)
GPIO4 → B(蓝色)
GND → GND(共阴极接地)

总共 4 根线,不需要焊锡,杜邦线直插即可。

固件开发

固件用 Arduino IDE 开发,核心逻辑很清晰。ESP32-C3 通过串口(波特率 115200)接收命令字符串,然后控制对应 GPIO 的电平来切换灯效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 核心状态枚举
enum LedState {
STATE_IDLE, // 空闲 - 绿灯常亮
STATE_DONE, // 完成 - 绿灯常亮
STATE_RUNNING, // 思考中 - 蓝灯慢闪
STATE_TOOL, // 工具调用 - 紫灯快闪
STATE_ASK, // 等待确认 - 黄灯快闪
STATE_ERROR // 出错 - 红灯快闪
};

// 串口命令处理
void handleCommand(String cmd) {
cmd.trim();
cmd.toLowerCase();

if (cmd.startsWith("state:")) {
cmd = cmd.substring(6);
// ... 映射到对应状态
}
}

// 主循环
void loop() {
readSerialCommands(); // 读取串口命令
updateLedEffect(); // 更新灯效(闪烁逻辑)
}

几个细节:

  • 共阴极逻辑:HIGH = 灯亮,LOW = 灯灭
  • 闪烁实现:用 millis() 做非阻塞定时,不同状态有不同闪烁频率
  • 上电自检:启动时红、绿、蓝各闪一次,方便确认硬件正常
  • 串口协议:支持 STATE:xxx 设置状态、PING 心跳检测、HELP 查看帮助

Python Hook 脚本

Python 脚本是 Claude Code 和硬件之间的桥梁。它注册为 Claude Code 的 Hook,在特定事件触发时被调用。

1
2
3
4
5
6
7
8
9
# 事件到灯效的映射
VALID_STATES = {
"idle", # SessionStart / SessionEnd
"done", # Stop
"running", # UserPromptSubmit
"tool", # PreToolUse
"ask", # PermissionRequest
"error", # PostToolUseFailure
}

零依赖设计是这个脚本的亮点——没有 pip install 任何东西:

  • macOS / Linux:用标准库 termios 做串口通信
  • Windows:用 ctypes 调用 kernel32.dll 做串口通信

这意味着不管你在什么平台,只要系统里有 Python 3.8+ 就能直接跑,不用装任何第三方库。

一键部署

项目提供了一键部署脚本,支持 macOS / Linux / Windows 三平台:

1
2
3
4
5
# macOS / Linux — 部署到当前项目
curl -fsSL https://raw.githubusercontent.com/canyuda/ClaudeCodeRGB/main/install.sh | bash

# 部署到用户级(所有项目生效)
curl -fsSL https://raw.githubusercontent.com/canyuda/ClaudeCodeRGB/main/install.sh | bash -s -- --user
1
2
# Windows (PowerShell) — 部署到当前项目
iwr -useb https://raw.githubusercontent.com/canyuda/ClaudeCodeRGB/main/install.ps1 | iex

脚本执行流程:

  1. 系统检测 — 检查操作系统和 Python 环境
  2. 下载 Hook 脚本 — 从 GitHub 拉取 claude_rgb_hook.py
  3. 配置串口 — 自动扫描可用串口,交互式设置
  4. 合并配置 — 将 Hooks 配置写入 settings 文件,不影响已有配置

两种部署模式的区别:

项目级 用户级
配置文件 .claude/settings.local.json ~/.claude/settings.json
生效范围 当前项目 所有项目
是否进 git 不提交

WiFi 无线版本

除了有线版本,项目还提供了一个基于 WiFi 的无线方案。使用充电宝供电,RGB 灯不再需要 USB 连接电脑,可以放在桌面任何位置。

无线版通过 HTTP API 替代串口通信,ESP32-C3 连接 WiFi 后监听 HTTP 请求来切换灯效。

效果展示

最终效果如下:

  • 绿灯常亮 — Claude Code 空闲或任务完成
  • 蓝灯慢闪 — Claude 正在思考,处理你的 prompt
  • 紫灯快闪 — Claude 正在调用工具(读文件、执行命令等)
  • 黄灯快闪 — Claude 在等你确认权限
  • 红灯快闪 — 出错了,需要你关注

未来展望

目前 ClaudeCodeRGB 以 ESP32-C3 SuperMini 为核心,提供了有线串口和 WiFi 无线两种方案。接下来计划适配更多开发板,覆盖不同的使用场景和预算。

蓝牙无线版 — Seeed XIAO nRF52840

nRF52840 方案已经完成了开发,核心思路是用 BLE(蓝牙低功耗)替代串口通信,实现真正的无线状态灯:

  • 无需外接 RGB 模块 — 开发板内置 3-in-1 RGB LED,硬件成本和接线复杂度进一步降低
  • BLE 守护进程架构 — BLE 连接建立需要 1-3 秒,而 Claude Code hook 超时只有 2 秒,所以引入了一个后台守护进程维持 BLE 长连接,hook 脚本通过 HTTP 调用守护进程(~5ms),避免超时
  • macOS 开机自启 — 通过 launchd 注册守护进程,开机即连接,无需手动操作

架构示意:

1
Claude Code Hooks → Hook 脚本 (HTTP ~5ms) → BLE 守护进程 (长连接) → nRF52840 内置 RGB

这个方案非常适合不想拉线的用户——开发板用充电宝供电,放在桌面任意位置,通过蓝牙无线控制。

屏幕显示版 — M5StickC Plus

M5StickC Plus 是一个很有想象力的方向。它基于 ESP32-PICO,自带 1.14 英寸 IPS 彩屏、120mAh 电池、IMU 传感器、蜂鸣器,集成了 WiFi + BLE,相当于一个火柴盒大小的微型终端。

规划中的功能:

  • 屏幕显示状态信息 — 不仅亮灯,还能在屏幕上展示当前状态文本、正在执行的工具名称、耗时等
  • 内置电池 — 120mAh 虽然不大,但作为状态灯足够支撑数小时,配合充电宝可实现全天候无线
  • 蜂鸣器提醒 — error 或 ask 状态时蜂鸣提醒,适合不看灯的场景
  • 按键交互 — 可以通过按键切换显示模式(纯灯效 / 灯效+文字 / 详细信息)

极简有线版 — Pro Micro ATmega32U4

Pro Micro 基于 ATmega32U4,没有 WiFi 和蓝牙,资源也非常有限(32KB Flash、2.5KB SRAM)。但正因为简单,它适合作为最廉价的有线方案:

  • 成本极低 — 开发板本身十几块钱,加上 RGB 模块总成本不到 20 元
  • 纯串口通信 — ATmega32U4 内置 USB 收发器,无需额外 USB 转串口芯片,直接 USB 连电脑
  • 适用场景 — 不需要无线、不需要屏幕,只要一个最简单的桌面状态灯

方案对比

ESP32-C3 SuperMini nRF52840 (BLE) M5StickC Plus Pro Micro
连接方式 USB 串口 / WiFi 蓝牙 BLE WiFi / BLE USB 串口
无线 ✅ WiFi ✅ BLE ✅ WiFi + BLE
屏幕 ✅ 1.14" IPS
内置电池 ✅ 120mAh
开发进度 ✅ 已完成 ✅ 已完成 🚧 规划中 🚧 规划中
硬件成本 ~25 元 ~60 元 ~70 元 ~20 元

总结

ClaudeCodeRGB 是一个小而美的开源硬件项目,核心思路:

  • 利用 Claude Code 的 Hooks 机制,将运行状态暴露为物理信号
  • ESP32-C3 + RGB 模块,低成本(<25 元)、零焊接、即插即用
  • Python 标准库实现串口通信,跨平台且零依赖
  • 一键部署脚本,从克隆到运行只需一条命令

如果你也是 Claude Code 用户,不妨试试这个项目。欢迎在 GitHub 上提 Issue 和 PR!