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
170 lines
5.7 KiB
Markdown
170 lines
5.7 KiB
Markdown
# 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).
|