Skip to content

RaftCLI

Rob Dobson edited this page Oct 26, 2026 · 10 revisions

Raft command-line interface (CLI)

The RaftCLI project installs an executable program on your machine called raft. It is partly a wrapper around the Espressif ESP IDF build tools and also provides a consistent developer experience for scaffolding, building, flashing, serial monitoring, remote logging and OTA update of Raft applications, and for managing the files and device type records on a running device over HTTP, WebSocket, USB serial or BLE.

What RaftCLI does

RaftCLI handles the following tasks so you don't have to interact with ESP IDF directly:

  • SysType resolution — determines which SysType to build (from the -s flag, a previously recorded choice, or the first SysType folder found)
  • Build method selection — automatically chooses Docker or native ESP IDF, with options to override
  • ESP IDF version matching — reads the required ESP IDF version from the project's Dockerfile and locates a matching local installation for native builds
  • Build invocation — calls idf.py -B build/<SysType> build with the correct environment
  • Flash — uses esptool for flashing
  • Serial Monitor provides a built-in serial monitor with command history and auto-reconnect
  • Remote Logging provides logging and command handling over an IP (WiFi, etc) link directly to the terminal
  • OTA update — sends firmware to a device over WiFi/Ethernet
  • Files on a device — lists, downloads, uploads and mirrors files (including the app's FSImage) on a running device, over HTTP, WebSocket, USB serial or BLE - see Devices
  • Device type records — chooses the records compiled into the firmware and builds, pushes and checks the device type file on a running device
  • Local library checkouts — fetches Raft libraries into a project's raftdevlibs/ folder for in-place development

For a detailed description of each build stage that happens after RaftCLI invokes the build, see Raft Build Process.

Installation

RaftCLI is written in Rust and installed via:

cargo install raftcli

You will also need either Docker (for containerised builds) or a locally installed ESP IDF (for native builds). For flashing, install esptool:

python3 -m pip install esptool

Commands

Command Alias Description
raft new <folder> raft n Scaffold a new Raft app - see Creating an app
raft detect The chip, flash size and PSRAM of a connected board (esptool)
raft build raft b Build the firmware
raft run raft r Build, flash and monitor
raft flash raft f Flash without rebuilding (or from a browser: the Raft Flasher, below)
raft monitor raft m Serial monitor
raft debug <args> raft d Debug over IP
raft ota <ip> raft o Over-the-air firmware update
raft fs <command> <device> Manage files on a running device: list (ls), df, get, put, cat, delete (rm), sync, format; raft fs <device> on its own mirrors the built FSImage - see Devices
raft ports raft p List serial ports
raft ble scan List the Raft devices in BLE range (name, address, signal strength)
raft esptool <args> raft e Run esptool directly
raft devtypes raft dt Manage device type records: the selection, checks, and device type files on a running device - see Selecting Device Types
raft libs <command> raft l Local development libraries in raftdevlibs/: status (default), fetch, pull, link, unlink, remove
raft update-project Bring the CMakeLists.txt of an app made by an older raft new up to date; with --set <key=value>, change one of raft new's answers and update the files made from it

Use --no-docker to build with a local ESP IDF instead of Docker. Use -s <SysType> to select a specific SysType.

Creating an app

raft new asks for the project name, then the hardware, in one of four ways:

  • detected from a connected board (esptool reports the chip, flash size and PSRAM in the chip) - the board on -p/--port, or the most likely serial port (under WSL through Windows raft.exe, or with -n a port attached to WSL);
  • a dev board from a list, which also gives the I2C connector's pins;
  • an Espressif module by its ordering code (e.g. ESP32-S3-WROOM-1-N8R2: 8 MB flash, 2 MB PSRAM);
  • the chip, with safe defaults if you don't know the rest.

Then:

  • wireless connectivity: WiFi and BLE, WiFi, BLE or none;
  • OTA updates: two app slots, or one larger one;
  • I2C and sensors: RaftCore's common or extended named sets, all, none built in, or no I2C;
  • decoding of sensors added later from a device type file;
  • a user SysMod.

A summary shows the partition table and an estimate of the app's size before anything is written.

The answers are saved in the app as .raftnew.json:

  • raft new --answers <file> makes the same app;
  • raft update-project --set flash_size=8 (for example) changes an answer and updates the files that haven't been edited.

The questions, their --set keys and the size of each choice are in RaftCLI's README.

Without WiFi (connectivity ble or none), add_compile_definitions(RAFT_NO_NETWORKING) in the app's features.cmake leaves out:

  • the networking SysMods (NetMan, CommandSocket, MQTTMan) and the network loggers;
  • the WiFi driver, IP stack and mDNS.

That saves about 700 KB on an ESP32-S3 (RaftCore 1.64.0 and RaftSysMods 1.28.0 and later).

Devices

raft fs and raft devtypes reach a running device over any of its connections. The device is named as:

Device Connection
192.168.86.52, MyDevice.local, http://host[:port] HTTP: the device's REST API
ws://host[:port][/path] The device's WebSocket (path default /ws), using RICREST
serial:<port>[@baud], e.g. serial:COM4 The device's USB serial console, using RICREST alongside the log output (SerialConsole). serial: on its own picks the port
ble:<name, name prefix or address> The device's RICREST BLE service (BLEManager). ble: on its own uses the only Raft device in range

The device is the first argument, or comes from -d/--device or the RAFT_DEVICE environment variable:

raft fs ls 192.168.86.52 -r                       # list every file
raft fs get serial:COM4 config.json               # download
raft fs put ws://MyDevice.local settings.json     # upload (checked with the device's CRC of the file)
raft fs sync ble:Axiom018 ./webui /web --hash     # mirror a folder
raft fs MyDevice.local --dry-run                  # mirror the project's built FSImage
RAFT_DEVICE=serial:COM4 raft devtypes status
  • Uploads use the file upload protocol over WebSocket, serial and BLE, and an HTTP multipart POST over HTTP. Downloads use filesection requests (FileManager) on every connection.
  • --fs sd works with a device's SD card (default local).
  • Over serial the port is shared with the log: --show-log shows it, and raft monitor can't have the port open at the same time.
  • In WSL, serial and BLE devices are handed to the Windows raft.exe (WSL has no USB serial ports or Bluetooth); -n uses WSL's own ports.
  • Rough speeds with an ESP32-S3: HTTP and WebSocket 20-50 KB/s, USB serial 10-16 KB/s up and about 40 KB/s down, BLE 15-25 KB/s up and 5-8 KB/s down.

BLE

raft ble scan lists the Raft devices in range (those advertising a RICREST BLE service). BLE has been tested on Windows only so far. Connections are made with btleplug; RaftCLI:

  • writes the response characteristic's CCCD as notify after subscribing (older firmware doesn't count an indicate-only subscription), and sizes its writes from the MTU;
  • remembers each device's address on Windows, so later connections skip the scan;
  • always sends bledisconnect when it finishes, including on Ctrl-C, because Windows otherwise keeps the link up after a program exits. If RaftCLI is killed, Windows ends the link about 25 s later; devices with RaftSysMods 1.26 or later keep advertising meanwhile (BLEManager connections).

