| name | esp-idf-cy |
| description | 面向第一次接触 ESP-IDF 的新手及已有工程用户的一站式 skill——用户只需说板子/芯片和想做什么,skill 自动检测或安装 macOS/Windows 开发环境(国内网络走乐鑫官方镜像),并完成编译、烧录、串口验证、设备命名/收录和排错;EIM、Python、工具链与环境激活默认由 skill 内部处理。支持 ESP32 全系芯片(ESP32/S2/S3/C3/C6 等)。当用户提到 "ESP-IDF"、"idf.py"、"ESP32 编译"、"烧录固件"、"flash 到板子"、"串口 monitor/日志"、"装 ESP-IDF"、"IDF 环境配置"、"menuconfig"、"sdkconfig"、"hello_world 跑不起来"、"找不到串口/COM口"、"esptool"、"给开发板命名"、"收录/记住这个设备"、"设备别名" 时必须触发;即使用户只说"我刚买了 ESP32-S3,电脑什么都没装,帮我开始"、"帮我把这个 ESP32 项目编译烧录一下"、"看看板子输出了什么",也应触发。不做:Arduino-ESP32 / PlatformIO 工作流,具体外设驱动业务代码的编写。 |
| license | GPL-3.0-only |
esp-idf-cy — ESP-IDF 编译/构建/烧录(agent 能力为主,脚本为辅)
你在处理什么
用户可能用 Mac 也可能用 Windows,项目在任何位置,ESP-IDF 装没装、怎么装的、装的哪个版本都不确定。
你的职责:用户一句"编译烧录",你负责搞清环境 → 缺什么补什么 → 编译 → 烧录 → 验证。
环境差异和故障靠你自己的侦察和判断吸收,不指望用户懂环境,也不指望脚本枚举了所有情况。
宿主边界:本 skill 运行在已经能执行 Agent 工具的会话里。macOS/Linux 需要可调用 Bash;
Windows 需要 Agent 宿主提供 Git Bash,或由 Agent 直接用系统 PowerShell 调用
scripts/eim-windows.ps1。它会自动补齐 ESP-IDF 所需的 EIM、Python、Git 和工具链,
但不能在自己尚无法执行时“先安装自己的 shell/Agent 宿主”。不要把这个边界甩给新手;
若当前 Windows 会话没有 Bash,就由你改走已有 PowerShell,而不是要求用户学习 EIM。
新手第一次使用的体验目标
默认把用户当作可能完全没装过、也不需要先理解 ESP-IDF 安装体系的新手:
- 用户只需要提供能知道的业务信息:板子/芯片型号、已有项目路径,以及想编译还是烧录。
能从已连接板子、项目
sdkconfig/README 自动判断的就自己判断;只有判断不出且会改变 GB 级
下载目标或烧录安全性时,才问一个简短问题。
- EIM、
export.sh、Python 虚拟环境、工具链包和镜像都是内部实现细节。默认只报告结果,
不把安装教程、官网链接或一串依赖清单甩给用户;只有失败定位或用户主动追问时才解释。
doctor.sh 若证明现有环境 READY=yes,就复用探测到的精确版本和位置,继续用户的任务。
不要因为有更新的 stable 就静默升级、重装或切换版本。
- 确认没有可用环境时才自动安装:已有项目优先服从项目锁定的精确版本;新项目用
stable;
从板子推导并显式传 --targets,避免默认下载全部芯片工具链。安装完成必须真实执行
idf.py --version;若用户要“从零开始/跑起来”,再用对应 target 构建官方最小示例完成端到端验证。
- 正常情况下不要让用户暂停去手工装 Python/Git/SDK 或访问网页。只在系统权限/系统弹窗
(如 macOS Command Line Tools)、缺少无法探测的板型信息,或真实烧录确认时请用户介入。
- 完成后用新手听得懂的三件事收口: 装好了什么版本和位置、验证到了哪一步、下一句可以怎么说。
不要用 EIM 等实现名词作为成功摘要的主角。
Agent-first 动态决策,不要把示例路径当事实
- 先看当前 Agent 实际拥有的能力(shell、PowerShell、Computer Use、网络、文件权限),再选路线。
脚本提供确定性检查和安全门禁,但脚本没覆盖的机器差异由你继续侦察、读日志和处理,不能把
“不在默认目录”直接等同于“没有安装”。
- 路径来自用户上下文和机器证据:项目
build/project_description.json、IDF_PATH、EIM 登记、
IDE 设置、进程环境和经过边界限制的文件搜索。~/esp、C:\esp 只是最后的惯例候选;
找到候选后必须验证 tools/idf.py 和真实 idf.py --version。
- GUI 不是默认依赖。CLI 能完成就由 Agent 直接做;用户明确要求 GUI 且当前宿主有 Computer Use 时,
Agent 可操作 EIM 的普通按钮、版本选择和日志页面。密码、Touch ID、UAC、macOS 安全确认及许可
接受属于系统信任边界,必须让用户本人处理。没有 Computer Use 时自动回到 CLI,不要把一串点击
教程丢给新手。
ACTION_REQUIRED/rc=20 表示可恢复的人机交接:说明用户只需完成哪个系统动作,完成后由 Agent
重跑原命令并续上。不要让用户重新理解整套安装流程。
三层职责不要混淆:
- **你(Agent)**负责侦察证据、选择路线、解释异常、向用户取得烧录确认并持续推进。
- **
SKILL.md**只给决策顺序、安全红线、完成标准和按需读取 reference 的路由。
- **
references/**保存会随 ESP-IDF/EIM/平台变化的命令与排错知识;执行前以实机和当前官方能力复核。
- **
scripts/**提供确定性探针、可重入默认安装动作,以及验签、argv传递、身份解析、精确验证、
超时等机械边界。它们可以执行你已选定的路线,但不是决策者或用户授权门禁;输出与实机冲突时
继续调查,不能盲信或无脑重跑。
按任务渐进读取,不要一次把全部知识塞进上下文:
| 当前阶段 | 先读 |
|---|
| 安装、修复、EIM、PowerShell-only | references/install-playbook.md |
| 国内网络或镜像失败 | references/china-mirrors.md |
| target、idf.py、esptool、EIM 命令 | references/idf-commands.md |
| 已有报错、驱动、BOOT/RESET、串口异常 | references/troubleshooting.md |
| 设备命名、收录、改名、版本快照 | references/device-registry.md |
五条物理事实,决定了下面所有做法:
export.sh 只对当前 shell 生效,而你每次 Bash 调用都是新 shell
→ 每条 idf 命令都要在同一条命令里先装配环境。
- 你没有交互终端 → menuconfig(TUI)和官方
idf.py monitor(强制要求 TTY)
对你不可用;配置改 defaults,日志验证用有界的 pyserial 采集器。
- 烧录/复位会让 USB 重枚举 → 端口名不能跨步骤缓存,每次烧录/监视前重扫。
- 烧录 = 覆盖用户硬件上的固件,板上可能跑着用户其他项目
→ 未验明设备身份并经用户确认,不烧。这条不因任何理由松动。
- flash 退出 0 ≠ 新固件已经运行 → 手动下载模式可能仍停在 ROM;只有目标身份已重验、
应用专用健康标志命中且没有 ROM 下载证据,才能报告烧录闭环完成。
设备长期记录再加两条硬边界:
- 名称只负责可读性:底层始终按 fresh MAC 关联。多设备时先由 Agent 扫描并逐块验身,
再把当前端口、芯片、名称和 MAC 尾号列给用户选;只有无法安全逐块连接时才请用户暂时拔掉一块。
- 版本必须带来源:存储 schema 分开保存 environment/project/firmware,不得只有一个通用
idf_version。界面可把证据充分的“当前固件 IDF”作为摘要,但不能丢掉另外两类观测或把摘要
当设备永久属性。
工作方式:侦察 → 判断 → 行动 → 验证
以你自己的能力为主:自己跑命令探测、自己读报错、自己决定下一步。
脚本和文档是工具不是流程——脚本覆盖不了的情况,你直接上手。
侦察:环境线索在哪
省事的话跑 bash <skill>/scripts/doctor.sh 一次拿全景(KEY=VALUE 输出)。
自己侦察时的线索地图:
- IDF 在哪:项目已有 build 时先读
build/project_description.json 的 idf_path,再看 $IDF_PATH;
EIM 登记文件 eim_idf.json(POSIX 在
~/.espressif/tools/,Windows 在 C:\Espressif\tools\);惯例路径 ~/esp/esp-idf*。
仍没有时检查项目 .vscode/settings.json/CI/终端配置,再只对用户目录、已知 SDK 根目录或实际磁盘
做有界搜索,不要无界扫描整盘。版本用 git -C <目录> describe --tags 或真命令拿,别信目录名。
- 工具链健康度:
~/.espressif/python_env/idf<IDF版本>_py<py版本>_env——目录名本身
编码了它绑定的 python 版本,系统 python 升级过它就失效(经典坑)。
- Python 闸门:优先读取所选 IDF 自带的版本检查/当前 EIM 前置结果;reference 里的版本表只是
已验证快照。遇到未知的新 major 必须查当前证据或 fail closed,不能默认回落到旧 Python 下限。
- 串口:mac 看
/dev/cu.usbmodem*(乐鑫原生口)和 /dev/cu.usbserial*/SLAB*/wch*(桥接);
linux 看 /dev/ttyACM*//dev/ttyUSB*;Windows 用 PowerShell
Get-CimInstance Win32_PnPEntity -Filter "PNPClass='Ports'",乐鑫原生口 DeviceID 含
VID_303A&PID_1001。
- 网络:GitHub 不畅但国内可达 → IDF仓库、工具资产和pip优先走乐鑫官方机制
(
references/china-mirrors.md)。EIM本体自举是否有国内官方资产要按当期来源另查;不要先把VPN甩给用户,
也不要为“能下载”绕过hash/签名。
- 探到多个 IDF 版本或奇怪位置 → 把候选列给用户选,别猜。
环境装配:每条 idf 命令的写法
安装或修复(先判断状态再做)
- 先以
doctor.sh 的真实命令结果和你的现场证据做三态分流:
READY=yes:原样复用,不安装、不升级。
- 已发现精确安装但真命令/工具损坏:EIM管理的优先
eim fix -p <精确路径>,legacy才重跑该仓库
的官方安装工具;修完仍对同一路径严格复检。
- 确认不存在兼容环境:才新安装。多个候选或证据冲突时继续调查或只问一个会改变结果的问题。
- 省事路径:
bash <skill>/scripts/install.sh [--version stable|v5.5|v5.5.4] [--targets esp32s3]
——幂等、可安全重跑、国内自动镜像。首次 clone 走同级受管暂存区,完整后才原子落位;
子模块与工具下载可重复执行。下载量以 GB 计,后台跑或放宽超时。
- macOS 空白机:
install.sh 先侦察再动态选路。已有可用 EIM 时直接复用;已有 Homebrew 且
未指定精确仓库路径时,按 ESP-IDF v6.0+ 官方默认路线补齐乐鑫列出的前置、安装/复用 EIM CLI
并非交互安装。EIM 与 Homebrew 都没有或用户传了 --path 时,不静默引入包管理器,改走仍受官方支持的
bootstrap-macos.sh + ESP-IDF install.sh 路线。缺 Command Line Tools 时主动
拉起苹果系统安装窗口;缺兼容 Python 时,已有 Homebrew 就自动安装,没有 Homebrew 就从
Python.org 下载固定版本的 universal2 官方包,同时校验 SHA256 和 Python Software Foundation
签名后才打开系统安装器。系统 UI 必须由用户本人确认;脚本返回 ACTION_REQUIRED/rc=20 时
不是安装失败,等用户完成后重跑原命令即可续上。不要静默安装 Homebrew,也不要用 curl|sh
引入第三方 Python。EIM 在 POSIX 只检查前置:有 Homebrew 时 install-eim-macos.sh 先安装官方
清单;只有 EIM 时允许它先做真实检查,失败后 Agent 根据缺项换官方脚本路线或向用户说明选择。
不能把“EIM 已装”误当成“所有依赖已齐”。
- 脚本失败或不适用(特殊版本/公司代理/非常规位置):别无脑重跑。读它的输出定位卡点,
按
references/install-playbook.md 的配方自己一步步来——每一步都能单独重试和替换。
- 版本选择:先看项目 README/CI/容器配置;已有项目跟它的精确版本。新项目默认
stable;--version v5.5 表示“5.5 系列最新 patch”,要复现才传 v5.5.4 这类精确 tag。
--targets 从板子/项目推导并显式传入(C6→esp32c6);候选必须以所选 IDF 的
idf.py --list-targets/当前官方元数据验证,reference中的有限列表不是完整真相;真不知道才用 all。
- Windows 优先用
winget 精确包/官方源/用户 scope 安装 EIM;fallback 动态读官方 GitHub release,
必须同时通过 release asset SHA256 与 Espressif Authenticode 签名才落盘和执行。EIM 的安装/运行
都默认 --do-not-track true;不要直接执行未验签的下载 exe。
- 装完或修复后必须经过严格门禁:先从EIM登记/安装输出锁定本次实际路径,清除ambient
IDF_PATH干扰,再真实运行 idf.py --version并要求READY=yes;仓库元数据版本与
idf.py --version 实际报告版本都必须和请求精确一致;
macOS/Linux 还要与请求安装路径一致。任一不满足都算安装失败,不能因安装器退出 0 就报成功。
用户的目标是开始开发时,继续做目标芯片的最小示例构建,
不把“安装脚本退出 0”当作完成。最后用人话告诉用户版本、位置、验证结果和下一步即可。
编译
- 编译前先运行
doctor.sh --project <项目目录> 或做等价检查。ESP-IDF 官方不支持 IDF 路径或
项目路径包含空白;shell 引号只能保留参数边界,不能修复上游构建限制。发现空白时不要直接移动
用户原项目:先检查相对依赖/符号链接,再由 Agent 选择无空格的实际路径建立受管工作副本或经用户
确认迁移;完成后重新体检并明确产物位置。
- 芯片型号从用户话里拿("S3 板子"→ esp32s3),或看项目 sdkconfig 的
CONFIG_IDF_TARGET,
都没有就问。首次或换芯片先 set-target(会重新生成 sdkconfig)。
- 首次 build 编译几百个文件,几分钟正常,后台跑。
- 报错不要瞎试:先看第一个
error:,对照 references/troubleshooting.md,没匹配再自己分析。
- 编译完把关键信息报给用户:固件大小、分区余量(build 输出末尾就有)。
烧录(硬安全规约,agent-first 不改变这条)
- 重扫端口(线索见"侦察";或
bash <skill>/scripts/find-port.sh)。
- 只读验明设备:
bash <skill>/scripts/identify-device.sh -p <口> 拿芯片型号+MAC
(内部兼容 esptool v4/v5 命令名;连接会复位板子,但不写 flash)。
- 向用户报告"将烧录到 <口> 的 <型号>(MAC xx:xx)",用户确认才烧;
多设备把候选全列出来让用户挑;芯片型号和项目 target 不符,拦下来问。
- 烧录显式
-p。只要经历复位/掉线/USB 重枚举,必须在新口上重跑
identify-device.sh;MAC 与用户刚确认的设备一致才能续烧。同一 MAC 无需再问,
不同/读不出则立即停。
可选设备收录与命名
把设备身份、显示名称和软件版本严格分层:
identify-device.sh 本次真实读取的标准化 MAC 才是设备键;用户名称只是当前电脑上的显示标签。
名称允许重复,不能单独选择硬件、证明重枚举前后是同一设备或授权烧录。
- fresh 识别成功后先按 MAC 查询本机目录。命中时显示
名称 · 芯片 · MAC尾号;真正烧录确认仍显示本次读取的完整 MAC、端口与 target。
- 首次见到且用户未主动要求时,最多提供一次非阻塞选择:“要给它起一个只保存在这台电脑上的名称吗?”
用户跳过就不创建持久记录,不影响当前任务,本会话也不重复追问。只有明确同意收录/命名才调用
scripts/device-registry.py remember;改名/忘记同样需要明确目标和用户意图。
- 多块设备同名时全部列出芯片、当前端口和 MAC 尾号让用户消歧,不静默覆盖、不自动选一个,
也不把别名重新绑定到新 MAC。用户说“烧到桌面板”后仍先扫描并逐块 fresh 验身;能自动列全时
不要求用户先拔板,只有 USB/驱动/板级限制导致无法分别连接时才用逐块插拔作为退路。
- IDF 版本不是设备永久属性。分别记录:
- 当前实际激活环境的
idf.py --version;
- 当前 build metadata 的项目构建版本;
- 刚烧录 app image 的
esp_app_desc_t.idf_ver,或运行应用主动报告的版本。
三者可能不同,缺哪项就保持未知,绝不能用当前环境版本冒充板上固件版本。只识别硬件时不要为了补版本
额外读 flash、复位或进入下载模式。设备目录底层不得提供一个含糊的总 idf_version/“主版本”
字段;外部存储只有一个通用版本格时先扩展 schema,不能三选一或把三类证据塞进同一字符串。
UI 可把证据充分的 firmware 域标成“当前固件 IDF”作摘要,其余来源仍保留在详情。版本不同只证明
观测不同,不足以自行断言哪个“旧了”、哪个已经烧到板上。详细证据和命令见
references/device-registry.md。
- 设备目录只保存在当前用户数据目录,不进项目/Git/云同步;普通列表掩码 MAC,不保存项目绝对路径、
串口日志、网络或业务数据。别名不进入文件名和 shell 命令。
板子没进下载模式 / 连不上时的标准应对(不要报错了事,把用户带过去):
Failed to connect、等待包头超时或端口暂时消失,不足以单独证明板子没进下载模式;
也可能是端口选择、USB 重枚举、数据线或驱动问题。芯片型号相同不代表开发板下载/复位电路相同,
先按本轮历史和具体板子的按键、原理图/说明、USB 接口与供电方式判断:
- 自动连接尚未真实尝试时,先让用户不碰按键,由所选
idf.py/esptool 的默认复位机制尝试。
- 已能与 ROM 通信、刚完成一次手动进入动作或正在等 USB 重枚举时,板子已经在下载模式;
不要再次要求按 BOOT,直接重扫、验身并按既有授权继续。
- 只有自动连接已失败且证据表明尚未进入下载模式时,才选择这块板真实具备的一种手动动作:
- 有
BOOT + RESET/EN:按住 BOOT → 点按一次 RESET/EN → 松开 BOOT。
- 只有
BOOT:按住 BOOT → 真正断电再上电 → 松开 BOOT。只有 USB 供电时可拔插 USB;
有电池或外部供电时拔 USB 不等于断电。
- 没有 BOOT 按键:查当前芯片资料与板型说明/原理图,确认这块板真实的下载 strap 焊盘、跳线
或厂商恢复方式;不要让用户寻找不存在的按键,也不要把所有 ESP32 系列的 BOOT 都硬编码成 GPIO0。
普通断电重上电本身不能保证进入下载模式。
- 端口不见时跑
bash <skill>/scripts/wait-port.sh -t 90;它只返回 CANDIDATE_PORT,
多口时拒绝猜 BEST_PORT。拿到候选口后重跑 identify-device.sh,匹配原 MAC 才续烧。
等特定口用 -p <端口>,但即使名字没变也要重验身份。
- 只有用户/跳线实际参与进入下载模式才记
manual;完全由控制线/原生 USB 自动进入记
automatic,无法确认才记 unknown。手动/不明方式烧完必须继续下面的恢复门禁。
- wait-port 超时(90s 没动静):按它输出的 HINT 引导用户检查数据线、板级进入方式和驱动,再等一轮;
连接不稳的板子换
-b 115200 低速烧。
烧录后闭环(prepare → 物理恢复 → verify)
identify-device.sh 内部使用 esptool,会主动连接 ROM 并改变复位状态。因此 MAC 的最后一次重验
必须发生在最终物理恢复之前;用户按 RESET/重新上电后严禁再跑 identify/esptool 来判断
“是否还在下载模式”。使用两阶段门禁:
bash <skill>/scripts/post-flash-check.sh prepare \
-p <烧录口> -m <用户已确认的MAC> \
--download-entry <automatic|manual|unknown>
bash <skill>/scripts/post-flash-check.sh verify --session <POST_FLASH_SESSION> \
-C <proj> -e '<能证明应用健康的正则>' [-p <已明确的恢复后端口>]
--download-entry 由你根据本轮历史显式传 automatic|manual|unknown,不能从端口日志猜。
manual/unknown 的 prepare 会输出 ACTION_REQUIRED=restore_normal_boot_for_board 和 rc=20;
这不是固定按键命令。manual 时只释放本轮实际使用且仍被拉低的下载条件(松开 BOOT/移除下载
strap 跳线),恢复正常启动绝不再次按 BOOT;随后有 RESET/EN 就点按一次,没有则真正断电再上电。
unknown 时先确保下载 strap 未被拉低,不清楚就只问一个板型/供电问题。用户完成后拿同一个
session 续跑 verify,不要把模式改写成 automatic。
automatic 的 prepare 返回 rc=0 和 NORMAL_BOOT_RECOVERY_REQUIRED=no;直接 verify,
不要求用户按或松 BOOT,也不预先要求实体 RESET。只有新鲜 ROM 下载证据出现后才转入板级恢复。
- 重新上电必须切断这块板的全部供电;有电池、调试器或外部 5V/3V3 时只拔 USB 可能没有产生
上电复位。板上既无按键又无法确认安全断电方式时,查板型说明/原理图,不要编造统一手势。
- prepare 会把已匹配的 MAC、进入方式和烧录口写入权限受限、限时的 session;verify 必须校验它,
不能靠调用方自报“已经验过身份”。成功后 session 自动消费。
- verify 阶段只做 fresh rescan + 尝试串口控制线 reset/采集,零次调用 identify/esptool。
控制线 API 调用成功不能证明具体板子已把 RTS 接到 EN;脚本会把 reset 效果保持为
unverified,
仍以应用证据为准。
prepare只证明最终恢复前的MAC匹配。原端口消失后,脚本只能返回恢复后候选;由你结合刷新前后
清单、USB topology/serial、用户明确选择等证据传入 -p。当前只有一个新口也不等于同一设备;
证据不足保持未验证。macOS /dev/cu.*、Windows COM号都不是永久身份。
- 只有应用
-e 命中时才输出 POST_FLASH_READY=yes/rc=0。DOWNLOAD_BOOT(...)、
DOWNLOAD(USB/UART0...)、waiting for download 是仍在 ROM 下载模式的强证据,输出 rc=20;
无日志、端口消失、普通 ESP-ROM/rst: 文本只是不确定,不能冒充 READY 或下载模式确诊。
- 用户已明确收录设备时,只有
POST_FLASH_READY=yes 后才能把刚烧录 app image 的内嵌 IDF 版本
记录为该 MAC 的 flash_verified 固件快照。只有本地 image 但尚未烧录/验证时不得绑定到设备;
未收录或用户跳过命名时不因烧录成功自动创建长期记录。
- 原始串口内容不混入机器 KV,而是写到
CAPTURE_LOG 指向的权限受限系统临时文件;需要排错时读取,
任务结束后删除。恢复后的 -p 只是本轮明确定位符,多口或无法唯一关联时必须停下来让用户选择。
- 不默认尝试
--after watchdog-reset:它不是全芯片通用恢复路径,C6 原生 USB 场景甚至可能需要
断电恢复。跨 ESP32 系列的保守兜底是保持所有下载 strap 释放,再用该板实际具备的 RESET/EN、
全部断电再上电或厂商恢复方式,不是统一要求某个按键。
- 应用健康证据若是蜂鸣、灯光、继电器等只能由用户观察的物理现象,最终只给当前板适用的一条
正常启动动作并让用户报告观察结果。例如板上无 RESET/EN 时就只要求保持 BOOT 释放并真正重新上电;
自动下载且已正常运行时直接观察,两个键都不碰。用户或任务一旦声明“不再运行设备识别或写入命令”,
严格停在这个观察边界,不得为了确认再调用 identify/esptool 或追加写入。
监视(只采集日志或作为上述 verify 的底层)
官方 esp-idf-monitor 在 stdin 非 TTY 时会拒绝启动;它没有 expect/reset/exit 文本 DSL。
agent 验证固件用有界的直接串口采集:
bash <skill>/scripts/monitor.sh -p <口> -C <proj> -t 50 -R -e '<能证明正常的正则>'
脚本会从 build/project_description.json 读波特率(也可 -b 覆盖),匹配则 0,
超时未匹配则 1,开口失败 2,读取失败 3,缺 pyserial 4,参数错误 64;输出
DATA_SEEN/CAPTURE_BYTES 区分“完成了纯采集”和“真的看到了数据”。它不做官方 monitor 的符号化地址解码;
用户给定的 expect 正则会在可终止的独立进程里匹配,并受采集总 deadline、64 KiB 窗口和
4096 字符模式上限约束;量词嵌套等高风险模式直接 rc=64,不能用复杂回溯绕过 -t 超时。
如需人类交互调试,告诉用户在真终端里跑 idf.py monitor。agent 不裸跑它。
单独 monitor 等不到输出时不要直接断言仍在下载模式;回到上面的 post-flash 两阶段门禁。
配置修改
改项目的 sdkconfig.defaults(没有就创建)→ set-target 重新生成。
不直接编辑生成的 sdkconfig(会被覆盖),不跑 menuconfig。常用 CONFIG 项见 references/idf-commands.md。
辅助工具箱(可选加速器,不是必经之路)
| 脚本 | 值得用的时候 | 别依赖它的时候 |
|---|
scripts/doctor.sh | 开场一次拿全景,省多轮探测 | 输出和你实际观察冲突时,以实际为准 |
scripts/install.sh | 动态安装(mac 有 EIM/Homebrew→EIM,否则官方脚本 / win EIM) | 非标场景 → install-playbook 手动配方 |
scripts/install-eim-macos.sh | 复用 Mac EIM;有 Homebrew 时先补官方前置 | EIM/Homebrew 都没有;不要借此静默安装包管理器 |
scripts/bootstrap-macos.sh | Mac 缺 CLT/Python 时自动补到系统 UI 边界 | 非 macOS;系统安装窗口仍需用户本人确认 |
scripts/idf-env.sh | 需要统一免激活入口且其现场假设成立时 | 它不是授权门禁;特殊环境/调试export时由Agent原生装配 |
scripts/find-port.sh | 快速扫口;单口给候选,多口报需选择 | 它不代替芯片+MAC 验身 |
scripts/identify-device.sh | 烧前及重枚举后读芯片+MAC | 读不出就停,不用端口名替代身份 |
scripts/device-registry.py | 用户同意后保存名称和分域 IDF 证据;按 fresh MAC 查询 | 别名不代替验身、target、授权或 post-flash session |
scripts/wait-port.sh | 提示用户操作后等候选端口 | 多口不自动选;返回后必须重验 MAC |
scripts/monitor.sh | 无 TTY 时定时采集日志/正则验证 | 需要地址符号化或人类交互时用真终端的官方 monitor |
scripts/post-flash-check.sh | flash 后做 prepare/verify 闭环,处理手动下载模式 | verify 后不再跑 identify;无应用 expect 不能判 READY |
同一个脚本失败两次 → 停止重试脚本,读输出、换你自己的手来。
references(知识库,按需读)
references/install-playbook.md — 按平台安装/修复、PowerShell-only原语和每步失败处理
references/idf-commands.md — 当前命令速查、动态target发现、破坏性操作前置和版本差异
references/china-mirrors.md — 国内镜像机制底账(只有网络/镜像问题时读)
references/troubleshooting.md — 已知报错、驱动、BOOT/RESET和串口排错剧本
references/device-registry.md — 本机设备命名、重复名称消歧、IDF版本证据与隐私边界
反模式
- ❌ 不装配环境裸跑
idf.py(必失败)
- ❌ 裸跑
idf.py monitor / menuconfig(交互式,卡死会话)
- ❌ 缓存串口名跨步骤复用,或把新端口名当设备身份(重枚举后要对 MAC)
- ❌ 把用户名称当设备身份或烧录授权,或因别名相同跳过 fresh MAC 复验
- ❌ 把当前
idf.py --version、项目期望版本或本地未烧录 image 写成设备正在运行的固件版本
- ❌ 为设备设置单一 IDF“主版本”,或仅凭三个版本不同推断固件新旧和烧录历史
- ❌ 未经用户同意持久保存 MAC/别名,或把本机设备目录写进项目、Git、云同步和公开日志
- ❌ 把 flash 退出 0、普通 boot log 或无 expect 的 monitor rc=0 当作应用已运行
- ❌ 用户最终恢复正常启动后再跑 identify/esptool“验身”(它会重新扰动启动状态)
- ❌ 把 BOOT/RESET 当成所有开发板的固定步骤,或在恢复正常启动时再次要求按 BOOT
- ❌ 跨芯片默认使用 watchdog reset;应按具体板子的 RESET/EN、完整断电或厂商方式恢复
- ❌ 不验明设备、未经用户确认就烧录(多设备烧错板子;板上可能是用户其他项目)
- ❌ 把
idf-env.sh 当成烧录授权门禁,或把未确认的 flash/erase/write 命令交给它执行
- ❌ 把用户/仓库提供的路径、正则或参数直接拼进
eim run 命令字符串
- ❌ 被脚本框死:脚本失败无脑重跑、脚本没覆盖就说做不了(你的能力才是主体)
- ❌ 假设用户平台、假设项目在固定路径
- ❌ 只因默认目录没找到就判定“未安装”,或无界扫描整块磁盘
- ❌ 认为给带空格的 IDF/项目路径加引号就能让 ESP-IDF 支持它
- ❌ 把 EIM GUI/Computer Use 设成公开 Skill 的强依赖,或代用户处理密码/Touch ID/UAC
- ❌ 国内装不动就先让用户开 VPN,或为绕过网络问题执行未验签的 EIM
- ❌ 直接编辑生成的 sdkconfig
环境变量
| 变量 | 用途 | 默认 |
|---|
ESP_IDF_CY_IDF_PATH | 显式指定用哪个 IDF(多版本/非常规位置) | 自动探测 |
ESP_IDF_CY_EIM_BIN | 显式指定 EIM 二进制(直下/非 PATH 安装) | PATH 或 ~/.esp-idf-cy/bin/eim(.exe) |
ESP_IDF_CY_EIM_JSON | 显式指定已发现的 eim_idf.json;探测、run、fix、install统一使用其目录 | 平台官方默认登记 |
ESP_IDF_CY_EIM_VERSION | Windows fallback 要求的精确 EIM tag;不设则动态取最新正式版 | 最新正式版 |
ESP_IDF_CY_INSTALL_MODE | macOS 安装路线:auto/eim/official-script;Agent 按实机覆盖 | auto |
ESP_IDF_CY_PROJECT_DIR | 提供项目上下文,允许从 build 元数据发现非常规 IDF | 从 idf.py -C/doctor 参数提取 |
ESP_IDF_CY_DEVICE_REGISTRY_DIR | 覆盖用户明确启用的本机设备目录;不要指向项目/Git/共享目录 | 当前用户私有数据目录 |
ESP_IDF_CY_PYTHON_BIN | 显式指定兼容 Python;Mac bootstrap 成功后也用它续传 | 自动探测 |
ESP_IDF_CY_MAC_PYTHON_VERSION | 无 Homebrew 时下载的 Python.org 版本 | 3.13.14 |
ESP_IDF_CY_MAC_PYTHON_SHA256 | 对应 Python.org pkg 的 SHA256 | 内置官方发布值 |
ESP_IDF_CY_MAC_PYTHON_URL | 公司镜像/后续维护时覆盖官方 pkg URL | python.org 官方 URL |
ESP_IDF_CY_CURL_BIN | 覆盖网络探针和 macOS 下载所用 curl(测试/非标准环境) | curl |
IDF_TOOLS_PATH | 工具链位置(透传给官方脚本) | ~/.espressif |