Boards and ports
Find attached boards, name them, bind a project to one, and pick the port and baud rate.
With one board attached you never name a port. This page is for everything else: finding boards, telling several apart, and pinning a project to the right one.
List attached boards
devices lists the serial ports with a dev board on them. Each row has the port, the USB serial interface and the board's name if you gave it one:
| Interface | USB vendor id |
|---|---|
| native USB (the chip's own USB serial/JTAG) | 303A |
| CP210x bridge | 10C4 |
| CH34x bridge | 1A86 |
| FTDI bridge | 0403 |
| PL2303 bridge | 067B |
Ports with any other vendor id are left out. --all lists every serial port, including the Bluetooth and debug-console ports macOS has built in. On macOS espx lists only the /dev/cu.* device of each port, never its /dev/tty.* twin.
--json prints the ports as one document, with the USB vendor and product ids, serial number, manufacturer and product of each. See JSON events.
Identify the chip
--probe runs espflash board-info on every port and adds the chip to each row, or unknown with the error. This connects to and resets every board listed. Plain espx devices only lists ports and touches nothing.
For one board, espx info prints its chip, revision, crystal, flash size, features and MAC address. It resets the board too.
Watch boards come and go
--watch keeps running and prints attached and detached as boards are plugged in and unplugged, until Ctrl+C. With --json each change is one event per line. It cannot be combined with --probe or --all.
Board ids
espx keys every physical board on its id: the USB serial number when the port reports one, else the port path. On native-USB chips the serial number is the chip's MAC address, so it stays the same across ports and replugs. Names, [board] id bindings, agent policies and leases all use this id, and ids compare without regard to case.
espx devices --json shows the serial number as usb.serial_number. A port without one has its path as its id.
Name a board
boards name takes the board's id, its current port or its current name, and writes the name to ~/.espx/boards.toml:
Names are unique, at most 64 characters of ASCII letters, digits, -, _ and ., starting with a letter or digit. espx devices then shows bench-c6 next to the port, and every --port flag accepts it. espx rewrites the file when it saves a name, so comments you add by hand do not survive.
How espx picks a board
flash, run and monitor pick their board in this order:
- The
--portflag: a port path, a board id or a name. [board] idin the project'sespx.toml.[connection] serialin the project'sespflash_ports.toml.- The single connected board.
A value matches an attached board by id, by port or by name. A bound board that is not connected is an error (board_not_attached), never a quiet switch to another board. With no board at all, or several and nothing chosen, espx stops with port_required and lists the candidates by name.
The order also decides which board [board] id affects. It is the board flash and run write to and monitor reads, not only the board an agent may touch.
erase and info take a plain serial port in --port and leave the choice to espflash, unless another espx process holds the boards; then they resolve the board the same way and borrow it.
Bind a project to a board
espx.toml sits next to the project's Cargo.toml. Its [board] table names the board the project flashes by default and the speed to flash it at:
espx new <name> --board-id <id> writes the [board] section for you. The same file holds the [agent] policy, described in Agent policy. An unknown key is an error that names the file, the line and the key.
Pin a port
espflash_ports.toml is espflash's own file. espx reads it as step 3 above and passes the chosen port to espflash:
espx new <name> --port <port> writes it. A port path changes when you plug the board into another USB socket, so prefer [board] id when the board has a serial number.
Baud rates
There are two speeds. The flashing speed is how fast espflash talks to the bootloader. The monitor speed is the firmware's UART rate.
| Speed | Set by, strongest first |
|---|---|
Flashing (flash, run) | --baud on flash, then [board] baud in espx.toml, then espflash's own ESPFLASH_BAUD, baudrate in espflash.toml, or its default |
Monitor (monitor, run, flash --monitor) | --baud on monitor, then MONITOR_BAUD, then 115200 |
When the bootloader does not answer, espx retries the flash once at 115200 by itself. espflash.toml can also hold a [flash] table with the flash mode, size and frequency; espx reads its size for the partition check.
Environment variables
| Variable | Read by | Effect |
|---|---|---|
MONITOR_BAUD | espx and espflash | The monitor speed when --baud is not given |
ESPFLASH_BAUD | espflash | The flashing speed when neither --baud nor [board] baud is set |
ESPFLASH_PORT | espflash | The port when espx leaves the choice to espflash: erase and info without --port, and flash -i |
espx's own board selection does not read ESPFLASH_PORT. When espx picks a board it passes the port to espflash explicitly, which overrides the variable.
Driver warnings
On macOS a WCH CH34x or CH9102 bridge without WCH's own driver runs on Apple's built-in serial driver. The port shows up as /dev/cu.usbmodem… instead of /dev/cu.wchusbserial…. That driver corrupts large writes: the monitor reads fine, but every flash fails. espx spots the pairing from the port alone and warns on stderr:
espx devices, espx doctor, the MCP devices tool and the desktop app all show it, and --json carries it as the port's warning. Install WCH's CH34x driver and turn it on in System Settings > General > Login Items & Extensions > Driver Extensions, or plug the cable into the board's native USB port (labelled USB on ESP32-S3 DevKits).
Board models
espx also knows a few dev board models and their pins:
devices names a model only when a board's USB ids identify exactly one. Native USB (303A:1001) and the generic bridges never do, because every board with them reports the same ids. The Chips and boards reference has the table.