The ESP32 IDE
apps/ide/esp is a small window for working on an ESP32 program. It has a
folder tree, an editor, and a chip selector with a Detect button. One
Build+Flash button builds the project for the chip on the USB port, writes
it to the board, and then shows what the board prints. It is written in Pascal
and built with PXX, like the Eliah IDE,
and shares Eliah's core. The name esp is a working name.
Everything on this page was run from a checkout at 9fa9c55901 with pin v426
(compiler sha256 7b742af6f9df…) on 2026-09-25. The board steps were run on
an ESP32-S3 devkit (/dev/ttyACM0). No ESP32-C3 board has been tried; see
What is and is not proven.
What you need
-
A PXX checkout, and the GTK 3 development files that the Eliah IDE also needs.
-
ESP-IDF v6.0.1 in
~/esp/esp-idf, or whereverESP_IDF_DIRpoints. Step 1 of Getting started on the ESP32 installs it. The IDE loads ESP-IDF's environment itself, so you do not need to sourceexport.shfirst. -
Permission to open the serial port. On most Linux systems the board's port belongs to the
dialoutgroup. To check whether you are in it:id -nG | tr ' ' '\n' | grep -x dialout
If that prints nothing, add yourself with
sudo usermod -aG dialout $USER, then log out and back in. The new group only reaches programs started after you log in again.
Build and start it
espide.sh at the root of the checkout does both:
./espide.sh # opens examples/esp32
./espide.sh examples/esp32/hello-s3 # opens that folder
It builds the IDE first when the binary is missing or older than its sources
(apps/ide/esp, apps/ide/garin, lib/pcl, lib/rtl) or the pinned
compiler, which takes about ten seconds. Then it starts the IDE with your
arguments. It works from any directory. A relative folder is looked up in your
current directory first, then in the checkout, so
examples/esp32/hello-s3 works from anywhere. If you are not in the
dialout group, it prints one line saying how to fix that, and starts the
IDE anyway:
espide.sh: to use the board's serial port, run: sudo usermod -aG dialout <you> -- then log out and back in.
espide.sh: you are in the dialout group, but this login predates it: log out and back in to use the board's serial port.
The first line is for a user who is not in the group. The second is for a user who was added but has not logged in again since.
To build and run it by hand instead:
apps/ide/esp/build.sh # built: apps/ide/esp/espide
apps/ide/esp/espide examples/esp32/hello-s3
Using it
- Open a folder. Type a path in the box at the top left and press
Open, or pass the path on the command line. The tree lists its files and
subfolders, but not
build/or hidden entries. Click a file to open it in the editor. Save writes it back. - Pick the project. A project is a folder with a
CMakeLists.txtand abuild.sh, like everyexamples/esp32/<name>-<chip>folder. The IDE uses the project that holds the file or folder you clicked. So you can open all ofexamples/esp32and click into the project you want. The status line names the project and the chip it builds for: the folder's-s3,-c3or-s2suffix, or else the chip named in itsbuild.shorsdkconfig. - Detect. The IDE asks every
/dev/ttyACM*and/dev/ttyUSB*port which chip is behind it, usingesptool chip-id. This resets the board. The status line then names each board found and its port. - Chip. Leave the selector on
autoto follow the board you detected, or pickESP32-S3,ESP32-C3orESP32-S2by hand. - Build+Flash. This first saves the open file. Then it runs
tools/esp_flash.sh --project <project> --chip <chip> --port <port>, which builds with the project's ownbuild.sh. The log appears in the lower pane as the build runs. A build can take several minutes: ESP-IDF configures a project from scratch the first time, and some examples,hello-s3among them, runidf.py set-targetin theirbuild.sh, which does that on every build. After the image is written, the pane shows the board's first few seconds of output. Then it switches to the serial monitor. - Monitor. The monitor reads the port at 115200 baud and shows everything the board prints, until you press Stop. Monitor reopens it on the last board. Detect and Build+Flash close the monitor first, because they need the port themselves. The pane keeps the most recent 32 KB of output.
On the S3 devkit, hello-s3 built, flashed and printed
PXX hello from Pascal S3: i=1 to i=5. monitor-s3 flashed, and its
once-a-second reports kept arriving in the monitor pane after the flash:
# 7 mean 3858 range 3839..3876 trend flat frames 110 free 262068
# 8 mean 3859 range 3799..3879 trend flat frames 126 free 262072
# 9 mean 3859 range 3838..3879 trend flat frames 142 free 262068
When it refuses
The IDE does not guess a chip or a board. In these cases it stops and says why, word for word as below.
Chip on auto and no board found. It will not build for a default chip:
No board detected: connect an ESP32 board and press Detect, or pick the chip by hand.
A folder that is not an ESP-IDF project, such as a bare main.pas with no
CMakeLists.txt. Here the folder was called fixtures:
fixtures is not an ESP-IDF project (it has no CMakeLists.txt and build.sh): copy a project from examples/esp32 and put your main.pas or main.npy in its main/ folder.
The project and the board are different chips. Here a -c3 project met
an S3 board:
This project builds for the ESP32-C3, not the ESP32-S3: open a project for the ESP32-S3 or connect an ESP32-C3.
The selector and the board disagree. Here the selector said C3 and an S3 was plugged in:
The chip selector says ESP32-C3 but the connected board is an ESP32-S3.
No permission to open the port. Detect reports it for each port:
Detect: /dev/ttyACM0: permission denied: your user needs the dialout group (add it, then log in again)
Without clicking
Two options run the IDE unattended. The window still opens, so under a
headless session run it with xvfb-run -a.
./espide.sh --gui-smoke # opens, paints, prints GUI SMOKE OK
./espide.sh --auto examples/esp32/hello-s3 10 # detect, build+flash, monitor 10 s
--auto prints the log to standard output and ends with
ESPIDE-AUTO-COMPLETE rc=<n>. rc is 0 when the board was flashed, 1 when
the build or the flash failed, and 2 when the IDE refused, for any of the
reasons above.
The decisions behind the refusals live in apps/ide/garin/espproj.pas, and
apps/ide/test.sh tests them without opening a window. With pin v426 it
reports 202 passed, 0 failed.