ESP-IDF Project Setup Guide
When to Use This Skill
Apply this skill when the user:
- Wants to set up the build environment for the first time (
setup) - Needs to create a new ESP32 project (
new <name> <platform>) - Wants to verify the development environment (
check) - Wants to configure CMakeLists.txt or component dependencies
- Needs help with sdkconfig or menuconfig
- Wants to add a project to the monorepo
Based on $ARGUMENTS:
- Empty or
setup→ Environment setup new <name> <platform>→ Create new projectcheck→ Verify environment
Environment Setup (Docker-Based)
All ESP-IDF builds run inside Docker containers. No local ESP-IDF installation needed.
Quick Setup
# Full environment: Docker images + dev tools
just setup-all
# Or individually:
just docker-build # Build ESP-IDF container image
just install-dev-tools # Install host-side linters/formatters
Host-Side Tools
These run natively (not in container):
esptool— for flashing firmware (pip install esptool)clang-format— C/C++ formatting (brew install clang-format)cppcheck— C/C++ linting (brew install cppcheck)ruff— Python linting (pip install ruff)pre-commit— git hooks (pip install pre-commit)
Interactive Container Shell
just docker-dev # Root-level interactive shell
just webserver::shell # Project-specific shell
Verify Environment
Run the environment check:
just check-environment
Also check:
Available serial ports:
ls -la /dev/cu.usbserial-* /dev/ttyUSB* 2>/dev/null || echo "No USB serial devices found"Docker availability:
docker --versionProject structure:
just --list
Provide a summary: Docker status, serial ports, projects found, missing dependencies.
If issues found:
- Missing Docker → "Install Docker to build ESP-IDF projects"
- No serial ports → "Connect your ESP32 device via USB"
- Missing tools → "Run
just install-dev-tools"
Creating New Projects
Supported Platforms
esp32— ESP-IDF based ESP32 projectesp32-cam— ESP32-CAM specific projectarduino— Arduino platform projectstm32— STM32 platform project
ESP32/ESP32-CAM Structure
packages/<domain>/$name/
├── justfile
├── CMakeLists.txt
├── sdkconfig.defaults
├── version.txt
├── main/
│ ├── CMakeLists.txt
│ └── main.c
└── README.md
Justfile (import shared config)
# Project Name
# Run `just --list` to see available recipes
import '../../../tools/esp32.just'
project_dir := "packages/<domain>/project-name"
port := env("PORT", _detected_serial) # or _detected_s3 for ESP32-S3
target := "esp32" # or "esp32s3"
default:
@just --list
[group: "build"]
build:
#!/usr/bin/env bash
set -euo pipefail
echo "Building project-name..."
{{container_cmd}} compose -f {{compose_file}} run --rm \
-w /workspace/{{project_dir}} \
esp-idf \
bash -c "idf.py set-target {{target}} && idf.py build"
Root CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(project-name)
Main Component CMakeLists.txt
idf_component_register(
SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES driver nvs_flash esp_wifi
)
sdkconfig.defaults
CONFIG_IDF_TARGET="esp32"
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_SINGLE_APP=y
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
Arduino Structure
packages/arduino-projects/$name/
├── src/
│ └── main.cpp
├── include/
├── lib/
├── platformio.ini
└── README.md
STM32 Structure
packages/stm32-projects/$name/
├── src/
│ └── main.c
├── include/
├── Makefile
└── README.md
Adding to the Monorepo
- Place project in
packages/<domain>/<name>/ - Create justfile with
import '../../../tools/esp32.just' - Register as module in root justfile:
mod name 'packages/<domain>/<name>' - Test:
just name::build
Component Management
IDF Component Manager
Create idf_component.yml in component directory:
dependencies:
espressif/led_strip: "^2.0.0"
Local Components
Place in project's components/ directory.
Common Configuration Tasks
Menuconfig (runs in container)
just webserver::menuconfig
just xbox::menuconfig
Steps for New Project
- Create directory structure for the specified platform
- Generate template files with proper boilerplate
- Add project to root justfile as
mod - Print next steps for the user
Best Practices
- Use sdkconfig.defaults — Don't commit generated sdkconfig
- Import tools/esp32.just — Don't duplicate container_cmd, require-port, etc.
- Minimal dependencies — Only include REQUIRES you actually use
- Document GPIO usage — Create WIRING.md with
/wiring-doc