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.
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.
Install the published command on Windows, macOS, or Linux:
uv tool install baud-cli
baud --helpInstall from a checkout while developing:
uv tool install --editable .
baud --helpFor development:
uv sync --extra dev
uv run baud --helpInstall the Agent Skill from the public repository with the cross-agent skills CLI:
npx skills add Nitmi/baud-cli --skill baudOpenClaw users can install the published ClawHub skill:
openclaw skills install @nitmi/baudFor 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 --jsonThe 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.
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.
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 --jsonprobe 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.
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.
| 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.