Files
streamdeck-go/omarchy-plugin/README.md
Levi Woodard 2aa4c65e42 Add Omarchy shell plugin for the Stream Deck
QML bar widget + popout panel (dev.woodard.streamdeck) that drives
streamdeck-ctl: key grid shaped by the connected model, per-key editor,
brightness slider, and daemon controls. Themed via qs.Commons.

Makefile gains build-ctl, install-ctl, install-plugin, validate-plugin
and uninstall-plugin targets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BjuZBBfzXqZgxRhxzJvkkC
2026-09-27 18:21:33 -06:00

170 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Stream Deck — Omarchy shell plugin
A bar widget for [Omarchy](https://omarchy.org) that controls the
[streamdeck-go](https://git.i0t.app/lwoodard/streamdeck-go) daemon: device and
daemon status, brightness, and a live 8×4 key grid you can edit in place.
Every colour and metric resolves through Omarchy's `qs.Commons` theme tokens
(`Color.*`, `Style.*`), so the widget follows the active theme rather than
carrying a palette of its own.
---
## What it does
**Bar icon** — a miniature deck that fills in proportionally to how much of the
deck is mapped, and dims when the deck is unplugged or the daemon is stopped.
**Panel**
| Section | Behaviour |
|---|---|
| Header | Title, status line, and an on/off switch for the `streamdeck-go` user service |
| Brightness | Slider writing `brightness:` into `config.yaml`; the daemon hot-reloads, so the deck dims as you drag |
| Facts | Device model, connection state, daemon state and uptime |
| Key grid | One cell per physical key, with icon previews, slot indices, and labels. Empty slots are shown so you can fill them |
| Editor | Right-click a key to edit its module/function, parameters, shell command, icon, label, and label colour |
| Actions | Restart the daemon, open `config.yaml`, open the icons folder, follow the log |
A red dot on a cell marks a `priv:` key. Those run through the privileged helper
and are deliberately **not** runnable from the panel — press them on the deck.
### Mouse and keyboard
| Input | Action |
|---|---|
| Left-click bar icon | Open/close the panel |
| Right-click bar icon | Refresh |
| Middle-click bar icon | Start/stop the daemon |
| Left-click a key | Run that key's command (fire-and-forget, like a physical press) |
| Right-click a key | Open the editor for that key |
| Arrow keys | Move the grid cursor |
| `Enter` | Edit the focused key |
| `Space` | Run the focused key |
| `e` | Edit the focused key |
| `r` | Refresh |
| `p` | Start/stop the daemon |
| `Esc` | Leave the field → close the editor → close the panel |
---
## Requirements
- Omarchy with `omarchy-shell` running
- `streamdeck-go` installed and its user service present
- **`streamdeck-ctl`** — the helper CLI the plugin drives. The panel refuses to
show controls without it and tells you how to install it.
The plugin never edits YAML or probes USB itself; it shells out to
`streamdeck-ctl`, which reuses the daemon's own config and device code. That
keeps one implementation of the config format rather than two.
---
## Install
From a checkout of the streamdeck-go repo:
```bash
make install-plugin # builds + installs streamdeck-ctl, links the plugin
omarchy plugin enable dev.woodard.streamdeck right
```
`make install-plugin` symlinks this directory into
`~/.config/omarchy/plugins/dev.woodard.streamdeck`, so edits to the QML are live
after a rescan:
```bash
omarchy-shell shell rescanPlugins
```
> Qt caches compiled QML in `~/.cache/quickshell/qmlcache`, and a running shell
> can keep serving a stale compiled unit across a rescan. If an edit doesn't seem
> to take effect, `omarchy restart shell`.
To validate before committing:
```bash
make validate-plugin
```
`omarchy plugin validate` refuses a symlinked plugin folder by design, so this
target validates the source directory rather than the installed link.
### Remove
```bash
make uninstall-plugin
```
---
## Settings
Configurable from the Omarchy bar widget settings:
| Setting | Default | Meaning |
|---|---|---|
| `refreshIntervalSec` | 10 | Poll cadence while the panel is open; closed, it relaxes to at most once a minute |
| `ctlPath` | *(empty)* | Explicit path to `streamdeck-ctl`; empty searches `~/.local/bin`, `~/go/bin`, `/usr/local/bin`, then `$PATH` |
| `configPath` | *(empty)* | Explicit `config.yaml`; empty uses `~/.config/streamdeck-go/config.yaml` |
| `hideWhenDisconnected` | false | Hide the bar icon entirely when no deck is connected |
---
## IPC
```bash
omarchy-shell dev.woodard.streamdeck open
omarchy-shell dev.woodard.streamdeck toggle
omarchy-shell dev.woodard.streamdeck status # "20 of 32 keys in use"
omarchy-shell dev.woodard.streamdeck refresh
omarchy-shell dev.woodard.streamdeck brightness 60
omarchy-shell dev.woodard.streamdeck press 3
```
Useful for Hyprland binds — e.g. a key that dims the deck without opening the bar.
---
## Security note
Module keys can reference secrets via `{{env "TOKEN"}}` in their exec templates.
`streamdeck-ctl status` never emits the rendered command — the panel shows only
`module · function` for module keys — so tokens can't leak into the UI or into
anything scraping the CLI's JSON. On Linux, `key press` merges the systemd user
manager's environment over the caller's before running, so a token imported with
`systemctl --user import-environment` reaches panel presses exactly as it reaches
hardware presses. (macOS keeps the caller's environment — launchd has no
equivalent bulk query.)
## A note on config formatting
Saving from the editor rewrites `config.yaml` through a YAML node-level editor.
Comments and blank lines are preserved, but two normalisations happen on any
save:
- trailing whitespace on values is trimmed
- a comment block dangling at the end of a key entry may be re-indented to match
the block it attaches to
Both are cosmetic. Values, ordering, and comment text are preserved.
---
## Files
```
manifest.json plugin metadata + settings schema
Panel.qml bar icon and popout panel (entry point)
Service.qml owns every streamdeck-ctl invocation
KeyGrid.qml the 8x4 (or 5x3) key grid
KeyEditor.qml per-key editor
StreamDeckIcon.qml drawn deck icon, takes its colour from the caller
Model.js parsing and formatting helpers
```
## License
MIT — see [LICENSE](LICENSE).