尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

用 ESP32 给 Claude Code CLI 做个电子宠物:程序员的实体监工代码搭子

发布时间:2026/9/26 10:59:10

资讯中心
01
ARTICLE

用 ESP32 给 Claude Code CLI 做个电子宠物:程序员的实体监工代码搭子

用 ESP32 给 Claude Code CLI 做个电子宠物:程序员的实体监工代码搭子
1. 凌晨两点我盯着滚动的终端决定给 Claude Code 配个实体监工Claude Code CLI 是个好东西工具自动执行、Bash 命令一条接一条效率确实高。但问题也在这儿它跑起来之后终端就是个黑盒。你盯着飞速滚动的日志心里直打鼓——它现在是在忙还是卡住了高危操作的审批提示会不会被日志刷过去漏看我到底还要等多久这种失控感用过 Claude Code 的人应该都懂。尤其是让它跑长任务的时候你不可能一直盯着屏幕但离开又怕它偷偷改了配置文件或者某个需要审批的操作被忽略掉。所以我决定给它做个实体监工一块 ESP32 开发板通过 BLE 和 PC 上的守护进程通信把 Claude Code 的运行状态映射到桌面上的小屏幕。空闲时它闭眼打哈欠忙碌时皱眉干活等待审批时瞪大眼睛歪头等你点 YES任务完成跳个爱心舞。你不用再刷日志找进度瞟一眼小屏幕就知道 Claude 现在是在摸鱼还是在干活。这篇文章我会把整套方案拆开讲从 TaoToken 的 Key 配置到 Claude Code 的 settings.json 骨架再到 ESP32 端的 BLE 连接参数和 asyncio 状态轮询脚本。你可以跟着一步步搭起来也可以只挑其中一部分用到自己的项目里。2. 为什么用 TaoToken 统一 Key 和 API 通道在动手写代码之前先把接入层理清楚。Claude Code CLI 本身支持自定义 API 端点但如果你同时用多个模型或者多个工具每个都单独配 Key 和地址会很乱。TaoToken 在这里的作用就是统一入口一个 Key 走通所有请求API 地址固定不用在每个工具里重复填不同的配置。具体来说TaoToken 提供的是兼容 Anthropic 协议的 API 通道。你只需要在 Claude Code 的配置里把 base_url 指向https://taotoken.net/api然后把 API Key 填进去剩下的请求格式、鉴权方式都和原生一致。这样做的直接好处是你的 ESP32 守护进程、Claude Code CLI、以及后续可能加的其他工具都走同一个 Key 和同一个通道排查问题的时候不用来回切换配置。如果你还没有 Key可以去 TaoToken 控制台创建一个。创建完之后在 API Keys 页面能看到完整的 Key 字符串复制下来备用。注意这个 Key 只在创建时显示一次记得存好。注意TaoToken 的 API 地址是https://taotoken.net/api不要加多余的路径后缀。Claude Code 的配置里填这个地址就行。3. 可复制配置settings.json 与 config.toml 骨架Claude Code CLI 的配置分两部分一部分是 Claude Code 自己的 settings.json另一部分是守护进程用的 config.toml。先看 Claude Code 这边。3.1 Claude Code settings.json在项目根目录或者用户目录下创建.claude/settings.json内容如下{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-your-taotoken-key-here }, permissions: { allow: [ Bash, Write, Edit ] }, hooks: { PreToolUse: [ { matcher: Bash|Write|Edit, hooks: [ { type: command, command: python3 ~/claude-buddy/hook_bridge.py } ] } ] } }这里有几个关键点。ANTHROPIC_BASE_URL指向 TaoToken 的 API 地址ANTHROPIC_API_KEY填你刚才创建的 Key。hooks里的PreToolUse是 Claude Code 在执行工具之前触发的钩子我们用它把审批请求转发给 ESP32。hook_bridge.py是 PC 端的桥接脚本负责和守护进程通信。3.2 守护进程 config.toml守护进程跑在 PC 上负责 BLE 连接管理和状态轮询。配置文件config.toml如下[ble] device_name ClaudeBuddy service_uuid 6E400001-B5A3-F393-E0A9-E50E24DCCA9E tx_char_uuid 6E400002-B5A3-F393-E0A9-E50E24DCCA9E rx_char_uuid 6E400003-B5A3-F393-E0A9-E50E24DCCA9E mtu 20 reconnect_interval 5 [daemon] poll_interval 0.5 approval_timeout 30 log_level INFO [taotoken] base_url https://taotoken.net/api api_key sk-your-taotoken-key-hereBLE 部分用的是 Nordic UART Service 的 UUID这是 ESP32 上最常用的 BLE 串口服务。mtu 20是 BLE 单次传输的字节限制后面会在驱动层做透明分片。approval_timeout 30表示审批请求发出后 30 秒内没有响应就自动放行避免卡住任务。4. ESP32 端 BLE 连接与 asyncio 状态轮询脚本ESP32 这边我用的是 MicroPython因为 asyncio 支持比较完整写并发任务方便。核心逻辑分三块BLE 连接管理、状态机、渲染循环。4.1 BLE 透明分片ESP32 的 BLE NUS 服务单次只能发 20 字节JSON 消息很容易被截断。我在驱动层做了透明拼接发送时自动按 20 字节分片加帧头标记接收时自动拼接完整消息遇到换行符再抛给上层。这样上层代码收发 JSON 就和普通字符串一样简单。import bluetooth import struct import asyncio class BLETransport: def __init__(self, ble, conn_handle): self.ble ble self.conn_handle conn_handle self.rx_buffer b async def send_json(self, data: str): payload data.encode(utf-8) b\n for i in range(0, len(payload), 20): chunk payload[i:i20] self.ble.gatts_notify(self.conn_handle, TX_CHAR, chunk) await asyncio.sleep_ms(10) def on_rx(self, data: bytes): self.rx_buffer data while b\n in self.rx_buffer: line, self.rx_buffer self.rx_buffer.split(b\n, 1) asyncio.create_task(self.handle_message(line.decode(utf-8)))4.2 双层状态机状态机分两层base 状态和 Claude Code 同步active 状态是临时动画。比如审批通过后跳爱心舞持续 2-3 秒后自动回落到 base 状态。这样就算 Claude 还在忙碌跳完庆祝舞也会自动回到忙碌状态不用写复杂的恢复逻辑。class StateMachine: def __init__(self): self.base_state idle self.active_state None self.active_until 0 def set_base(self, state: str): self.base_state state def trigger_active(self, state: str, duration_ms: int 2500): self.active_state state self.active_until ticks_ms() duration_ms def current(self) - str: if self.active_state and ticks_ms() self.active_until: return self.active_state self.active_state None return self.base_state4.3 三任务异步并发用 asyncio 开三个独立任务ble_task 处理蓝牙连接和消息收发touch_task 监听触控render_task 固定 20FPS 渲染动画。就算 Claude 疯狂发消息小猫的眨眼动画也不会掉帧。async def ble_task(transport): while True: await transport.process() await asyncio.sleep_ms(50) async def touch_task(state_machine): while True: if touch_pressed(): state_machine.trigger_active(approve) await asyncio.sleep_ms(100) async def render_task(state_machine, display): while True: state state_machine.current() display.render(state) await asyncio.sleep_ms(50) async def main(): state_machine StateMachine() transport BLETransport(ble, conn_handle) await asyncio.gather( ble_task(transport), touch_task(state_machine), render_task(state_machine, display) )5. 验证请求从终端到 ESP32 的完整链路配置写完之后先验证 TaoToken 的 API 通道是否通。在终端里直接跑一条 curlcurl -X POST https://taotoken.net/api/v1/messages \ -H x-api-key: sk-your-taotoken-key-here \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-20250514, max_tokens: 100, messages: [{role: user, content: ping}] }如果返回正常的 JSON 响应说明 Key 和通道都没问题。然后启动守护进程python3 ~/claude-buddy/daemon.py --config ~/claude-buddy/config.toml守护进程会开始扫描 BLE 设备找到名为ClaudeBuddy的 ESP32 后自动连接。连接成功后ESP32 屏幕上会显示CONNECTED然后进入空闲状态。接下来在另一个终端里跑 Claude Codeclaude --dangerously-skip-permissions注意这里加了--dangerously-skip-permissions是为了让 Claude Code 不弹终端审批全部走我们的 Hook 转发。当你让 Claude 执行一个 Bash 命令时ESP32 屏幕上会弹出审批界面显示命令内容和一个倒计时。点一下 YES命令才会真正执行。实测下来从 Hook 触发到 ESP32 显示审批请求延迟在 200ms 左右基本感觉不到。审批通过后小猫会跳个爱心舞然后回到忙碌状态继续同步进度。6. 本篇常见错排查6.1 BLE 连接不上最常见的原因是设备名不对。ESP32 广播的名称必须和 config.toml 里的device_name完全一致大小写敏感。另外确认一下 PC 的蓝牙适配器支持 BLE 4.0 以上有些老适配器只支持经典蓝牙扫不到 NUS 服务。如果连接后频繁断开把reconnect_interval调大一点比如 10 秒。BLE 连接本身就不太稳定加个自动重连逻辑能省很多事。6.2 Hook 不触发检查.claude/settings.json里的hooks配置是否正确。matcher字段用的是正则表达式Bash|Write|Edit表示匹配这三种工具。如果你想让所有工具都触发审批可以改成.*。另外确认hook_bridge.py有可执行权限并且路径是绝对路径。Claude Code 执行 Hook 的时候工作目录可能和你想象的不一样用绝对路径最保险。6.3 TaoToken 返回 401先检查 Key 有没有复制完整前后有没有多余空格。然后确认ANTHROPIC_BASE_URL填的是https://taotoken.net/api不要加/v1或者别的后缀。如果还是 401去 TaoToken 控制台确认一下 Key 的状态看看是不是被禁用了或者额度用完了。6.4 ESP32 屏幕不刷新大概率是 render_task 被阻塞了。检查一下有没有在渲染循环里做耗时操作比如同步的文件读写或者网络请求。所有耗时操作都应该放到独立的 asyncio 任务里用await asyncio.sleep_ms()让出控制权。如果屏幕完全没反应先确认电源是否正常。ESP32 的屏幕背光耗电不小USB 供电不足的时候可能会闪屏或者不亮。7. 接入文档与后续调试整套方案跑通之后你可以根据自己的需求调整。比如换一个 ASCII 角色或者加一个蜂鸣器审批请求来的时候响一声。硬件抽象层都放在config.py里换板子只需要改引脚定义业务代码不用动。如果你在接入 TaoToken 的过程中遇到问题或者想看看完整的 API 参数说明可以直接翻接入文档。需要管理多个 Key 或者查看用量的话控制台里有详细的调用记录。长期跑编码任务的话Coding Plan 的额度更划算适合把 Claude Code 当成日常开发搭子的人。调试的时候有个小技巧先把守护进程的日志级别调到 DEBUG这样能看到每一条 BLE 消息的收发内容。确认链路通了之后再调回 INFO不然日志刷得太快反而看不清关键信息。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。