1. 项目概述一个会“催更”的实体代码搭子最近在折腾Claude Code CLI的时候突然冒出一个想法这玩意儿在命令行里跟我对话提醒我写代码、review代码功能是挺酷但总觉得少了点“实感”。作为一个喜欢捣鼓硬件的程序员我就在想能不能把这个虚拟的“代码监工”给实体化让它变成一个看得见、摸得着甚至有点“脾气”的电子宠物于是这个基于ESP32和MicroPython的“Claude Code CLI 实体监工搭子”项目就诞生了。简单来说这是一个通过蓝牙BLE与你的电脑通信的小设备。它静静地趴在你的桌角当你长时间不写代码比如在刷网页、摸鱼时它会通过灯光、表情甚至轻微震动来“提醒”你该干活了。而当你完成一个功能模块、通过测试或者提交了代码它则会给你一个“点赞”的反馈。核心思路就是把Claude Code CLI这种基于文本的、被动的代码辅助体验升级成一种具象的、带有情感化交互的实体陪伴。它适合所有觉得命令行工具有点冰冷希望开发环境更有趣、更有互动感的程序员尤其是那些喜欢物联网IoT和硬件DIY的极客们。2. 核心设计思路与方案选型2.1 为什么是“实体监工”在深入技术细节前我想先聊聊为什么选择这个方向。我们每天面对IDE和终端信息流是单向的、沉默的。Claude Code CLI虽然能交互但它仍然被困在屏幕里。实体化的核心价值在于建立一种超越屏幕的、低侵入性的注意力锚点。它不会像弹窗一样粗暴打断你的思路而是通过外围视觉灯光和触觉震动给你一个温和的提示。这种体验很像一个真实的搭档坐在旁边轻轻敲下桌子提醒你走神了比任何软件通知都更自然、更人性化。2.2 硬件核心ESP32为何是绝佳选择在硬件选型上我几乎没怎么犹豫就锁定了ESP32。原因有以下几点双核处理器与丰富外设ESP32的主频和内存足够流畅运行MicroPython并同时处理蓝牙通信、传感器数据读取和屏幕/灯光驱动多任务无压力。其内置的DAC、触摸传感器、霍尔传感器等为未来功能扩展如添加环境音监测、磁吸交互留足了空间。低功耗蓝牙BLE是刚需本项目需要与电脑保持长时间、低功耗的无线连接。ESP32的BLE协议栈成熟稳定开发资料丰富能轻松实现设备广播、服务发布和与电脑端CLI工具的数据交换。相比Wi-FiBLE在保持连接时的功耗要低得多适合7x24小时待机。MicroPython开发效率奇高对于这种重交互逻辑、轻底层驱动的创意项目MicroPython是生产力利器。它允许我用Python这种熟悉的高级语言快速原型迭代直接操作GPIO、驱动屏幕、处理JSON数据省去了嵌入式C语言复杂的编译、烧录和调试周期。强大的社区与生态无论是相关的开发板如合宙ESP32-C3、传感器模块还是遇到问题时的解决方案ESP32的社区支持都是顶级的。这意味着很多功能你不需要从零造轮子。2.3 软件架构双向通信与状态机整个系统的软件架构围绕“状态同步”和“事件驱动”展开。设备端ESP32运行一个状态机。状态包括“空闲”、“工作中”、“提醒中”、“庆祝中”。每个状态对应不同的灯光模式、屏幕动画和是否启用传感器监测。它通过BLE广播自身并提供一个包含“状态写入”和“日志读取”特性的GATT服务。电脑端CLI插件核心是一个后台守护进程Daemon。它做了三件事监听系统与IDE通过文件系统监控如watchdog监听项目目录、进程查询如检测浏览器或游戏进程或IDE插件API来判断开发者的活动状态。与Claude Code CLI集成解析CLI的输出或提供钩子hooks当Claude给出“建议开始编码”或“代码审查通过”等指令时能捕获这些事件。BLE通信管理发现并连接我们的ESP32设备根据监听和捕获到的事件向设备写入对应的状态指令例如写入“提醒”状态码。通信协议为了简单高效我设计了一个极简的基于JSON的文本协议。通过BLE的一个可写特征Characteristic传输。例如电脑端发送{cmd: set_state, state: remind}设备端解析后切换到提醒状态。注意电脑端监听活动是一个敏感操作务必在代码中明确告知用户并获得授权仅用于本项目改善工作效率的初衷并确保所有数据处理都在本地完成。3. 硬件搭建与核心电路解析3.1 物料清单与选型考量除了ESP32开发板这个大脑为了让“宠物”有表现力还需要一些外围器件显示单元我选择了一块1.3英寸的IPS LCD彩屏ST7789驱动。为什么不用OLED虽然OLED更省电但IPS LCD在可视角度和显示丰富的表情动画上更有优势而且成本相差无几。屏幕用于显示“宠物”的各种表情 休眠、 专注、⚠️ 提醒、 庆祝。反馈单元RGB LEDWS2812B环贴在设备外壳内侧用于环境光氛围渲染。不同颜色代表不同状态蓝色-连接中绿色-工作中黄色-闲置红色-提醒。震动马达扁平转子马达用于提供触觉反馈。在提醒状态时短震在庆祝状态时长震两下这种物理反馈比纯视觉更抓人注意力。蜂鸣器有源可选。用于播放简单的提示音但考虑到办公环境我在代码中默认禁用了声音可通过配置开启。输入与感知单元EC11旋转编码器集成了按键功能。旋转可以调节屏幕亮度或切换模式按下按键可以手动切换状态或确认提醒。这给了用户主动交互的入口。温湿度传感器DHT22或SHT30我选择了精度更高的SHT30。初衷是让“宠物”能感知环境比如在温度过高时芯片过热给出“降温”提示增加一点拟人化的趣味性。电源与结构一枚常见的18650锂电池配合充放电管理模块如TP4056保证无线续航。外壳使用3D打印设计成一个小方块或小机器人的造型让所有传感器和屏幕合理排布。3.2 电路连接要点与避坑指南将这么多模块连接到ESP32需要仔细规划GPIO。下面是我的连接方案及原因模块连接ESP32引脚引脚类型备注与避坑点LCD屏幕 (ST7789)SCL-GPIO18, SDA-GPIO23SPI使用硬件SPI以获得最高刷新率。务必注意有些ESP32板子的默认SPI引脚被闪存占用需要根据具体型号调整。RGB LED (WS2812B)GPIO2数字输出需要一根数据线即可。重要WS2812B对时序要求严最好在代码中禁用此引脚的中断或使用RMT远程控制外设驱动这是ESP32的特色高效驱动方式。震动马达GPIO4数字输出通过一个NPN三极管如8050或MOSFET驱动切勿直接连接ESP32的GPIO驱动电流不足。EC11编码器CLK-GPIO32, DT-GPIO33, SW-GPIO25数字输入CLK和DT需要配置上拉输入。避坑编码器抖动严重必须在软件中做消抖处理例如设置一个50ms的防抖延时。SHT30传感器SCL-GPIO22, SDA-GPIO21I2C使用硬件I2C。I2C总线可以挂载多个设备注意地址不要冲突。电池管理BAT/-接电池OUT/-接ESP32 Vin/GND-TP4056模块的CHRG和STDBY指示灯引脚可以接到ESP32用于监控充电状态。实操心得在面包板上搭建原型时务必先分模块测试。例如先单独测试屏幕显示再测试LED最后整合。电源管理是关键当所有模块同时工作时尤其是屏幕和LED全亮电流需求可能骤增一个好的稳压电路和足够容量的电池是稳定运行的保障。我曾因电源纹波过大导致ESP32不断重启后来在ESP32的电源输入脚就近加了一个100μF的电解电容才解决。4. 设备端MicroPython固件开发详解4.1 开发环境搭建与固件烧录首先你需要为ESP32刷入MicroPython固件。我推荐使用合宙的ESP32-C3开发板性价比极高。获取固件从MicroPython官网下载最新的ESP32通用固件.bin文件。烧录工具使用esptool.py这个Python工具。安装命令pip install esptool。擦除与烧录将开发板通过USB连接电脑进入下载模式通常需要按住Boot键再按Reset键。然后执行以下命令替换COMx为你的实际端口如COM3或/dev/ttyUSB0# 擦除闪存 esptool.py --chip esp32c3 --port COMx erase_flash # 烧录固件 esptool.py --chip esp32c3 --port COMx --baud 460800 write_flash 0x0 micropython-firmware.bin验证使用串口工具如PuTTY、VS Code的Serial Monitor连接板子波特率115200如果看到MicroPython的REPL提示符说明成功。4.2 BLE服务与通信实现这是设备端代码的核心。MicroPython的bluetooth模块提供了BLE支持。我们需要创建一个包含自定义服务的BLE外围设备Peripheral。import bluetooth import struct import json from ble_advertising import advertising_payload # 定义自定义服务UUID可以随机生成但确保唯一 _SERVICE_UUID bluetooth.UUID(0xABCD) # 示例UUID _STATE_CHAR_UUID bluetooth.UUID(0xABCE) # 用于接收电脑指令的特征 _LOG_CHAR_UUID bluetooth.UUID(0xABCF) # 用于发送设备日志的特征可选 class BLEPet: def __init__(self, nameCodeBuddy): self._ble bluetooth.BLE() self._ble.active(True) self._ble.irq(self._irq_handler) self._connections set() self._state_handlers [] # 状态变更回调函数列表 # 注册服务 state_char (bluetooth.UUID(_STATE_CHAR_UUID), bluetooth.FLAG_WRITE | bluetooth.FLAG_NOTIFY,) log_char (bluetooth.UUID(_LOG_CHAR_UUID), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,) service (_SERVICE_UUID, (state_char, log_char),) services (service,) ((self._state_handle, self._log_handle),) self._ble.gatts_register_services(services) # 设置特征值的初始数据 self._ble.gatts_write(self._state_handle, b\x00) # 初始状态0 self._ble.gatts_write(self._log_handle, bHello from CodeBuddy!) # 设置可连接广播 payload advertising_payload(namename, services[_SERVICE_UUID]) self._ble.gap_advertise(100000, adv_datapayload) print(BLE Advertising started, name:, name) def _irq_handler(self, event, data): # 处理BLE事件连接、断开、写入等 if event 1: # _IRQ_CENTRAL_CONNECTED conn_handle, addr_type, addr data self._connections.add(conn_handle) print(Connected by:, addr) elif event 2: # _IRQ_CENTRAL_DISCONNECTED conn_handle, addr_type, addr data if conn_handle in self._connections: self._connections.remove(conn_handle) print(Disconnected:, addr) # 重播广播 self._ble.gap_advertise(100000) elif event 3: # _IRQ_GATTS_WRITE conn_handle, value_handle data if value_handle self._state_handle: # 收到电脑端发来的新状态指令 received_data self._ble.gatts_read(value_handle) self._process_command(received_data) def _process_command(self, data): try: cmd_dict json.loads(data.decode(utf-8)) cmd cmd_dict.get(cmd) if cmd set_state: new_state cmd_dict.get(state) print(New state received:, new_state) # 触发所有注册的状态处理函数 for handler in self._state_handlers: handler(new_state) except Exception as e: print(Command process error:, e) def register_state_handler(self, handler): 注册一个状态变更处理函数 self._state_handlers.append(handler)这段代码构建了BLE服务的骨架。_process_command方法解析从电脑发来的JSON指令并调用注册的状态处理函数。这些处理函数将负责更新屏幕、灯光和马达。4.3 多任务管理与状态机实现MicroPython本身支持简单的多线程_thread模块但对于我们这个项目使用异步编程asyncio是更优雅和高效的选择它能更好地处理并发I/O操作如BLE事件、编码器扫描、动画刷新。import uasyncio as asyncio from machine import Pin, PWM import neopixel import st7789 import sht30 class PetStateMachine: def __init__(self): self.current_state idle self.screen st7789.ST7789(...) # 初始化屏幕 self.leds neopixel.NeoPixel(Pin(2), 24) # 24颗LED灯环 self.motor Pin(4, Pin.OUT) self.encoder RotaryEncoder(pin_clk32, pin_dt33, pin_sw25) self.sensor sht30.SHT30() # 状态与对应处理函数的映射 self.state_actions { idle: self._state_idle, working: self._state_working, remind: self._state_remind, celebrate: self._state_celebrate } async def run(self): 主异步循环 while True: action self.state_actions.get(self.current_state) if action: await action() # 执行当前状态的任务 await asyncio.sleep(0.1) # 释放控制权 async def _state_idle(self): # 空闲状态屏幕显示睡眠表情灯光缓慢呼吸蓝色 self.screen.display_image(sleep.png) await self._breathing_effect((0, 0, 50)) # 蓝色呼吸 # 检查编码器或传感器事件 if self.encoder.button_pressed(): self.change_state(working) async def _state_working(self): # 工作状态屏幕显示专注表情灯光常亮绿色 self.screen.display_image(working.png) self.leds.fill((0, 50, 0)) self.leds.write() # 可以在这里读取传感器数据比如每10秒读一次温湿度 # temp, humi self.sensor.measure() # if temp 30: # self.screen.show_text(Hot!) async def _state_remind(self): # 提醒状态屏幕显示警告表情灯光闪烁红色马达短震 self.screen.display_image(warning.png) for _ in range(5): # 闪烁5次 self.leds.fill((50, 0, 0)) self.leds.write() self.motor.value(1) await asyncio.sleep(0.2) self.leds.fill((0,0,0)) self.leds.write() self.motor.value(0) await asyncio.sleep(0.2) # 提醒结束后自动回到空闲或工作状态 self.change_state(idle) async def _state_celebrate(self): # 庆祝状态屏幕显示开心表情彩虹灯效马达长震两次 self.screen.display_image(celebrate.png) self.motor.value(1) await asyncio.sleep(0.5) self.motor.value(0) await asyncio.sleep(0.2) self.motor.value(1) await asyncio.sleep(0.5) self.motor.value(0) await self._rainbow_effect(cycles2) self.change_state(working) def change_state(self, new_state): 安全地切换状态 if new_state in self.state_actions: print(fState change: {self.current_state} - {new_state}) self.current_state new_state # ... 灯光效果函数_breathing_effect, _rainbow_effect ...这个状态机类是整个“宠物”行为逻辑的核心。run()方法是异步任务的主循环它会持续执行当前状态对应的行为函数。状态切换通过change_state方法触发可以由BLE指令、编码器按键或内部条件如传感器超标调用。4.4 主程序整合与启动最后我们需要一个主文件来将所有模块整合并启动。# main.py import uasyncio as asyncio from ble_pet import BLEPet from pet_state_machine import PetStateMachine async def main(): # 初始化硬件和状态机 pet PetStateMachine() # 初始化BLE并注册状态处理器 ble BLEPet() ble.register_state_handler(pet.change_state) # 将状态切换函数注册给BLE print(Code Buddy Pet Started!) # 创建异步任务 pet_task asyncio.create_task(pet.run()) # 这里可以添加其他异步任务比如定期读取传感器 # sensor_task asyncio.create_task(read_sensor_periodically(pet)) # 等待所有任务实际上pet.run()是永不结束的循环 await asyncio.gather(pet_task) # 启动事件循环 try: asyncio.run(main()) except KeyboardInterrupt: print(Program stopped by user.) finally: # 清理工作如关闭灯光 pass将main.py、ble_pet.py、pet_state_machine.py以及相关的驱动库st7789.py,sht30.py等通过串口工具如ampy,rshell或VS Code的MicroPython插件上传到ESP32的文件系统中重启后设备就会开始广播等待连接。5. 电脑端CLI守护进程开发5.1 监听开发者活动状态电脑端程序的核心是判断开发者是否在“有效工作”。这里提供几种思路可以组合使用以提高准确性活动窗口/进程监控使用Python的psutil库周期性地检查当前焦点窗口的进程名。如果检测到浏览器chrome.exe,firefox.exe且标签页非开发相关或检测到游戏进程则判定为“可能摸鱼”。import psutil def get_active_process(): # 此方法在Windows/macOS/Linux上实现不同以下为简化示例 # 可能需要使用pygetwindow或Quartz(macOS)等库 # 返回进程名或None pass文件系统监控使用watchdog库监听项目目录下源代码文件.py,.js,.go等的修改事件。如果在设定的时间窗口内如15分钟没有任何修改事件则判定为“闲置”。from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler class CodeChangeHandler(FileSystemEventHandler): def on_modified(self, event): if not event.is_directory and event.src_path.endswith((.py, .js)): update_last_activity_time() # 更新最后活动时间戳IDE/编辑器集成这是最精准的方式。可以为VS Code、IntelliJ等编辑器开发插件直接监听编辑器的活动事件如文件保存、输入停止、测试运行。但这需要针对不同编辑器开发复杂度较高。一个折中方案是读取编辑器产生的临时文件或日志。5.2 与Claude Code CLI的交互目标是捕获Claude Code CLI的输出并解析关键信息。一个可行的方法是包装wrapCLI命令。子进程通信你的守护进程启动Claude Code CLI作为一个子进程并实时捕获其标准输出stdout。import subprocess import threading def run_claude_cli(): proc subprocess.Popen([claude, code, --your-flags], stdoutsubprocess.PIPE, stderrsubprocess.PIPE, textTrue) for line in iter(proc.stdout.readline, ): if It looks like you havent written code for a while in line: trigger_state(remind) elif Great job! This implementation looks solid. in line: trigger_state(celebrate)使用官方API/SDK如果提供如果Claude Code提供编程接口直接调用是更稳定和高效的方式。需要查阅其官方文档。5.3 BLE通信客户端实现在电脑端我们需要一个BLE中心设备Central来连接ESP32。在Python中可以使用bleak这个优秀的跨平台BLE库。import asyncio from bleak import BleakClient, BleakScanner import json ESP32_DEVICE_NAME CodeBuddy STATE_CHAR_UUID 0000abce-0000-1000-8000-00805f9b34fb # 需与设备端一致 async def connect_and_control(): device None # 1. 扫描设备 devices await BleakScanner.discover() for d in devices: if d.name and ESP32_DEVICE_NAME in d.name: device d break if not device: print(Device not found.) return # 2. 连接并发送指令 async with BleakClient(device.address) as client: print(fConnected to {device.name}) # 示例发送“提醒”状态 remind_cmd json.dumps({cmd: set_state, state: remind}).encode(utf-8) await client.write_gatt_char(STATE_CHAR_UUID, remind_cmd) print(Remind command sent.) # 可以保持连接监听设备端发来的通知如日志 # await client.start_notify(LOG_CHAR_UUID, notification_handler) # await asyncio.sleep(60) # 保持连接一段时间 # await client.stop_notify(LOG_CHAR_UUID) def trigger_state(state_name): 供活动监听模块调用的函数 asyncio.run(send_ble_command(state_name)) async def send_ble_command(state): # 简化的发送函数 cmd json.dumps({cmd: set_state, state: state}).encode(utf-8) # ... 连接并写入的代码同上...5.4 守护进程的整合与自启动将活动监听、CLI交互和BLE通信三个模块整合到一个主守护进程中并使用一个事件循环来协调它们。# daemon_main.py import asyncio import threading from activity_monitor import ActivityMonitor from claude_cli_wrapper import ClaudeCLIWrapper from ble_client import BLEManager class CodeBuddyDaemon: def __init__(self): self.ble_manager BLEManager() self.activity_monitor ActivityMonitor(on_idleself._on_idle, on_activeself._on_active) self.claude_wrapper ClaudeCLIWrapper(on_praiseself._on_praise, on_remindself._on_remind) self.current_activity active def _on_idle(self, idle_time): 当监测到闲置时调用 if idle_time 300: # 闲置超过5分钟 if self.current_activity ! idle: print(fUser idle for {idle_time}s, sending remind.) asyncio.create_task(self.ble_manager.send_state(remind)) self.current_activity idle def _on_active(self): 当监测到恢复活动时调用 if self.current_activity idle: print(User back to work.) asyncio.create_task(self.ble_manager.send_state(working)) self.current_activity active def _on_praise(self, reason): 当Claude给出表扬时调用 print(fClaude praised: {reason}) asyncio.create_task(self.ble_manager.send_state(celebrate)) def _on_remind(self, reason): 当Claude建议开始编码时调用 print(fClaude suggests: {reason}) # 可以在这里决定是立即提醒还是结合活动状态 if self.current_activity idle: asyncio.create_task(self.ble_manager.send_state(remind)) async def run(self): 主异步循环 # 启动BLE连接 connect_task asyncio.create_task(self.ble_manager.start()) # 启动活动监控可能需要在独立线程中运行同步代码 # 启动Claude CLI包装器 # 等待所有任务 await asyncio.gather(connect_task) if __name__ __main__: daemon CodeBuddyDaemon() # 对于Windows/macOS可以将其打包为系统服务或启动项 # 对于Linux可以创建systemd service文件 asyncio.run(daemon.run())为了让守护进程开机自启不同系统有不同方法Linux (systemd): 创建一个.service文件放在~/.config/systemd/user/下。macOS (launchd): 创建一个.plist文件放在~/Library/LaunchAgents/下。Windows: 可以创建计划任务或者使用pyinstaller打包成exe后添加到注册表启动项。6. 调试、优化与常见问题排查6.1 开发调试技巧分而治之务必先单独测试每个硬件模块屏幕、LED、传感器和每个软件功能BLE广播连接、状态机逻辑、电脑端监听。利用REPLMicroPython的交互式REPL是神器。通过串口实时执行命令可以快速测试函数、查看变量、调试硬件。打印日志在代码关键节点添加print()语句输出到串口。对于BLE通信打印发送和接收的原始数据有助于排查协议问题。电脑端模拟在开发电脑端守护进程时可以先写一个模拟脚本手动发送状态指令验证设备端响应是否正常无需等待活动监听逻辑完成。6.2 性能与功耗优化ESP32端深度睡眠Deep Sleep如果设备长时间未被连接可以进入深度睡眠仅通过定时器或外部中断如编码器按键唤醒极大降低功耗。屏幕背光控制通过PWM动态调节屏幕背光亮度在空闲时调暗。异步延时在状态机的asyncio.sleep()中非必要等待时使用较长的间隔如1秒减少循环频率。电脑端轮询间隔活动监控的检查间隔不宜过短设置为10-30秒是比较合理的既能及时响应又不会过度消耗CPU。连接保持BLE连接建立后尽量保持避免频繁断开重连因为扫描和连接过程比较耗电。6.3 常见问题与解决方案速查表问题现象可能原因排查步骤与解决方案ESP32无法被电脑扫描到1. BLE未激活2. 广播数据错误3. 距离过远或有干扰1. 检查代码中ble.active(True)是否执行。2. 检查广播负载advertising_payload是否包含正确的服务UUID。3. 靠近设备避开USB 3.0接口等强干扰源。电脑端连接后立即断开1. BLE服务/特征未正确注册2. MTU设置问题3. 设备端代码崩溃1. 检查gatts_register_services的返回值确认句柄有效。2. 尝试在电脑端连接后协商一个更大的MTU如bleak中设置mtu512。3. 查看设备端串口日志是否有异常抛出。屏幕显示花屏或错位1. SPI引脚配置错误2. 屏幕初始化参数分辨率、偏移不对3. 电源不稳定1. 核对屏幕驱动芯片型号ST7789/ST7735等和引脚定义。2. 查阅屏幕数据手册调整初始化序列中的xstart,ystart等参数。3. 确保屏幕的VCC和GND供电充足必要时单独供电。WS2812B LED灯珠颜色异常1. 数据线接反2. 时序问题3. 电源功率不足1. 检查DI数据输入是否接ESP32DO数据输出接下一个灯珠。2. 尝试使用ESP32的RMT外设驱动而非软件模拟。3. 全白时电流最大计算总电流是否超过电源如USB口500mA上限需外接供电。电脑端守护进程CPU占用高1. 活动监控轮询间隔太短2. BLE扫描未设置超时3. 代码存在阻塞操作1. 增加轮询间隔至15秒以上。2. 扫描设备时设置超时如BleakScanner.discover(timeout5.0)。3. 检查所有网络、文件IO操作是否都使用了异步async/await。状态切换不灵敏或错误1. 电脑端活动判断逻辑有误2. BLE指令发送失败或乱序3. 设备端状态机逻辑冲突1. 优化活动判断算法结合多种信号如键鼠事件文件变化。2. 在BLE通信中添加序列号和确认机制。3. 在设备端为状态切换加锁防止异步任务同时修改状态。6.4 功能扩展思路这个项目的基础框架搭建好后有很多可以扩展玩味的方向更多传感器加入麦克风模块识别环境噪音在太吵时显示“戴耳机”表情。加入光线传感器自动调节屏幕亮度。云端同步让ESP32连接Wi-Fi将你的“专注时间”、“被提醒次数”同步到Notion或Google Sheets生成每周编程报告。多人互动如果办公室有多个“代码宠物”可以让它们通过Wi-Fi或蓝牙Mesh进行简单通信比如当有人完成一个重大提交时所有人的宠物一起庆祝。自定义表情与动画开发一个简单的手机App或网页通过蓝牙上传自定义的GIF动画或图片到ESP32的闪存中让你的宠物拥有独一无二的表情包。这个“实体监工代码搭子”从想法到实现最大的乐趣在于将虚拟世界的逻辑与物理世界的反馈连接起来。它不仅仅是一个提醒工具更像是你编程时的一个小小仪式感。当红色的灯光闪烁起来你真的会下意识地关掉无关网页回到代码中而当庆祝的彩虹灯效亮起时完成一段代码的成就感也仿佛被放大了。