--ble-service, --ble-cmd and --ble-resp reach devices with other UUIDs, and --ble-mtu overrides the MTU.

Flashing from a browser

The Raft Flasher (raftjs apps/flasher) flashes a build over USB from Chrome or Edge, with no tools installed. Pick the project's build/<SysType> folder (or its flasher_args.json and .bin files), or give the URL of an ESP Web Tools manifest. It writes what raft flash writes, where it writes it (from flasher_args.json), and:

  • shows the app's name, version and build date, and the partition table, and checks each image fits its partition and the build is for the board's chip;
  • flashes everything, the firmware only (keeping the file system, as raft flash --no-fs), or the file system image only, optionally erasing the flash first;
  • checks each image after writing it (MD5), then restarts the board.

Writing the file system image replaces the device's files, among them its device type file and saved device settings.

Local development library checkouts

raft libs (raft l) manages a project's raftdevlibs/ folder, where the Raft build system picks up library checkouts in place of the normal GitHub fetch. A library there is either a clone made for the project or a link (symlink, or a junction on Windows) to a repo kept elsewhere.

raft l                                         # status of each library (clone or link, branch, ahead/behind, changes)
raft l fetch                                   # clone the libraries in RAFT_COMPONENTS at main, or update existing clones
raft l fetch --branch v1.44.1 --libs RaftCore  # pin a library to a tag
raft l fetch --account my-fork --libs RaftCore # fetch from a fork
raft l pull                                    # fast-forward pull every clean library
raft l link ../../raft                         # link repos from a folder (relative to the app folder)
raft l unlink                                  # remove links (the linked repos aren't changed)
raft l remove --libs RaftI2C                   # delete a clone (refused if it holds local work, unless --force)

fetch stops before updating a clone with uncommitted changes unless --force is given, and never changes linked repos. After a library is added to or removed from raftdevlibs, the next raft build recreates the SysType's build folder.

See Local Raft Development Libraries and the Library Developer Guide for what raftdevlibs/ does at build time.

Persistent settings

Several options are remembered between invocations — -p serial port, -b monitor baud, -f flash baud, -v vendor ID, and --no-fs/--fs — saved to build/raft.info after a successful run. Specify the option again to override the saved value.

Full documentation including all command options is available in the RaftCLI README.

Clone this wiki locally