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:

  1. Download the library zip from GitHub/release
  2. Extract it into your libraries/ directory
  3. 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_USER is the environment variable to point at project-local libraries.
  • TFT_eSPI requires a board-specific User_Setup.h overwritten 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-index must run before installing any core.
  • There’s no incremental compile shortcut; --clean rebuilds everything each time.

#arduino #esp32 #arduino-cli #embedded #cyd