# 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

```sh
espx devices
```

`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](https://www.espx.dev/docs/reference/events#data-documents).

### Identify the chip

```sh
espx devices --probe
```

`--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

```sh
espx devices --watch
espx devices --watch --json
```

`--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

```sh
espx boards name /dev/cu.usbmodem2101 bench-c6
espx devices
```

`boards name` takes the board's id, its current port or its current name, and writes the name to `~/.espx/boards.toml`:

```toml title="~/.espx/boards.toml"
[names]
"58:8C:81:53:AD:2C" = "bench-c6"
```

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:

1. The `--port` flag: a port path, a board id or a name.
2. `[board] id` in the project's `espx.toml`.
3. `[connection] serial` in the project's `espflash_ports.toml`.
4. 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:

```toml title="espx.toml"
[board]
id = "58:8C:81:53:AD:2C"   # a board id, a name or a port
baud = 460800              # flashing speed when --baud is not given
```

`espx new <name> --board-id <id>` writes the `[board]` section for you. The same file holds the `[agent]` policy, described in [Agent policy](https://www.espx.dev/docs/agents/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:

```toml title="espflash_ports.toml"
[connection]
serial = "/dev/cu.usbmodem101"
```

`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](https://www.espx.dev/docs/cli/build-and-flash#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:

```text
warn: /dev/cu.usbmodem1101: this CH34x bridge runs on macOS's built-in serial driver (…), which corrupts large writes, so flashing will most likely fail. …
```

`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:

```sh
espx boards                  # id, chip and name of each known board
espx board xiao-esp32c6      # LED, BOOT button, UART pins, USB ids, documentation
```

`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](https://www.espx.dev/docs/reference/chips#boards) reference has the table.

## Related

- [Build and flash](https://www.espx.dev/docs/cli/build-and-flash)
- [Configuration](https://www.espx.dev/docs/reference/configuration)
- [`espx devices` in the command reference](https://www.espx.dev/docs/cli/commands#espx-devices)
