1. Set up the toolchain
Recommended: set it up by hand. You install each piece yourself, so you know what it is and where it lives.
You install four things: ESP-IDF (the toolchain for the ESP32-S3), the CrossPad project, a settings file for CP Tools, and crosspad-hil (the tool that talks to the board). CrossPad needs ESP-IDF 5.5.4 or a newer 5.5.x (tested: v5.5.5; 6.x is not supported).
CP Tools is CrossPad’s command-line helper: it installs and removes apps, checks your setup and updates the board.
It comes with the project as tools/app_manager.py, which downloads the CP Tools code from CrossPad/crosspad-apps the first time it runs.
These commands are for Ubuntu and Debian. Run them in one terminal, top to bottom. You can run a block again if it was interrupted.
-
Install the packages ESP-IDF and the tools need.
Terminal window sudo apt-get updatesudo env DEBIAN_FRONTEND=noninteractive apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0python3 --versionYou should see:
Pythonfollowed by version 3.10 or newer, for examplePython 3.12.3.If not: apt-get install fails or a package is not found, or python3 is missing or too old
-
Choose the folder for CrossPad’s ESP-IDF. It is ~/esp/esp-idf. If that folder already holds another ESP-IDF version, CrossPad’s copy goes next to it in ~/esp/esp-idf-v5.5, and your other projects keep theirs. The last two lines save the choice in
~/.bashrcfor new terminals, once.Terminal window CROSSPAD_IDF_DIR=~/esp/esp-idfif [ -d "$CROSSPAD_IDF_DIR" ] && [ "$(git -C "$CROSSPAD_IDF_DIR" describe --tags 2>/dev/null)" != "v5.5.5" ]; thenCROSSPAD_IDF_DIR=~/esp/esp-idf-v5.5fiecho "CrossPad ESP-IDF folder: $CROSSPAD_IDF_DIR"line="export CROSSPAD_IDF_DIR=$CROSSPAD_IDF_DIR"grep -qxF "$line" ~/.bashrc 2>/dev/null || echo "$line" >> ~/.bashrcYou should see:
CrossPad ESP-IDF folder:and the full path of ~/esp/esp-idf, or of ~/esp/esp-idf-v5.5 if you already had another version.If not: CrossPad ESP-IDF folder shows the side-by-side folder
-
Download ESP-IDF v5.5.5. This takes a few minutes. If the folder already holds v5.5.5, the block skips the download.
Terminal window if [ "$(git -C "$CROSSPAD_IDF_DIR" describe --tags 2>/dev/null)" != "v5.5.5" ]; thenmkdir -p "$(dirname "$CROSSPAD_IDF_DIR")"git -c advice.detachedHead=false clone --depth 1 --branch v5.5.5 --recursive --shallow-submodules https://github.com/espressif/esp-idf.git "$CROSSPAD_IDF_DIR"figit -C "$CROSSPAD_IDF_DIR" describe --tagsYou should see:
v5.5.5If not: ESP-IDF download fails
-
Install the ESP-IDF tools for the ESP32-S3. This takes about 10 minutes the first time. The first lines make this terminal forget any other ESP-IDF it has loaded (its variables and its tools on PATH), so that version cannot get in the way.
Terminal window unset IDF_PATH IDF_PYTHON_ENV_PATHPATH=$(printf %s "$PATH" | tr : '\n' | grep -v -e /.espressif/ -e /esp-idf | paste -sd: -)IDF_TOOLS_PATH=~/.espressif "$CROSSPAD_IDF_DIR/install.sh" esp32s3You should see:
All done! You can now run:near the end.If not: ESP-IDF tools install fails
-
Load ESP-IDF into this terminal and check the version. Run the first line again in every new terminal.
Terminal window . "$CROSSPAD_IDF_DIR/export.sh"idf.py --versionYou should see:
ESP-IDF v5.5.5If not: wrong ESP-IDF version is active
-
Let your user open USB serial ports. Then log out and back in once (or restart) before you flash the board.
Terminal window sudo usermod -aG dialout $USERYou should see: after you log in again,
groupslistsdialout. -
Download the CrossPad project with its submodules. If the project folder is already there, the block skips the clone and only fills in the submodules. Until the project is public, the clone needs access to the CrossPad organisation on GitHub (see the caution at the top of the page).
Terminal window [ -d ~/CrossPad/.git ] || git clone --branch main https://github.com/CrossPad/platform-idf.git ~/CrossPadgit -C ~/CrossPad submodule update --init --recursivegit -C ~/CrossPad submodule status | grep -c '^-' || trueYou should see:
0on the last line (no submodule left out).If not: project clone fails
-
Record CrossPad’s ESP-IDF for CP Tools. CP Tools uses the ESP-IDF loaded in its terminal; where none is loaded, it reads this file. The one-line installer writes the same file.
Terminal window printf '{"idf_path": "%s", "idf_tools_path": "%s"}\n' "$CROSSPAD_IDF_DIR" ~/.espressif > ~/CrossPad/crosspad.local.jsoncat ~/CrossPad/crosspad.local.jsonYou should see: one line with
"idf_path"set to your ESP-IDF folder and"idf_tools_path"set to the full path of ~/.espressif.If not: CP Tools uses the wrong ESP-IDF
-
Install crosspad-hil in a virtual environment inside the project. The flash script uses it to detect your board, and the smoke test in 4. Check it works runs on it.
Terminal window python3 -m venv ~/CrossPad/.venv~/CrossPad/.venv/bin/pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"~/CrossPad/.venv/bin/crosspad-hil --versionYou should see:
crosspad-hil 1.6.0(or newer).If not: crosspad-hil install fails
-
Install the Apple command line tools and Homebrew. Skip this if you have both.
Terminal window xcode-select --installA window asks to install the tools. Click Install and wait. Then install Homebrew with the command on brew.sh.
You should see:
xcode-select -pprints a folder, andbrew --versionprintsHomebrewand a version. -
Install the packages ESP-IDF and the tools need.
Terminal window brew install git cmake ninja dfu-util python3python3 --versionYou should see:
Pythonfollowed by version 3.10 or newer, for examplePython 3.12.3.If not: xcode-select or brew is missing or fails, or python3 is missing or too old
-
Choose the folder for CrossPad’s ESP-IDF. It is ~/esp/esp-idf. If that folder already holds another ESP-IDF version, CrossPad’s copy goes next to it in ~/esp/esp-idf-v5.5. The last two lines save the choice in
~/.zshrcfor new terminals, once.Terminal window CROSSPAD_IDF_DIR=~/esp/esp-idfif [ -d "$CROSSPAD_IDF_DIR" ] && [ "$(git -C "$CROSSPAD_IDF_DIR" describe --tags 2>/dev/null)" != "v5.5.5" ]; thenCROSSPAD_IDF_DIR=~/esp/esp-idf-v5.5fiecho "CrossPad ESP-IDF folder: $CROSSPAD_IDF_DIR"line="export CROSSPAD_IDF_DIR=$CROSSPAD_IDF_DIR"grep -qxF "$line" ~/.zshrc 2>/dev/null || echo "$line" >> ~/.zshrcYou should see:
CrossPad ESP-IDF folder:and the full path of ~/esp/esp-idf, or of ~/esp/esp-idf-v5.5 if you already had another version.If not: CrossPad ESP-IDF folder shows the side-by-side folder
-
Download ESP-IDF v5.5.5. If the folder already holds v5.5.5, the block skips the download.
Terminal window if [ "$(git -C "$CROSSPAD_IDF_DIR" describe --tags 2>/dev/null)" != "v5.5.5" ]; thenmkdir -p "$(dirname "$CROSSPAD_IDF_DIR")"git -c advice.detachedHead=false clone --depth 1 --branch v5.5.5 --recursive --shallow-submodules https://github.com/espressif/esp-idf.git "$CROSSPAD_IDF_DIR"figit -C "$CROSSPAD_IDF_DIR" describe --tagsYou should see:
v5.5.5If not: ESP-IDF download fails
-
Install the ESP-IDF tools for the ESP32-S3.
Terminal window unset IDF_PATH IDF_PYTHON_ENV_PATHPATH=$(printf %s "$PATH" | tr : '\n' | grep -v -e /.espressif/ -e /esp-idf | paste -sd: -)IDF_TOOLS_PATH=~/.espressif "$CROSSPAD_IDF_DIR/install.sh" esp32s3You should see:
All done! You can now run:near the end.If not: ESP-IDF tools install fails
-
Load ESP-IDF into this terminal and check the version. Run the first line again in every new terminal.
Terminal window . "$CROSSPAD_IDF_DIR/export.sh"idf.py --versionYou should see:
ESP-IDF v5.5.5If not: wrong ESP-IDF version is active
-
Download the CrossPad project with its submodules. macOS needs no USB permission step. If the project folder is already there, the block skips the clone. Until the project is public, the clone needs access to the CrossPad organisation on GitHub (see the caution at the top of the page).
Terminal window [ -d ~/CrossPad/.git ] || git clone --branch main https://github.com/CrossPad/platform-idf.git ~/CrossPadgit -C ~/CrossPad submodule update --init --recursivegit -C ~/CrossPad submodule status | grep -c '^-' || trueYou should see:
0on the last line.If not: project clone fails
-
Record CrossPad’s ESP-IDF for CP Tools. CP Tools uses the ESP-IDF loaded in its terminal; where none is loaded, it reads this file.
Terminal window printf '{"idf_path": "%s", "idf_tools_path": "%s"}\n' "$CROSSPAD_IDF_DIR" ~/.espressif > ~/CrossPad/crosspad.local.jsoncat ~/CrossPad/crosspad.local.jsonYou should see: one line with
"idf_path"set to your ESP-IDF folder and"idf_tools_path"set to the full path of ~/.espressif.If not: CP Tools uses the wrong ESP-IDF
-
Install crosspad-hil in a virtual environment inside the project.
Terminal window python3 -m venv ~/CrossPad/.venv~/CrossPad/.venv/bin/pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"~/CrossPad/.venv/bin/crosspad-hil --versionYou should see:
crosspad-hil 1.6.0(or newer).If not: crosspad-hil install fails
Use PowerShell (not as administrator). Run everything in one window, top to bottom. Folder paths must not contain spaces.
-
Allow scripts in this PowerShell window. ESP-IDF’s environment script needs it. This only affects the current window.
Terminal window Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -ForceYou should see: no output.
-
Install Git and Python for your user, then reload the PATH in this window.
Terminal window winget install --id Git.Git --exact --silent --scope user --accept-package-agreements --accept-source-agreementswinget install --id Python.Python.3.12 --exact --silent --scope user --accept-package-agreements --accept-source-agreements$env:Path = [Environment]::GetEnvironmentVariable("Path", "User") + ";" + [Environment]::GetEnvironmentVariable("Path", "Machine")git config --global core.longpaths truegit --versionpython --versionYou should see:
git version 2.and a number, thenPythonfollowed by version 3.10 or newer, for examplePython 3.12.8. If winget says a package is already installed, that is fine. -
Choose the folder for CrossPad’s ESP-IDF. It is C:\CrossPad\esp-idf. If that folder already holds another ESP-IDF version, CrossPad’s copy goes next to it in C:\CrossPad\esp-idf-v5.5. The
SetEnvironmentVariableline saves the choice for new windows.Terminal window $env:CROSSPAD_IDF_DIR = "C:\CrossPad\esp-idf"if ((Test-Path $env:CROSSPAD_IDF_DIR) -and ((git -C $env:CROSSPAD_IDF_DIR describe --tags) -ne "v5.5.5")) {$env:CROSSPAD_IDF_DIR = "C:\CrossPad\esp-idf-v5.5"}[Environment]::SetEnvironmentVariable("CROSSPAD_IDF_DIR", $env:CROSSPAD_IDF_DIR, "User")"CrossPad ESP-IDF folder: $env:CROSSPAD_IDF_DIR"You should see:
CrossPad ESP-IDF folder: C:\CrossPad\esp-idf, or C:\CrossPad\esp-idf-v5.5 if you already had another version.If not: CrossPad ESP-IDF folder shows the side-by-side folder
-
Download ESP-IDF v5.5.5. This takes a few minutes. If the folder already holds v5.5.5, the block skips the download.
Terminal window if (-not ((Test-Path $env:CROSSPAD_IDF_DIR) -and ((git -C $env:CROSSPAD_IDF_DIR describe --tags) -eq "v5.5.5"))) {New-Item -ItemType Directory -Force (Split-Path $env:CROSSPAD_IDF_DIR) | Out-Nullgit -c advice.detachedHead=false clone --depth 1 --branch v5.5.5 --recursive --shallow-submodules https://github.com/espressif/esp-idf.git $env:CROSSPAD_IDF_DIR}git -C $env:CROSSPAD_IDF_DIR describe --tagsYou should see:
v5.5.5If not: ESP-IDF download fails
-
Install the ESP-IDF tools for the ESP32-S3. This takes about 15 minutes the first time. The first lines make this terminal forget any other ESP-IDF it has loaded (its variables and its tools on PATH), so that version cannot get in the way.
Terminal window Remove-Item Env:IDF_PATH, Env:IDF_PYTHON_ENV_PATH -ErrorAction SilentlyContinue$env:Path = ($env:Path -split ';' | Where-Object { $_ -notmatch '\\\.espressif\\|\\esp-idf' }) -join ';'$env:IDF_TOOLS_PATH = "C:\CrossPad\.espressif"& "$env:CROSSPAD_IDF_DIR\install.bat" esp32s3You should see:
All done! You can now run:near the end.If not: ESP-IDF tools install fails
-
Load ESP-IDF into this window and check the version.
Terminal window . "$env:CROSSPAD_IDF_DIR\export.ps1"idf.py --versionYou should see:
ESP-IDF v5.5.5If not: wrong ESP-IDF version is active
-
Download the CrossPad project with its submodules. Windows has the USB drivers built in, so there is no permission step. If the project folder is already there, the block skips the clone. Until the project is public, the clone needs access to the CrossPad organisation on GitHub (see the caution at the top of the page).
Terminal window if (-not (Test-Path C:\CrossPad\firmware\.git)) { git clone --branch main https://github.com/CrossPad/platform-idf.git C:\CrossPad\firmware }git -C C:\CrossPad\firmware submodule update --init --recursive(git -C C:\CrossPad\firmware submodule status | Select-String '^-').CountYou should see:
0on the last line.If not: project clone fails
-
Record CrossPad’s ESP-IDF for CP Tools. CP Tools uses the ESP-IDF loaded in its window; where none is loaded, it reads this file.
Terminal window @{ idf_path = $env:CROSSPAD_IDF_DIR; idf_tools_path = "C:\CrossPad\.espressif" } | ConvertTo-Json | Set-Content -Encoding ascii C:\CrossPad\firmware\crosspad.local.jsonGet-Content C:\CrossPad\firmware\crosspad.local.jsonYou should see:
"idf_path"set to your ESP-IDF folder and"idf_tools_path"set to C:\CrossPad\.espressif. JSON shows each backslash twice.If not: CP Tools uses the wrong ESP-IDF
-
Install crosspad-hil in a virtual environment inside the project.
Terminal window python -m venv C:\CrossPad\firmware\.venvC:\CrossPad\firmware\.venv\Scripts\pip install "crosspad-hil[all] @ git+https://github.com/CrossPad/crosspad-hil"C:\CrossPad\firmware\.venv\Scripts\crosspad-hil --versionYou should see:
crosspad-hil 1.6.0(or newer).If not: crosspad-hil install fails
Optional Several ESP-IDF versions side by side
Each ESP-IDF version lives in its own folder, and each terminal uses one of them. Say your other projects use an older ESP-IDF in ~/esp/esp-idf. After step 1 you have:
~/esp/esp-idf the older version, for your other projects (untouched)~/esp/esp-idf-v5.5 v5.5.5 for CrossPad (CROSSPAD_IDF_DIR points here)~/.espressif the tools of both, one subfolder per versionOn Windows the folders are C:\CrossPad\esp-idf and C:\CrossPad\esp-idf-v5.5. CrossPad’s tools go to C:\CrossPad\.espressif, apart from the tools of other versions.
A terminal uses the ESP-IDF whose export script it loaded last. To see which one is active, run idf.py --version. Two terminals can use two versions at the same time:
# Terminal 1: your other project. ~/esp/esp-idf/export.shidf.py --version # the older version
# Terminal 2: CrossPad. "$CROSSPAD_IDF_DIR/export.sh"idf.py --version # ESP-IDF v5.5.5# Terminal 1: your other project. ~/esp/esp-idf/export.shidf.py --version # the older version
# Terminal 2: CrossPad. "$CROSSPAD_IDF_DIR/export.sh"idf.py --version # ESP-IDF v5.5.5# Window 1: your other project. C:\CrossPad\esp-idf\export.ps1idf.py --version # the older version
# Window 2: CrossPad$env:IDF_TOOLS_PATH = "C:\CrossPad\.espressif". "$env:CROSSPAD_IDF_DIR\export.ps1"idf.py --version # ESP-IDF v5.5.5If your shell profile loads another ESP-IDF at start-up, load CrossPad’s export script again in that terminal: the last one loaded wins.
Which ESP-IDF do the CrossPad tools use? python3 tools/app_manager.py (CP Tools) uses the one loaded in its terminal, and reads crosspad.local.json from step 8 only when none is loaded. The installer’s cptools and crosspad-idf commands always load CrossPad’s ESP-IDF first, whatever your terminal has.
If you installed ESP-IDF with Espressif’s installer (EIM) or the VS Code extension, they record their versions in esp_idf.json, and the one-line installer reads that file to find them. More, including how the installer picks among several versions: Use several ESP-IDF versions.
Optional Use an ESP-IDF you already have
An ESP-IDF you installed earlier (Espressif’s installer, the VS Code extension, or by hand) works if it is 5.5.x and at least 5.5.4. Check it: load its export script and run idf.py --version.
In the “Choose the folder” step, point CROSSPAD_IDF_DIR at that folder instead of running the if block:
CROSSPAD_IDF_DIR=/path/to/your/esp-idfline="export CROSSPAD_IDF_DIR=$CROSSPAD_IDF_DIR"grep -qxF "$line" ~/.bashrc 2>/dev/null || echo "$line" >> ~/.bashrcCROSSPAD_IDF_DIR=/path/to/your/esp-idfline="export CROSSPAD_IDF_DIR=$CROSSPAD_IDF_DIR"grep -qxF "$line" ~/.zshrc 2>/dev/null || echo "$line" >> ~/.zshrc$env:CROSSPAD_IDF_DIR = "C:\path\to\your\esp-idf"[Environment]::SetEnvironmentVariable("CROSSPAD_IDF_DIR", $env:CROSSPAD_IDF_DIR, "User")Then skip the download step. Still run the tools install step: it only adds what is missing. In the CP Tools step, write the tools folder that ESP-IDF was installed with as idf_tools_path.
Optional Claude + crosspad-mcp
crosspad-mcp is an MCP server for Claude Code. It gives Claude tools to build the firmware, flash the board, run the simulator and run crosspad-hil tests, so you can ask for “build, flash and smoke-test” in one sentence. It needs Node.js 18 or newer and the crosspad-hil you installed above. To register it with Claude Code, follow From Claude Code on the Test on hardware (HIL) page.
Next: 2. Build the firmware