Serial Command-Line Tool
brookesia-usb controls the ESP-Brookesia USB service through the single CDC-ACM channel provided by USB Serial/JTAG. The protocol version is 1.
Install
The USB CLI requires Python 3.9 or newer and can be installed online from PyPI:
python -m pip install brookesia-usb-cli
The install command also installs the pyserial dependency. After installation, view the command help:
brookesia-usb --help
Devices and Ports
The CLI selects a port automatically by the Espressif USB Serial/JTAG device identity and verifies it with the hello command:
brookesia-usb devices
brookesia-usb status
brookesia-usb --port /dev/ttyACM0 status
The common connection options can also be specified explicitly:
brookesia-usb --port /dev/ttyACM0 --baudrate 115200 --timeout 10 status
--port: USB Serial/JTAG device path; if omitted, discover a matching ACM port.--baudrate: retained for pyserial compatibility; USB Serial/JTAG has no physical baud rate and defaults to115200.--timeout: per-read and write timeout in seconds, defaulting to10.
When multiple matching devices are present, pass --port explicitly using a path reported by devices. A single Serial/JTAG CDC configuration normally exposes only /dev/ttyACM0; the absence of /dev/ttyACM1 is expected.
Control Sessions and Security
Commands that require a control session send hello and validate protocol version 1, the serial_jtag transport, and the exclusive session state before sending goodbye on exit.
Device logs are suppressed during the control session so they cannot corrupt JSON responses or file frames. USB Serial/JTAG shares its CDC channel with flashing, JTAG debugging, and console logs; close idf.py monitor, minicom, or any other program reading the same serial device before running a command.
The USB connection is treated as a trusted physical control boundary, while protocol, path, size, checksum, and service-argument validation still apply.
Get Status
Query the USB service, transfer, and control-session status:
brookesia-usb status
brookesia-usb --port /dev/ttyACM0 status
The command prints an error and returns a non-zero status when the device is unavailable or the USB service is not running.
Call a Service Function
The call command invokes a registered Brookesia service function. Arguments must be a JSON object and must match the service schema:
brookesia-usb call Manager GetServiceNames '{}'
brookesia-usb call Manager GetServiceSchema '{"Name":"Storage"}'
brookesia-usb call SystemCore GetSystemInfo '{}'
brookesia-usb call Storage FSStat '{"Path":"/littlefs"}'
brookesia-usb call Storage FSList '{"Path":"/littlefs"}'
Use Manager.GetServiceNames and Manager.GetServiceSchema to discover available services and functions. ServiceManager validates required parameters, default values, unknown parameters, and parameter types on the device.
Functions that require a RawBuffer argument cannot be called through the JSON interface because a host pointer is not valid in device memory. Use put and install for file and package data. Calls to the Usb service itself are rejected to prevent recursion into the active USB session.
Upload a File
Upload a local file under the configured device upload root. The default upload root is /littlefs/usb and the remote path must be relative:
brookesia-usb put ./logs/session.bin logs/session.bin
brookesia-usb put ./config/device.json config/device.json --overwrite
Existing files are not overwritten by default; explicitly pass --overwrite to replace one. Absolute paths, .. path components, symbolic-link escapes, and paths outside the upload root are rejected.
The CLI calculates the file size and SHA-256 digest, sends CRC-protected binary frames, and waits for an acknowledgement after every data frame. The default frame payload is no larger than 16 KiB and the default transfer limit is 8 MiB; the device Kconfig controls the actual limits.
The device writes data to a temporary file first and commits it only after size and SHA-256 verification succeed. The temporary file is cleaned up when a transfer is interrupted.
Install an Application Package
Send a complete BPK runtime app package to the device for validation and installation:
brookesia-usb install ./build/my_app.bpk
The package is first written to the USB temporary directory. System Core then performs manifest validation, ZIP path-safety checks, staging, replacement, and rollback. The host cannot select the device-side app installation directory directly.
The CLI does not retry an installation after a disconnect or an ambiguous result. Run brookesia-usb status before retrying the command.
Abort a Transfer
Abort an active transfer by request ID:
brookesia-usb abort 42
abort is an emergency command and does not start a new control session. When request 42 is active, the device removes the temporary file and returns aborted; an unknown request ID returns a device error and a non-zero status.
Errors and Troubleshooting
The CLI returns 0 after a successful operation and 1 for transport, protocol, validation, or device errors. Common error codes include:
invalid_command: malformed JSON or unsupported operation.busy: another control session or transfer is active.bad_frame: invalid frame CRC, type, or sequence.size_mismatch/hash_mismatch: declared metadata does not match the data.path_denied: unsafe path or overwrite was not explicitly enabled.storage_full: temporary storage cannot be created or written.install_failed: System Core rejected or failed to install the package.timeout/aborted: the operation timed out or was cancelled.
If the device is not found, check the USB Serial/JTAG Type-C data cable and list system devices:
ls /dev/ttyACM*
brookesia-usb devices
After confirming that no other program owns the CDC channel, pass the device path explicitly with --port.