opencode-rgbify-plugin 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # opencode-rgbify-plugin
2
+
3
+ An [opencode](https://opencode.ai) plugin that streams chat text deltas to an
4
+ [RGBify](https://github.com/dcerisano/rgbify-projector) 8x8 LED projector over
5
+ BLE, with an always-on host auralizer so the sound never stops even when the
6
+ projector is out of range.
7
+
8
+ ## How it works
9
+
10
+ ```
11
+ opencode events ──► src/index.ts (plugin) ──► raw tail ──► line on stdin
12
+
13
+ bridge/ble_bridge.py
14
+ ├─► BLE write → RGBify projector
15
+ └─► host auralizer (miniaudio)
16
+ ```
17
+
18
+ - **`src/index.ts`** — the opencode plugin. Spawns the Python bridge and
19
+ forwards each delta's last 8 chars as a newline-delimited line. **No
20
+ sanitization**: both auralizers treat any out-of-range byte as a rest, so
21
+ raw text is safe. (Sanitization existed for the scrolling-display era, where
22
+ tags in the text would scroll across the matrix; the firmware now blits one
23
+ char at a time, so tags are harmless — and the old tag-swallowing state
24
+ machine could stick on an unbalanced `<` and silently discard whole streams.
25
+ That was the long-standing "auralizers go silent" bug.)
26
+ - **`bridge/ble_bridge.py`** — the BLE bridge. Reads lines from stdin, chunks
27
+ them to the negotiated MTU, writes them to the projector's `TEXT_BRIDGE`
28
+ characteristic, and auralizes each char on the host at the firmware's native
29
+ cadence (one ~33ms note per char, log-scale frequency table identical to the
30
+ firmware).
31
+
32
+ ### Interrupt semantics
33
+
34
+ Every event is delivered immediately as its own line — no buffering, no
35
+ debounce, no rate limiter. Each sink (BLE write path, host auralizer) keeps
36
+ only the **latest** line, so a newer message supersedes anything still in
37
+ flight. The last message is the only message.
38
+
39
+ While the projector is connected, the host auralizer plays **exactly** the
40
+ bytes the projector receives (char-perfect sync). While it's down, the host
41
+ keeps auralizing and lines are dropped for the projector — nothing is queued or
42
+ replayed on reconnect.
43
+
44
+ ## Install
45
+
46
+ The plugin is **self-bootstrapping**: on first use it automatically runs the
47
+ bridge installer, which installs everything it needs (uv, Python, and the
48
+ bridge deps) as the current user — no root/admin required. On Linux/macOS it
49
+ runs `bridge/install.sh`; on Windows it runs `bridge/install.ps1` (via
50
+ PowerShell). No manual setup is needed; just install the plugin into opencode.
51
+
52
+ You can also run the installer yourself (it's idempotent — re-running is a
53
+ no-op):
54
+
55
+ ```bash
56
+ bash bridge/install.sh # Linux/macOS
57
+ powershell -ExecutionPolicy Bypass -File bridge/install.ps1 # Windows
58
+ ```
59
+
60
+ Each installer ensures `uv` (installing it into the user's home dir if
61
+ missing), uses uv to manage a Python interpreter, creates an isolated `.venv`
62
+ at the plugin root — the exact path `src/index.ts` probes for `VENV_PYTHON`
63
+ (`.venv/bin/python` on Unix, `.venv/Scripts/python.exe` on Windows) — and
64
+ installs `bleak` (required) plus `miniaudio` (host auralizer). `miniaudio`
65
+ bundles its own native audio lib, so the auralizer needs no system deps (no
66
+ PortAudio) and works cross-platform on Windows, macOS, and Linux. If
67
+ `miniaudio` is unavailable, the host auralizer is disabled and the projector
68
+ path still works.
69
+
70
+ ## Configuration
71
+
72
+ | Env var | Default | Purpose |
73
+ | --- | --- | --- |
74
+ | `RGBIFY_DISABLE` | — | Set to `1`/`true` to disable the plugin |
75
+ | `RGBIFY_PROJECTOR_ADDR` | `40:91:51:AB:50:CE` | Fixed projector address (skips BLE discovery) |
76
+ | `RGBIFY_HOST_AURALIZER` | `1` | Set to `0` to disable the host auralizer |
77
+ | `RGBIFY_VOLUME` | `10` | Initial host volume (0–10) |
78
+ | `RGBIFY_STATE_DIR` | `~/.config/opencode/state` | Where `host-volume` is persisted |
79
+ | `RGBIFY_DEBUG_LOG` | — | Append debug log path |
80
+
81
+ Host volume is mirrored from the projector's `VOLUME` characteristic whenever
82
+ it's connected and persisted to `host-volume` so it survives restarts. While
83
+ the projector is off you can still adjust the host volume by editing that file.
84
+
85
+ ## Development
86
+
87
+ ```bash
88
+ npm install # @opencode-ai/plugin types
89
+ bun run ... # run opencode with the plugin loaded
90
+ ```
91
+
92
+ The bridge logs one line per event to stdout for debugging: `ok <addr>` on
93
+ connect/delivery, `err <message>` on failure (it retries with backoff forever).
94
+
95
+ ## License
96
+
97
+ MIT