baud-cli
baud-cli provides the baud command: a small serial CLI designed for coding agents and repeatable embedded-hardware debugging.
It turns the recurring one-off pyserial scripts into guarded YAML workflows with deterministic exit
codes, JSON/JSONL output, raw-byte evidence, and automatically archived logs.
Install
baud-cli requires Python 3.10 or newer. The runtime dependencies are pyserial and PyYAML;
uv is the recommended installer but is not a runtime requirement.
Quick install with an Agent prompt
Give this prompt to an Agent with shell access:
Read https://github.com/Nitmi/baud-cli and follow its README to install baud-cli for me.
For manual installation, use the detailed paths below.
Install the published command on Windows, macOS, or Linux:
uv tool install baud-cli
baud --help
Install from a checkout while developing:
uv tool install --editable .
baud --help
For development:
uv sync --extra dev
uv run baud --help
Install the Agent Skill from the public repository with the cross-agent skills CLI:
npx skills add Nitmi/baud-cli --skill baud
OpenClaw users can install the published ClawHub skill:
openclaw skills install @nitmi/baud
For development from this checkout, install or verify the bundled Skill directly:
uv tool install --editable .
uv tool update-shell
uv run python tools/install_skill.py
uv run python tools/install_skill.py --check --json
The canonical Skill source remains under skills/baud; the installer copies that source to
~/.agents/skills/baud. It refuses to overwrite a different installed copy unless --force is
explicitly supplied.
Platform support
The serial transport uses pyserial and has no OS-specific code. CI is configured for Python 3.10 and
3.13 on Windows, macOS, and Linux, including a real pyserial loop:// round trip through the CLI.
| Platform | Typical port | Notes |
|---|---|---|
| Windows | COM5 |
USB serial drivers provide the COM port. |
| macOS | /dev/cu.usbserial-* or /dev/cu.usbmodem* |
Prefer /dev/cu.* for outbound CLI sessions. |
| Linux | /dev/ttyUSB0 or /dev/ttyACM0 |
The user needs permission to open the device. |
On Linux, add the user to the serial-device group used by the distribution, commonly dialout or
uucp, then start a new login session. USB drivers, device permissions, and DTR/RTS reset wiring
remain platform and hardware concerns even though the CLI itself is portable.
Standalone Windows release
Starting with 0.1.2, tag builds produce baud-<version>-windows-x86_64.zip.
It contains a single-file baud.exe and a manifest binding its SHA-256, version,
target, and source commit. Python is not required at runtime. The tag workflow
builds twice with fixed PYTHONHASHSEED and SOURCE_DATE_EPOCH, rejects unequal
ZIP hashes, runs only baud --version, and creates GitHub artifact provenance.
It does not enumerate or open serial ports.
After a tagged candidate is attached to a GitHub Release, verify it before use:
gh attestation verify baud-0.1.2-windows-x86_64.zip `
--repo Nitmi/baud-cli `
--source-ref refs/tags/v0.1.2 `
--signer-workflow Nitmi/baud-cli/.github/workflows/binary-release.yml `
--deny-self-hosted-runners
The archive can then be pinned by Embedded Agent Toolkit's authenticated component catalog. Attestation proves repository build provenance; it is not Windows Authenticode signing and does not prove a serial device or firmware identity.
Core commands
The examples use a Windows port name; replace COM14 with the connected /dev/cu.* or /dev/tty*
device on macOS or Linux.
uv run baud list --json
uv run baud monitor --port COM14 --duration 30 --json
uv run baud send --port COM14 status --wait 2 --require-response --json
uv run baud probe --port COM14 --commands help status ? --endings crlf lf --json
uv run baud run examples/wash_test.yaml --json
probe follows the diagnostic pattern seen in real agent sessions: listen first, preserve raw bytes,
then try harmless commands with multiple line endings. It distinguishes a responsive device from a
device that transmits a startup banner but never processes PC-to-device commands.
Guarded hardware actions
A dangerous action must name successful earlier steps. The CLI refuses to load a dangerous step with no guards, and it never transmits the action if a required assertion failed:
- id: sensor_snapshot
send: sensor_i2c_status
wait: 3
expect:
contains: ["target=164"]
- id: start_wash
send: wash_start
dangerous: true
requires: [sensor_snapshot]
The complete guarded example is in examples/wash_test.yaml.
Pin the physical serial device
For unattended or safety-sensitive workflows, bind the port to its enumerated USB identity. Baud checks these fields immediately before opening the port and exits with code 4 on any mismatch:
serial:
port: COM3
baudrate: 115200
dtr: false
rts: false
expected_vid: "303A"
expected_pid: "1001"
expected_serial_number: "E0:72:A1:D4:1F:DC"
VID and PID strings are hexadecimal. Direct commands expose the same guard through
--expected-vid, --expected-pid, and --expected-serial-number. Pyserial URLs such as
loop:// continue to work when no physical identity fields are configured.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Workflow or diagnostic command completed |
| 2 | Step or guard failed |
| 3 | Assertion failed |
| 4 | Port missing, busy, disconnected, or unreadable |
| 5 | Timeout |
| 6 | Encoding or protocol error |
| 7 | Workflow configuration error |
Every active serial command closes the port through a context manager, even after an assertion or I/O
failure. By default, human-readable .log and machine-readable .jsonl artifacts are written under
logs/; use --no-log only for disposable checks.
Companion project
For Bluetooth Low Energy discovery, GATT diagnostics, notifications, guarded writes, and offline evidence workflows, see BLEA. It provides a universal Agent Plugin with a portable Skill, deterministic CLI, and local MCP server.
Metadata
Release files for baud-cli 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| baud_cli-0.1.2.tar.gz | 53.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| baud_cli-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 72.6 kB
Release files / baud_cli-0.1.2.tar.gz
| Download URL | baud_cli-0.1.2.tar.gz |
|---|---|
| Size | 53.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a6488cd0cc94c9f7fe61f6692a15bec7cc5613f2806a35880a7acc71f918df10
|
|
BLAKE2b-256 checksum How to use checksums |
1b8e9856ed68256d61d1101a995c9b2f7e5c700114dc5433097876a5c6773f45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / baud_cli-0.1.2-py3-none-any.whl
| Download URL | baud_cli-0.1.2-py3-none-any.whl |
|---|---|
| Size | 18.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
33e632562996e6b2a2e6fc71cc6ec43ff4a43c2e3a08fcb2158f53f634cc203d
|
|
BLAKE2b-256 checksum How to use checksums |
184abf328cff4713805e9b20585eda5b66896513d05dbe1421009d602a05ba82
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|