# 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).