Zet - How do I use arduino-cli for ESP32 development?
How do I use arduino-cli for ESP32 development?
arduino-cli is the command-line interface for Arduino development. It compiles, uploads, and manages boards/libraries without the GUI — useful for scripting, CI, and headless environments.
Quick start
# Install (macOS)
brew install arduino-cli
# Install ESP32 board support
arduino-cli core update-index
arduino-cli core install esp32:esp32@3.3.10
Project structure with local libraries
Keep libraries alongside the project (checked into version control) rather than relying on the global ~/Documents/Arduino/libraries/:
my_project/
├── MySketch.ino
├── libraries/
│ ├── TFT_eSPI/
│ ├── ESP8266Audio/
│ └── ...
└── build.sh
Point arduino-cli at your project directory:
export ARDUINO_DIRECTORIES_USER="$PWD/Arduino" # or wherever libraries/ is
arduino-cli compile --fqbn "esp32:esp32:esp32" "$SKETCH_DIR"
ARDUINO_DIRECTORIES_USER is the key. Without it, arduino-cli looks in ~/Documents/Arduino/ and won’t find your project-local libraries.
Core commands
# List connected boards
arduino-cli board list
# Compile only
arduino-cli compile --fqbn "esp32:esp32:esp32" SketchDir/
# Compile + upload in one step
arduino-cli compile --upload -p /dev/cu.usbserial-11110 \
--fqbn "esp32:esp32:esp32" SketchDir/
# With board-specific options (upload speed, partition scheme)
arduino-cli compile --upload -p /dev/cu.usbserial-11110 \
--fqbn "esp32:esp32:esp32" \
--board-options "UploadSpeed=115200,PartitionScheme=huge_app" \
SketchDir/
# Clean rebuild
arduino-cli compile --clean --fqbn "esp32:esp32:esp32" SketchDir/
Library management
arduino-cli does NOT download libraries automatically (unlike the IDE). You must:
- Download the library zip from GitHub/release
- Extract it into your
libraries/directory - Name the folder to match the library name (e.g.,
TFT_eSPI/)
# Install a library from the index (alternative to manual)
arduino-cli lib install "TFT_eSPI"
# List installed libraries
arduino-cli lib list
# Search for a library
arduino-clo lib search "ESP8266Audio"
TFT_eSPI gotcha
TFT_eSPI requires a User_Setup.h tailored to your board. The library ships with a User_Setup_Select.h that includes one of many presets. If you keep TFT_eSPI in your project’s libraries/:
# Overwrite the default setup with your board's config
cp my_custom_User_Setup.h libraries/TFT_eSPI/User_Setup.h
If the screen stays white or garbled, the User_Setup.h likely doesn’t match your board. Check #define ILI9341_2_DRIVER (or ST7789_DRIVER, etc.) and pin mappings (TFT_CS, TFT_DC, TFT_RST, TFT_BL).
Selecting the correct FQBN
# List all installed cores and their boards
arduino-cli board listall
# Common ESP32 variants
arduino-cli compile --fqbn "esp32:esp32:esp32" ... # Generic ESP32
arduino-cli compile --fqbn "esp32:esp32:esp32s3" ... # ESP32-S3
arduino-cli compile --fqbn "esp32:esp32:esp32c3" ... # ESP32-C3
Flash and RAM budgets
Use --verbose to see resource usage:
arduino-cli compile --verbose --fqbn "esp32:esp32:esp32" SketchDir/
# Look for: "Sketch uses X bytes (Y%) of program storage space"
# "Global variables use X bytes (Y%) of dynamic memory"
Build script pattern
A reusable pattern (used in the ASCII-Aquarium project):
#!/bin/bash
set -e
export ARDUINO_DIRECTORIES_USER="$PWD/Arduino"
arduino-cli compile --clean --fqbn "esp32:esp32:esp32" "$SKETCH_DIR"
arduino-cli upload -p /dev/cu.usbserial-11110 \
--fqbn "esp32:esp32:esp32" \
--board-options "UploadSpeed=115200" \
"$SKETCH_DIR"
Key takeaways
ARDUINO_DIRECTORIES_USERis the environment variable to point at project-local libraries.- TFT_eSPI requires a board-specific
User_Setup.hoverwritten inside the library folder. - ESP32 v3.3.10 is a known-good core version for CYD-based projects. Newer versions may introduce breaking changes.
arduino-cli core update-indexmust run before installing any core.- There’s no incremental compile shortcut;
--cleanrebuilds everything each time.
#arduino #esp32 #arduino-cli #embedded #cyd