为什么你的 Claude 桌宠会睡觉?claude-desktop-buddy 七大状态机深度解析
【免费下载链接】claude-desktop-buddyReference and an example for the Bluetooth API for makers in Claude Cowork & Claude Code Desktop项目地址: https://gitcode.com/gh_mirrors/cl/claude-desktop-buddy
claude-desktop-buddy 是官方的Claude 桌宠(桌面伴侣)硬件参考项目:一只跑在 ESP32 上的电子宠物,通过 BLE 蓝牙连接 Claude 桌面端,实时"感知"你的会话状态。它会睡觉、会流汗、会因为你手抖而晕头转向——这一切背后,是一套干净利落的七大状态机。这篇文章用大白话带你一次看懂这 7 种状态的触发条件、优先级关系和源码位置,新手也能轻松上手。
🐾 先认识一下:Claude 桌宠长什么样
这是一只"住"在 M5StickC Plus 里的电子宠物(固件面向 ESP32 + Arduino 框架)。它通过 BLE 连接 Claude 桌面端,屏幕上用 18 种 ASCII 小宠(或你自定义的 GIF 角色)实时反映 Claude 的工作状态——会话在跑它就流汗干活,有权限请求待审批它就警觉地亮 LED,闲下来就闭眼睡觉。
它的全部"性格",都由 7 个状态驱动。源码中就是一个简洁的枚举定义:src/main.cpp。
📋 七大状态一览表
| 状态 | 触发条件 | 动画表现 | 持续时间 | 类型 |
|---|---|---|---|---|
sleep睡眠 | 桥接未连接(30 秒内没收到数据) | 闭眼、缓慢呼吸 | 直到重新连接 | 常驻态 |
idle待机 | 已连接,且无紧急事项 | 眨眼、东张西望 | 持续 | 常驻态 |
busy忙碌 | 同时有3 个及以上会话在跑 | 冒汗、埋头干活 | 持续 | 常驻态 |
attention警觉 | 有待审批的权限请求 | 警觉、LED 闪烁 | 持续 | 常驻态 |
celebrate庆祝 | 等级提升(每 5 万 token 升一级) | 彩带、蹦跳 | 3 秒 | 一次性 |
dizzy眩晕 | 摇晃设备(IMU 检测到剧烈震动) | 螺旋眼、摇晃 | 2 秒 | 一次性 |
heart心动 | 5 秒内完成审批 | 漂浮爱心 | 2 秒 | 一次性 |
💡 为什么"会睡觉"?答案很简单:它睡不睡,取决于它"听不听得见" Claude。
😴 核心谜题:它是怎么决定"睡觉"的?
状态机的"大脑"是一个只有 5 层的优先级判断函数derive(),位于 src/main.cpp:
PersonaState derive(const TamaState& s) { if (!s.connected) return P_SLEEP; // 没连接 → 睡 if (s.sessionsWaiting > 0) return P_ATTENTION; // 有审批 → 警觉 if (s.recentlyCompleted) return P_CELEBRATE; // 刚完成 → 庆祝 if (s.sessionsRunning >= 3) return P_BUSY; // ≥3 会话 → 忙碌 return P_IDLE; // 其余情况 → 待机 }注意第一条:只要没连接,就睡眠。而"连接"的判定藏在数据层 src/data.h 中——只要最近30 秒内收到过来自桌面的实时 JSON 数据,connected就为真;一旦断连,会话计数会被全部清零并显示 "No Claude connected",桌宠随之闭眼。所以:
- 桌面端在跑、数据在流 → 它醒着(idle / busy / attention)
- 桌面端关闭、蓝牙断开、或电脑休眠 → 30 秒后它就安静入睡了
这正是你"为什么你的 Claude 桌宠会睡觉"的完整答案:睡眠不是一个开关,而是"数据断流"的自然结果。
数据侧的完整状态结构(会话数、token、审批提示等字段)定义在 src/data.h 的TamaState中,数据层还内置了 demo / live / asleep 三种模式,方便你脱离真实会话调试。
⚡ 常驻态之上:三个"一次性"状态如何覆盖
上面 5 个常驻态之外,还有 3 个一次性(one-shot)状态,它们不依赖 Claude 的数据,而由设备端事件触发。核心机制是一个带倒计时的覆盖函数triggerOneShot()(src/main.cpp):先强制切入某个状态并记下截止时间,时间一到自动落回基础状态。
- 🎉celebrate:token 累计每满5 万升一级(阈值见 src/stats.h 的
TOKENS_PER_LEVEL),主循环检测到升级就播放 3 秒彩带 - 💫dizzy:加速度传感器检测到剧烈震动(摇晃设备),播放 2 秒螺旋眼
- 💗heart:审批提示弹出后5 秒内你按了确认键,播放 2 秒爱心——审批越快,它越"心动"
这套"基础状态 + 一次性覆盖"的双层设计非常值得借鉴:紧急事件(如审批)随时可以插队,但不会把主状态搅乱。另外还有一个贴心的细节——刚亮屏后会强制保持 12 秒睡眠动画(src/main.cpp),让你完整看到"醒来"的过程;而attention状态下 LED 每 400ms 闪烁一次,提醒你不要漏掉待审批请求。
🌙 隐藏彩蛋:桌宠还懂"昼夜节律"
当设备处于时钟模式(USB 连接、无会话、RTC 时间有效)时,桌宠会按真实时间"作息"(src/main.cpp):凌晨 1–7 点深睡、深夜 22 点后昏昏欲睡、周五下午开始蹦迪庆祝、周末则半睡半醒地冒爱心……细节控狂喜。
🔗 如何把桌宠连上 Claude(配对步骤)
- 开启开发者模式:Help → Troubleshooting → Enable Developer Mode
- 打开配对窗口:Developer → Open Hardware Buddy…
- 点击 Connect,从列表中选择你的设备;macOS 首次连接会请求蓝牙权限,允许即可
配对成功后,桥接会在双方都"醒着"时自动重连。找不到设备时,先按一下任意按钮唤醒,并确认设备设置里蓝牙已开启。
🎨 进阶玩法:给它换上你的 GIF 角色
不想用 ASCII 宠物?把角色包文件夹(manifest.json+ 96px 宽的 GIF,每个状态可配多张轮换动画)拖进 Hardware Buddy 窗口,设备会通过 BLE实时切换到 GIF 模式。仓库自带完整示例 characters/bufo/,其 manifest.json 正好对应了七大状态名。配套工具帮你搞定素材:
- tools/prep_character.py:任意尺寸 GIF 批量缩放到统一比例
- tools/flash_character.py:跳过 BLE 回传,直接 USB 刷机调试
📚 想继续深挖?源码导读
| 模块 | 路径 | 职责 |
|---|---|---|
| 状态机与 UI 主循环 | src/main.cpp | loop、derive()、triggerOneShot() |
| 线协议与 JSON 解析 | src/data.h | TamaState、三种数据模式 |
| 统计与设置(NVS 持久化) | src/stats.h | 升级、审批速度、作息记录 |
| 18 种 ASCII 宠物 | src/buddies/ | 每种 7 个动画函数 |
| BLE 服务(Nordic UART) | src/ble_bridge.cpp | 行缓冲收发 |
| GIF 解码与渲染 | src/character.cpp | 角色包模式 |
| 完整协议文档 | REFERENCE.md | UUID、JSON Schema、文件夹推送 |
小结:claude-desktop-buddy 用 7 个状态、两层覆盖,就让一只 ESP32 桌宠拥有了"睡醒—干活—警觉—庆祝"的完整人格。理解了这套状态机,你甚至可以为自己的硬件设计一套同款"情绪系统"。祝你的桌宠常伴左右,记得 5 秒内批完——它会在意你的速度。💗
【免费下载链接】claude-desktop-buddyReference and an example for the Bluetooth API for makers in Claude Cowork & Claude Code Desktop项目地址: https://gitcode.com/gh_mirrors/cl/claude-desktop-buddy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考