关于
FoloToy Codex Buddy
FoloToy Codex Buddy 是面向 FoloToy AI Passport 的 ESP32-C3 固件与桌面桥接 方案。它把原本独立的掌上设备变成 Codex 的实体伴侣:当 Codex 思考、执行命令、修改 文件或等待授权时,设备会用状态界面、像素宠物、灯光和声音给出反馈;用户也可以直接用 三个实体按键批准一次、使用 Codex 明确提供的会话级批准,或拒绝操作。
项目希望解决一个很具体的问题:长时间运行 Codex 任务时,用户不必一直盯着终端,也不必 在审批出现时重新切回电脑。AI Passport 负责展示经过压缩的任务信息和承接明确的审批动作, 完整命令、diff 与模型输出仍保留在电脑端。
当前固件基于 ESP-IDF 5.5.3,目标芯片为 ESP32-C3。FoloToy AI Passport 没有 PSRAM,因此界面和 19 种宠物均采用低内存程序化绘制。
演示视频
点击封面前往 YouTube 观看完整演示。
项目组成
Codex 原生 TUI
│ WebSocket JSON-RPC(localhost)
▼
Codex Buddy 审批代理
┌─────┴─────┐
│ │
Codex app-server 加密 BLE Nordic UART
│
▼
FoloToy AI Passport(ESP32-C3)
| 模块 | 作用 |
|---|---|
| ESP32-C3 固件 | 驱动屏幕、按键、电池、音频和 BLE,渲染状态并安全提交审批结果 |
| macOS 桥接器 | 启动本地 app-server 与原生 TUI,透明转发流量并把状态和审批映射到设备协议 |
| Buddy 协议 v2 | 提供能力协商、审批 nonce、结果 ACK、幂等重试和心跳失效保护 |
| 主机测试与兼容性工具 | 在没有硬件时验证协议、状态机、队列策略和 Codex schema 兼容性 |
代理只管理通过它创建或恢复的 Codex thread,不能接管 Codex Desktop 中已经运行的任务。 三类审批请求不会再转发给 TUI,而是只等待设备决策;普通问题、MCP 表单和其他未知服务端 请求仍透明传给原生 TUI。设备也不是通用远程终端:它只展示适合 240×320 屏幕的摘要, 并把实体按键决策返回给对应的审批请求。
核心能力
- 显示
Ready、Thinking、Working、Approval required、Completed、Failed和Interrupted等 Codex 状态。 UP批准一次、OK执行 Codex 明确提供的会话级批准、DOWN拒绝。- 支持 command、file-change、filesystem permission 和 network permission 审批。
- Codex 风格近黑高对比 UI,状态栏显示 BLE、安全连接、电量和时间。
- 设备页显示电池百分比和电压,低电量使用颜色与数字共同提示。
- 审批到达时双音和持续闪屏提醒,任务完成时播放上升音并闪屏。
- 19 种 4-bit 程序化像素宠物;
CODEX为启动默认宠物,支持七种状态动画。 - BLE LE Secure Connections、六位码配对、绑定、加密读写和自动重连。
- 协议 v2 包含 capability negotiation、审批 nonce、结果 ACK 和幂等重试。
- 30 秒没有有效心跳时清除审批,避免离线或旧连接继续授权。
适用场景
- 在编译、测试或代码生成任务运行时,把 AI Passport 放在桌面上查看进度。
- 离开终端窗口后,通过声音和闪屏及时发现新的审批请求或任务完成事件。
- 演示 Codex 的任务状态、权限边界和人机协作流程。
- 研究资源受限 ESP32-C3 上的 LVGL、NimBLE、安全配对和可靠消息协议实现。
本项目目前以 macOS 桥接器为主,适合开发和实验使用。固件构建、主机测试和一次实机启动
冒烟检查已有记录;配对重连循环、完整审批流程和 30 分钟稳定性仍需按
docs/validation/ 中的清单在真实设备上完成,不能仅凭编译通过视为
完整硬件验收。
硬件与软件要求
硬件:
- FoloToy AI Passport(ESP32-C3、8 MB Flash)
- ST7789P3 240×320 屏幕
- CW2017 电量计
- ES8311 音频 Codec
- 可传输数据的 USB 线
开发环境:
- ESP-IDF 5.5.3
- CMake、Ninja 和 ESP-IDF 自带 Python 环境
- macOS 桥接功能需要 Python 3 和支持 BLE 的 Mac
- Codex CLI,或包含 Codex 可执行文件的 Codex Desktop
桌面代理只在 127.0.0.1 上创建临时 WebSocket 监听,不向局域网暴露端口。Codex
app-server 的 WebSocket/remote TUI 接口目前是实验功能,升级 Codex 后应运行本仓库的
schema 兼容性检查。官方接口说明见 Codex App Server。
获取源码
git clone https://github.com/bingkina/FoloToy-Codex-Buddy.git
cd FoloToy-Codex-Buddy
仓库根目录就是唯一的固件源码目录:其中应直接包含 main/、components/、tests/
和 sdkconfig.defaults。构建、测试和刷机命令都必须在这个根目录执行,不要从下载目录、
旧副本或其他构建目录刷写。每次刷机前运行 idf.py build,确保写入的是当前源码生成的
最新固件。
刷机教程
交给 Agent 自动刷机
如果使用能访问本机终端和 USB 串口的 Codex 或其他编码 Agent,请让它阅读上述指南, 然后发送:
请按照 docs/AGENT_FLASHING.md 直接帮我刷机并验证启动。
设备已经通过 USB 连接;不要清空设备设置。
Agent 会自行检查 ESP-IDF 版本、识别唯一串口、编译、核验芯片、刷写并检查启动日志; 只有无法唯一确定设备或需要物理操作时才会询问用户。普通网页聊天无法访问本机 USB, 需要在具备本机终端和硬件访问能力的 Agent 环境中执行。
1. 安装并进入 ESP-IDF 5.5.3 环境
请先按照 Espressif ESP32-C3 入门文档 安装 ESP-IDF 5.5.3。每次打开新终端后加载环境:
source /path/to/esp-idf-v5.5.3/export.sh
idf.py --version
idf.py --version 应显示 ESP-IDF v5.5.3。不要使用 Arduino 构建链或其他 ESP-IDF
版本替代。
2. 连接设备并确认串口
使用支持数据传输的 USB 线连接 AI Passport。常见端口示例:
| 系统 | 端口示例 |
|---|---|
| macOS | /dev/cu.usbmodem101 |
| Linux | /dev/ttyACM0 |
| Windows | COM5 |
macOS 可执行:
ls /dev/cu.usbmodem* /dev/cu.usbserial* 2>/dev/null
Linux 可执行:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
3. 配置并编译
第一次编译或清理过配置后执行:
idf.py set-target esp32c3
idf.py build
成功后主要生成以下文件:
| 文件 | 烧录地址 | 用途 |
|---|---|---|
build/bootloader/bootloader.bin | 0x0 | Bootloader |
build/partition_table/partition-table.bin | 0x8000 | 分区表 |
build/FoloToy-AI-Passport.bin | 0x10000 | 主固件 |
这些是构建产物,不提交到 Git;需要分发固件时应作为 GitHub Release 附件发布。
4. 普通用户:从 GitHub Release 下载预编译固件
不需要修改源码的用户无需安装完整编译环境。请打开项目的 GitHub Releases,下载最新版本中的:
FoloToy-Codex-Buddy-merged.bin:首次安装或恢复使用的单文件整包;SHA256SUMS.txt:整包固件的 SHA-256 校验值。
首次刷机请严格按照普通用户从零刷机流程完成工具安装、文件 校验、串口识别、芯片核验、写入和启动检查。
安装独立的 esptool 后,可将整包从 0x0 写入:
python -m pip install esptool
python -m esptool --chip esp32c3 -p PORT -b 460800 \
--before default_reset --after hard_reset write_flash \
0x0 FoloToy-Codex-Buddy-merged.bin
把 PORT 换成设备的实际串口。固件仅适用于 FoloToy AI Passport(ESP32-C3、8 MB
Flash);不要为其他型号刷入该镜像。公开 Release 面向首次安装或恢复设备;整包会
覆盖 NVS,因而清除设备设置和 BLE 绑定。
5. 开发者推荐方式:直接刷机并查看日志
将下面端口替换为实际端口:
idf.py -p /dev/cu.usbmodem101 flash monitor
Windows 示例:
idf.py -p COM5 flash monitor
串口监视器中出现 Codex Buddy starting,并看到 display、battery、audio、button 和
BLE 初始化完成,即表示启动成功。按 Ctrl+] 退出监视器。
以后只修改代码并重新刷机时,通常直接执行:
idf.py build
idf.py -p /dev/cu.usbmodem101 flash
6. 使用已有 BIN 文件手动刷机
如果已经取得上述三个 BIN 文件,可在 ESP-IDF 环境中执行:
python -m esptool --chip esp32c3 -p /dev/cu.usbmodem101 -b 460800 \
--before default_reset --after hard_reset write_flash \
--flash_mode dio --flash_freq 80m --flash_size detect \
0x0 build/bootloader/bootloader.bin \
0x8000 build/partition_table/partition-table.bin \
0x10000 build/FoloToy-AI-Passport.bin
不要只把主固件写到 0x0;主固件的正确地址是 0x10000。
7. 可选:生成单文件整包固件
需要给量产工具或其他用户提供单个文件时,可将三段镜像合并:
python -m esptool --chip esp32c3 merge_bin \
--flash_mode dio --flash_freq 80m --flash_size 8MB \
-o build/FoloToy-Codex-Buddy-merged.bin \
0x0 build/bootloader/bootloader.bin \
0x8000 build/partition_table/partition-table.bin \
0x10000 build/FoloToy-AI-Passport.bin
合并文件从 0x0 写入:
python -m esptool --chip esp32c3 -p /dev/cu.usbmodem101 -b 460800 \
--before default_reset --after hard_reset write_flash \
0x0 build/FoloToy-Codex-Buddy-merged.bin
也可以在完成 idf.py build 后运行仓库提供的打包脚本:
bash scripts/package_firmware.sh
脚本会在 dist/firmware/ 生成整包和 SHA256SUMS.txt。
8. 发布新版本(维护者)
推送符合 v* 格式的版本标签会触发 Release firmware GitHub Actions 工作流:
git tag v1.0.0
git push origin v1.0.0
工作流使用固定的 ESP-IDF 5.5.3 容器全新构建 ESP32-C3 固件、合并单文件镜像、计算
SHA-256,并将全部文件上传到对应的 GitHub Release。也可以在 GitHub Actions 页面手动
运行该工作流并填写版本标签;预发布标签(例如 v1.0.0-rc.1)会创建 prerelease。
9. 刷机失败排查
Serial port not found:更换数据线或 USB 口,并重新确认串口名称。Port is busy:关闭其他串口监视器、IDE 或占用该端口的程序。- 一直停在
Connecting...:重新插拔设备;若板卡提供 BOOT 键,可按住 BOOT 后复位, 进入下载模式再试。 - 配置或依赖异常:执行
idf.py fullclean,再重新运行idf.py set-target esp32c3和idf.py build。 - 需要彻底清空时可执行
idf.py -p PORT erase-flash。这会删除 NVS、BLE 绑定和所有 设备设置,属于不可恢复操作,之后必须重新刷入完整固件。
首次启动与配对
- 启动后设备默认显示
CODEX宠物,并以Codex-<MAC 后缀>广播。 - 启动 macOS 桥接器并允许系统蓝牙权限。
- 首次连接时,设备显示六位 Secure Connections passkey。
- 在 macOS 配对窗口输入该六位数字。
- 加密连接建立后,设备开始显示 Codex 状态和审批请求。
BLE RX、TX 和 TX CCCD 均要求经过认证的加密连接。已绑定设备可自动重连;设备设置中 可以执行 Unpair,恢复出厂设置也会清除绑定。
macOS Codex 桥接器
创建独立 Python 环境:
python3 -m venv .venv-codex-buddy
. .venv-codex-buddy/bin/activate
python -m pip install -r tools/macos_codex_buddy/requirements.txt
启动原生 Codex TUI,并把状态和审批请求同步到设备:
python -m tools.macos_codex_buddy.cli tui \
--cwd /path/to/project
该模式使用仅监听 localhost 的 WebSocket 代理。Codex 原生 TUI 负责输入、Markdown、 历史记录、斜杠命令和 thread 切换;代理只截获命令、文件变更和权限审批,并等待设备端 决策。其他 App Server 请求仍交给 TUI 处理。BLE 意外断开时,代理会拒绝待处理审批、 中断当前 turn 并关闭 TUI,避免在失去实体授权通道后继续等待或误授权。
如需旧版无 TUI 的连续任务模式,可运行:
python -m tools.macos_codex_buddy.cli run \
--session --use-daemon \
--cwd /path/to/project \
--approval-policy untrusted \
"Run tests"
附近有多台设备时添加 --device Codex-A1B2C3。也可用 --codex PATH 指定 Codex
可执行文件。桥接器只管理通过本地代理创建或恢复的 thread,不能附着到 Codex Desktop
中已经运行的任务。
macOS 用户也可以直接双击 Start Codex Buddy.command,选择工作目录、完成 BLE 配对,
然后进入原生 Codex TUI。
测试
固件主机测试:
cmake -S tests -B build-host
cmake --build build-host
ctest --test-dir build-host --output-on-failure
macOS 桥接器测试与协议兼容性检查:
python -m unittest discover -s tools/macos_codex_buddy/tests -v
python -m tools.macos_codex_buddy.schema_compat
提交前应同时通过主机测试和一次全新的 ESP-IDF 5.5.3 构建。编译成功不能代替实机
验收;完整检查项目见 docs/validation/。
项目结构
components/bsp/ 显示、按键、电池、音频和共享 I2C 板级驱动
main/ BLE、协议、状态机、设置、UI 和 Codex 宠物
tests/ 无硬件依赖的 C 测试
tools/macos_codex_buddy/ 原生 TUI ↔ app-server ↔ BLE 审批代理
tools/windows_buddy_controller/ Windows 控制与协议工具
docs/validation/ 构建和实机验收记录
安全与限制
- 完整命令、diff 和模型输出保留在电脑端,设备只显示适合 240×320 屏幕的摘要。
- 原生 TUI 代理只监听 localhost;不要把临时监听地址改成非回环地址。
- 外部输入使用定长缓冲区;未知命令、错误 nonce、过期审批和旧连接事件均失败关闭。
- 当前不支持触摸、Wi-Fi 控制、GIF/大图集或旁路接管 Codex Desktop。
- ESP32-C3 没有 PSRAM,修改 LVGL、BLE 或音频缓冲区时需要重新检查内部 RAM。
- 尚需在真实设备上完成 20 次连接/断开循环和 30 分钟连接稳定性测试。
许可证与归属
项目基于 FoloToy AI Passport 固件结构开发,并保持对公开 Hardware Buddy Nordic UART
协议的兼容。第三方组件的版权和许可证信息见 NOTICE 及各组件目录。
截图
特性
一键安装
通过 Web Serial API 在浏览器内直接刷写固件到你的 AI Passport
FoloToy Codex Buddy:从零开始刷机
本流程面向普通用户,不需要下载源码或安装 ESP-IDF。完成后,FoloToy AI Passport 会运行 Codex Buddy 固件。
0. 开始前确认
准备以下物品:
- FoloToy AI Passport(ESP32-C3、8 MB Flash);
- 一根支持数据传输的 USB 线;
- Windows、macOS 或 Linux 电脑;
- Python 3.10 或更高版本及网络连接。
**重要:**公开版是从
0x0写入的完整固件,会清除设备原有设置和 BLE 绑定。只在 首次安装或确定要恢复设备时继续。固件不能用于其他型号。
可选:交给 Agent 自动刷机
如果 Codex 或其他编码 Agent 能访问本机终端和 USB 串口,可以让它自动完成文件下载、
隔离 Python 环境创建、esptool 安装、SHA-256 校验、串口识别、ESP32-C3 核验、刷写和
结果检查。普通网页聊天不能访问本机 USB,无法代替本地 Agent 执行。
将设备通过 USB 连接后,把本发布页面链接和下面的指令一起发送给 Agent:
请阅读这个 GitHub Release 页面的完整刷机说明,并按照其中流程自动下载和刷入当前版本。
设备已经通过支持数据传输的 USB 线连接到电脑。
我允许你在隔离的 Python 虚拟环境中安装 esptool,也已知晓并同意完整固件会清除设备设置
和 BLE 绑定。请自动完成以下工作:
1. 下载 FoloToy-Codex-Buddy-merged.bin 和 SHA256SUMS.txt;
2. 校验 SHA-256,失败时立即停止;
3. 探测串口;只有一个明确匹配的端口时自动选择,无法唯一确定时询问我;
4. 使用 chip-id 核验设备确实是 ESP32-C3,型号不符时立即停止;
5. 从 0x0 写入完整固件,并检查写入校验结果;
6. 确认设备正常重启;无法读取启动状态时明确标记 NOT RUN。
不要执行 erase-flash,不要使用 --force,也不要在校验失败或芯片型号不符时继续。
只有需要连接设备、选择多个候选串口或操作 BOOT/RESET 键时再询问我。
Agent 可以自动处理软件步骤,但以下情况仍需要用户配合:设备尚未连接、存在多个无法区分 的串口、USB 线仅能供电,或设备必须手动按 BOOT/RESET 进入下载模式。
1. 下载两个文件
展开本发布页面底部的 Assets,把下面两个文件下载到同一个文件夹:
FoloToy-Codex-Buddy-merged.bin:完整固件;SHA256SUMS.txt:固件校验值。
后续命令都要在这个下载文件夹中运行。可以在终端中使用 cd 进入该文件夹,例如:
cd ~/Downloads
Windows 用户可在文件夹空白处右键选择“在终端中打开”。
2. 安装 Python 和 esptool
如果尚未安装 Python,请从 Python 官网安装 Python 3.10 或更高版本。Windows 安装时勾选 Add python.exe to PATH。
Windows PowerShell:
py --version
py -m pip install --upgrade esptool
py -m esptool version
macOS 或 Linux:
python3 --version
python3 -m pip install --upgrade esptool
python3 -m esptool version
如果最后一条命令能显示 esptool 版本,即表示工具安装成功。
3. 校验下载的固件
Windows PowerShell:
$expected = (Get-Content .\SHA256SUMS.txt).Split()[0]
$actual = (Get-FileHash .\FoloToy-Codex-Buddy-merged.bin -Algorithm SHA256).Hash.ToLower()
if ($actual -eq $expected) { "OK" } else { "FAILED: 请重新下载两个文件" }
macOS:
shasum -a 256 -c SHA256SUMS.txt
Linux:
sha256sum -c SHA256SUMS.txt
只有结果为 OK 时才继续。出现 FAILED 时不要刷机,请删除文件并重新下载。
4. 连接设备并找到串口
使用数据线把 AI Passport 直接连接到电脑。关闭可能占用串口的 Arduino IDE、串口监视器 或其他刷机程序。
Windows PowerShell:
[System.IO.Ports.SerialPort]::GetPortNames()
常见结果为 COM5。也可以在“设备管理器 → 端口”中查看。
macOS:
ls /dev/cu.usbmodem* /dev/cu.usbserial* 2>/dev/null
常见结果为 /dev/cu.usbmodem101。
Linux:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
常见结果为 /dev/ttyACM0。如果有多个端口,可拔下设备、再次执行命令,再插回设备比较
新增的端口。记住实际端口,下面用 PORT 表示它。
5. 核验芯片型号
先确认连接的是 ESP32-C3,避免刷错设备。把命令中的 PORT 换成上一步的实际端口。
Windows 示例:
py -m esptool --chip esp32c3 --port COM5 chip-id
macOS 示例:
python3 -m esptool --chip esp32c3 --port /dev/cu.usbmodem101 chip-id
Linux 示例:
python3 -m esptool --chip esp32c3 --port /dev/ttyACM0 chip-id
输出必须确认芯片是 ESP32-C3。型号不符时立即停止。
6. 写入固件
确认终端仍位于两个下载文件所在的文件夹,然后执行对应命令。
Windows PowerShell:
py -m esptool --chip esp32c3 --port COM5 --baud 460800 --before default-reset --after hard-reset write-flash 0x0 .\FoloToy-Codex-Buddy-merged.bin
macOS:
python3 -m esptool --chip esp32c3 --port /dev/cu.usbmodem101 --baud 460800 \
--before default-reset --after hard-reset write-flash \
0x0 FoloToy-Codex-Buddy-merged.bin
Linux:
python3 -m esptool --chip esp32c3 --port /dev/ttyACM0 --baud 460800 \
--before default-reset --after hard-reset write-flash \
0x0 FoloToy-Codex-Buddy-merged.bin
刷写期间不要拔线、关闭终端或让电脑休眠。看到数据写入完成、校验成功和硬复位信息,才算 写入完成。
7. 确认启动成功
刷写完成后设备通常会自动重启。确认:
- 屏幕点亮并出现 Codex Buddy 界面或
CODEX宠物; - 设备没有持续黑屏或反复重启;
- 电脑蓝牙附近可发现名称以
Codex-开头的设备。
如果刷写成功但设备仍停留在下载模式,按一下 RESET;没有 RESET 键时,拔下 USB 后重新 插入。首次连接桌面桥接器时,设备会显示六位配对码,需要在 macOS 配对窗口中输入。
8. 常见问题
- **找不到串口:**确认 USB 线支持数据传输,换一个 USB 口,避免只供电的线和不稳定的 扩展坞。
- **
No module named esptool:**安装与运行必须使用同一个命令;Windows 都使用py -m, macOS/Linux 都使用python3 -m。 - **
Permission denied(Linux):**确认当前用户有串口权限,并关闭占用端口的程序。 - **
Failed to connect或一直Connecting...:**重新确认端口;仍失败时,按住 BOOT, 按一下 RESET 后松开 BOOT,再重新执行刷机命令。 - **端口被占用:**关闭串口监视器、Arduino IDE 和其他刷机工具后重试。
- **写入中途失败:**更换数据线或 USB 口,并把命令中的
--baud 460800改为--baud 115200后重试。 - **校验失败:**不要继续刷机,重新下载固件和
SHA256SUMS.txt。 - **刷完黑屏:**重新插拔设备;如果仍无显示,保留完整终端输出并提交 Issue。
不要自行执行 erase-flash。完整固件已经包含所需引导程序和分区表,无需额外擦除。
官方工具参考
版本更新
需要 Chrome/Edge 89+ · 不支持时可查看手动教程
手动安装教程 ↗
