Skip to content

qinwenshi/blooth-cli

Repository files navigation

blooth-cli

blooth-cli is a Go-based macOS CLI that sends structured Agent actions to an ESP32-C3 e-paper device over BLE.

Image + text card layout on e-paper display

docs/       product and technical specs
cli/        Go CLI source
firmware/   ESP32-C3 PlatformIO project (GxEPD2_420 e-paper driver)
fixtures/   sample action payloads
skills/     Cursor/Claude skill for Agent integration

Quick Start

  1. Download the CLI and flash the firmware
  2. Power on the device — it shows SChat-HUD-XXXX (last 4 hex of MAC) on screen
  3. Install the Skill in Cursor / Claude
  4. Ask the agent: "Show this on my desk display"

CLI Installation

# Apple Silicon
curl -L https://github.com/qinwenshi/blooth-cli/releases/latest/download/blooth-cli-darwin-arm64 -o blooth-cli
chmod +x blooth-cli && xattr -dr com.apple.quarantine blooth-cli
sudo mv blooth-cli /usr/local/bin/

# Intel Mac
curl -L https://github.com/qinwenshi/blooth-cli/releases/latest/download/blooth-cli-darwin-amd64 -o blooth-cli
chmod +x blooth-cli && xattr -dr com.apple.quarantine blooth-cli
sudo mv blooth-cli /usr/local/bin/

xattr -dr com.apple.quarantine removes the macOS Gatekeeper flag on unsigned binaries downloaded from the internet.


CLI Commands

blooth-cli device scan                             # find nearby BLE devices
blooth-cli device use <uuid>                       # save as default device
blooth-cli device default                          # show saved default
blooth-cli device forget                           # clear saved default
blooth-cli device status      [--device <uuid>]
blooth-cli device capabilities [--device <uuid>]
blooth-cli device clear       [--device <uuid>]
blooth-cli doctor ble                              # diagnose BLE permission
blooth-cli render text-card   [--device <uuid>] --title "..." --body "..." --footer "..."
blooth-cli render status-card [--device <uuid>] --status info --title "..." --summary "..."
blooth-cli render image-card  [--device <uuid>] --image <file|url|-> --layout top|right|full --title "..."
blooth-cli wait button        [--device <uuid>] --buttons confirm,menu --timeout-ms 120000
blooth-cli action run --file fixtures/actions/text-card.json
blooth-cli version

BLE environment variables (required for all BLE commands):

export BLOOTH_SERVICE_UUID=7a1f0001-7f3b-4b2a-8e5a-3c613a11d001
export BLOOTH_STATUS_CAPS_UUID=7a1f1002-7f3b-4b2a-8e5a-3c613a11d001
export BLOOTH_CONTROL_UUID=7a1f0002-7f3b-4b2a-8e5a-3c613a11d001
export BLOOTH_DATA_IN_UUID=7a1f0003-7f3b-4b2a-8e5a-3c613a11d001
export BLOOTH_DATA_OUT_UUID=7a1f0004-7f3b-4b2a-8e5a-3c613a11d001
export BLOOTH_EVENT_UUID=7a1f0005-7f3b-4b2a-8e5a-3c613a11d001

Skill (Agent Integration)

A Cursor/Claude skill is included in skills/blooth-epd/. It lets an Agent display content and wait for button input without knowing BLE details.

See skills/blooth-epd/README.md for installation and usage.


Hardware

Board

Item Spec
MCU ESP32-C3 (RISC-V, 160 MHz, 400 KB SRAM)
Module ESP32C3-FN4 CrossAir (4 MB Flash)
USB CDC on boot (no USB-Serial chip needed)
BLE Bluetooth 5.0 LE via NimBLE stack

E-Paper Display

Item Spec
Model Waveshare 4.2" e-Paper HAT
Resolution 400 × 300 px, Black & White
Driver IC SSD1683 (GxEPD2_420)
Interface SPI
Partial refresh ✅ supported (fast mode, max 6 before full refresh)

SPI pin wiring:

Signal GPIO
CS (chip select) 3
DC (data/cmd) 4
RST (reset) 5
SCK (clock) 6
MOSI (data) 7
BUSY 8

Buttons

Button GPIO Logic BLE name Status
Confirm 21 Active-LOW, INPUT_PULLUP confirm ✅ working
Menu (BOOT) 9 Active-LOW, INPUT_PULLUP menu ✅ working
Back 1 Active-HIGH, pull-down back ❌ not populated on this unit
Next 20 Active-HIGH, INPUT_PULLDOWN next ❌ not populated on this unit

GATT Service Layout

Service UUID: 7a1f0001-7f3b-4b2a-8e5a-3c613a11d001

Characteristic UUID suffix Properties Description
control 7a1f0002 WRITE, WRITE_NR Job header (action + job_id + payload_len)
data_in 7a1f0003 WRITE, WRITE_NR Chunked payload bytes
data_out 7a1f0004 NOTIFY, READ ACK / DONE / ERROR responses
event_notify 7a1f0005 NOTIFY Button press events
status_caps 7a1f1002 READ Device state + capabilities JSON

Firmware Features

  • Device name: SChat-HUD-XXXX (XXXX = last 4 hex digits of MAC) — unique per device, no scan conflicts
  • Display persistence: last rendered content saved to NVS, restored on reboot
  • Word wrap: long body text auto-wraps at word boundaries (Latin) or character boundaries (CJK)
  • Chinese support: U8g2 wqy16_t_gb2312 font (full GB2312: 6763 CJK + all punctuation)
  • Error screen: firmware shows ERROR header + message on display for all protocol errors

Firmware Flashing

Option A — Pre-built binary (recommended)

Download blooth-epd-firmware-vX.Y.Z.bin from the latest release:

pip install esptool

# Put board in flash mode: hold BOOT button, press RST, release BOOT
esptool.py --chip esp32c3 --port /dev/cu.usbmodem* \
  --baud 460800 write_flash 0x0 blooth-epd-firmware-vX.Y.Z.bin

After flashing, press RST to reboot. The display shows the device name (SChat-HUD-XXXX).

Option B — Build from source

# Requires PlatformIO
cd firmware
pio run --target upload

Local Development

make build          # compile CLI binary → ./blooth-cli
make fmt            # go fmt ./cli/...
make run-scan       # stub device scan (no hardware needed)

# With hardware:
make run-capabilities DEVICE=<uuid>
make run-render DEVICE=<uuid> TITLE="Hello" BODY="Line 1\nLine 2"
make run-wait-button DEVICE=<uuid> TITLE="Continue?" BODY="Press confirm"

Stub mode (no hardware):

export BLOOTH_TRANSPORT=stub
make run-scan

Requirements

  • CLI: macOS 12+, CoreBluetooth
  • Build from source: Go 1.22+
  • Firmware build: PlatformIO
  • Firmware flash: esptool (pip install esptool)

About

Your AI agent can now write on your desk. A CLI + ESP32 firmware that lets LLMs push text, images, and yes/no prompts to a physical e-ink display over BLE — no cloud, no polling, just atoms.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors