| name | esp-idf-build |
| description | Build this ESP-IDF project. Use when the user asks to build, compile, flash, monitor, or clean the project. Covers the working build command and environment setup. |
ESP-IDF Build
IRON LAW: Never run idf.py directly in the Bash shell. Always use the pwsh.exe wrapper command below. The MSYS environment inherited by Claude Code's Bash tool causes eim/idf.py to fail silently or refuse to run. Every command in this skill must go through the same pwsh.exe invocation pattern — no shortcuts.
This skill documents how to build and manage this ESP-IDF project from Claude Code.
Environment
All paths are derived from the variables below. Update them when IDF version or install location changes.
| Variable | Current Value | How to Find |
|---|
IDF_VERSION | 6.0.1 | idf.py --version in ESP-IDF PowerShell |
IDF_PATH | C:\esp\v6.0.1\esp-idf | echo $env:IDF_PATH |
IDF_TOOLS_PATH | C:\Espressif\tools | default unless customized |
IDF_PYTHON_ENV_PATH | C:\Espressif\tools\python\v6.0.1\venv | ls C:\Espressif\tools\python\ |
TOOLCHAIN_BIN | C:\Espressif\tools\xtensa-esp-elf\esp-15.2.0_20251204\xtensa-esp-elf\bin | ls C:\Espressif\tools\xtensa-esp-esp-elf\ |
Pre-flight: Confirm IDF version ⚠️ REQUIRED
Before building, verify the installed IDF matches expectations. Run once per session:
MSYS2_PATH_TYPE= MSYSTEM= pwsh.exe -NoProfile -Command "
\$env:MSYSTEM = \$null
\$env:MSYS2_PATH_TYPE = \$null
& 'C:\Espressif\tools\python\v6.0.1\venv\Scripts\python.exe' 'C:\esp\v6.0.1\esp-idf\tools\idf.py' --version"
If the version doesn't match, update the variables above before proceeding.
Why not eim run "idf.py build"
eim detects the inherited MSYS/Mingw environment from Claude Code's bash shell and refuses to run idf.py build. The eim run command only completes environment initialization but never reaches the actual build step.
Build Command
Use the following command via Bash tool (NOT PowerShell tool). Copy-paste the block and replace build with flash -p PORT / monitor / fullclean as needed.
MSYS2_PATH_TYPE= MSYSTEM= pwsh.exe -NoProfile -Command "
\$IDF = 'C:\esp\v6.0.1\esp-idf'
\$TOOLS = 'C:\Espressif\tools'
\$PYENV = 'C:\Espressif\tools\python\v6.0.1\venv'
\$TOOLCHAIN = 'C:\Espressif\tools\xtensa-esp-elf\esp-15.2.0_20251204\xtensa-esp-elf\bin'
\$env:IDF_PATH = \$IDF
\$env:IDF_TOOLS_PATH = \$TOOLS
\$env:IDF_PYTHON_ENV_PATH = \$PYENV
\$env:ESP_IDF_VERSION = '6.0.1'
\$env:MSYSTEM = \$null
\$env:MSYS2_PATH_TYPE = \$null
\$env:PATH = \$TOOLCHAIN + ';' + \$env:PATH
& \"\$PYENV\Scripts\python.exe\" \"\$IDF\tools\idf.py\" build"
Key points:
- Clear
MSYSTEM and MSYS2_PATH_TYPE to avoid eim's MSys/Mingw detection
- Add toolchain to PATH — clearing MSYS env removes the compiler from PATH; without this, CMake reports
xtensa-esp32s3-elf-gcc not found
- Set
ESP_IDF_VERSION=6.0.1 (required by idf_component_manager)
- Use
pwsh.exe -NoProfile for a clean PowerShell environment
- Call
idf.py directly via the venv Python interpreter
- Set timeout to 600000ms (10 minutes) for the build
Component Management
ESP-IDF supports two ways to include external components:
Option A: Local components/ directory (recommended)
Copy or symlink the component into <project>/components/<name>/. ESP-IDF automatically discovers it. No idf_component.yml entry needed for the copied component.
my_project/
├── components/
│ └── esp-tflite-micro/ # copied here
└── main/
├── CMakeLists.txt # PRIV_REQUIRES must list the component name
└── idf_component.yml # only declare dependencies NOT in components/
Option B: override_path in idf_component.yml
dependencies:
espressif/esp-tflite-micro:
version: "*"
override_path: "../../../path/to/component"
This can fail in ESP-IDF v6.0.1 if the component manager cannot resolve the path. Prefer Option A when in doubt.
Common Pitfall: missing PRIV_REQUIRES
If main includes headers from a component, that component must be in PRIV_REQUIRES:
idf_component_register(
SRCS "app_main.cpp"
INCLUDE_DIRS "."
PRIV_REQUIRES spi_flash esp-tflite-micro # <-- required
)
Without this, the compiler reports No such file or directory for the component's headers.
Common Tasks
Build
Clean
⚠️ Destructive operation. fullclean deletes the entire build/ directory. Confirm with the user before running.
Use the same command block as Build, replacing build with fullclean.
Flash
Flash requires a COM port. Ask the user for the port before flashing.
Use the same command block as Build, replacing build with -p COM_PORT flash.
Monitor
Use the same command block as Build, replacing build with -p COM_PORT monitor.
Build Output
- Firmware:
build/<project_name>.bin
- Bootloader:
build/bootloader/bootloader.bin
- Partition table:
build/partition_table/partition-table.bin
Common Pitfalls
Format specifiers on ESP32-S3
On ESP32-S3, int32_t is long int and uint32_t is long unsigned int. Using %d for these types causes -Werror=format build failures. Use PRI macros from <cinttypes>:
#include <cinttypes>
printf("zero_point=%" PRId32 "\n", input->params.zero_point);
printf("version=%" PRIu32 "\n", model->version());
Known Warnings (non-fatal)
ESP_ROM_ELF_DIR not defined — only affects gdbinit generation, does not affect build
Running as elevated user — eim warning, safe to ignore