Metadata-Version: 2.5
Name: baud-cli
Version: 0.1.2
Summary: Agent-friendly serial diagnostics and repeatable hardware workflows
Project-URL: Homepage, https://github.com/Nitmi/baud-cli
Project-URL: Repository, https://github.com/Nitmi/baud-cli
Project-URL: Issues, https://github.com/Nitmi/baud-cli/issues
Author: Nitmi
License: MIT License
        
        Copyright (c) 2026 Nitmi
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: agent,cli,hardware,serial,uart
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Requires-Dist: pyserial>=3.5
Requires-Dist: pyyaml>=6.0.2
Provides-Extra: binary
Requires-Dist: pyinstaller==6.22.2; extra == 'binary'
Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'binary'
Provides-Extra: dev
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.11; extra == 'dev'
Description-Content-Type: text/markdown

# baud-cli

[![CI](https://github.com/Nitmi/baud-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/Nitmi/baud-cli/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/baud-cli.svg)](https://pypi.org/project/baud-cli/)
[![Python](https://img.shields.io/pypi/pyversions/baud-cli.svg)](https://pypi.org/project/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:

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

```shell
uv tool install baud-cli
baud --help
```

Install from a checkout while developing:

```shell
uv tool install --editable .
baud --help
```

For development:

```shell
uv sync --extra dev
uv run baud --help
```

Install the Agent Skill from the public repository with the cross-agent `skills` CLI:

```shell
npx skills add Nitmi/baud-cli --skill baud
```

OpenClaw users can install the published [ClawHub skill](https://clawhub.ai/nitmi/skills/baud):

```shell
openclaw skills install @nitmi/baud
```

For development from this checkout, install or verify the bundled Skill directly:

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

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

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

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

```yaml
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](https://github.com/Nitmi/blea). It provides a universal Agent Plugin
with a portable Skill, deterministic CLI, and local MCP server.
