# Keybind reminder design A full-screen overlay listing every Hyprland keybind with what it does, opened with `SUPER + k`. It exists to recall shortcuts, so it must never show a bind that is not live or miss one that is. ## Source of truth `hyprctl binds -j`, run on every opening. This is what Hyprland has loaded, including binds generated in Lua loops, and it stays correct when `keybindings.lua` has been edited but not reloaded. Parsing the Lua file was rejected for exactly those two cases. No cache: the call is cheap and a cache is the only way the list could go stale. `hyprctl` reports every Lua action as `dispatcher: "__lua"` with an opaque numeric `arg`, so the action text comes from the bind's `description`, a documented `HL.BindOptions` field (`/usr/share/hypr/stubs/hl.meta.lua`). ## Hypr side (`hypr-theme` repo) - Every `hl.bind` gains `{ description = "Group: Label" }`, merged into any options it already has (`locked`, `repeating`, `mouse`). Loop-generated binds build theirs in the loop, e.g. `"Workspaces: Go to 3"`. - The text before the first `": "` is the group heading in the overlay. - New bind: `SUPER + k` → `qs -p /keybinds ipc call keybinds toggle`, description `"Help: Keybind reminder"`. - `autostart.lua` starts `qs -p /keybinds`. - `decorations.lua` gains a `blur-keybinds` layer rule matching namespace `^(quickshell-keybinds)$`, copied from `blur-window-switcher`. - `SUPER + s` is defined in `dashboard.lua`, a symlink into the `conky-theme-udt` repo; its description is a commit there. ## Quickshell side: `keybinds/` - `shell.qml`: `ShellRoot` with the overlay and an `IpcHandler` target `keybinds` exposing `toggle`, `show`, `close`. - `Keybinds.qml`: `Scope` holding the 1x1 click-through keepalive `PanelWindow` and a `LazyLoader` overlay on `root.open`. Overlay layer, namespace `quickshell-keybinds`, `ExclusionMode.Ignore`, exclusive keyboard. A focused `Item` handles Esc; a click anywhere closes. - Opening sets `running = false` then `true` on a `Process` running `hyprctl binds -j`; `StdioCollector` output is parsed on exit. - `Binds.js` (pure, `.pragma library`): `mods(mask)` decodes SHIFT=1, CTRL=4, ALT=8, SUPER=64 in the order SUPER, CTRL, ALT, SHIFT; `group(binds)` returns `[{ name, rows: [{ keys, label }] }]`, groups in first-seen order. A bind with no description goes to group `Undescribed` with its raw key as label, so gaps stay visible. Mouse binds show as written (`mouse:272`). - Layout: groups flow in a `Flow` of columns, each a heading plus `keys label` rows. Theme from the `Theme.qml` symlink to `../shared/Theme.qml`; glyph-free. - While loading or on `hyprctl` failure, the overlay says so rather than drawing empty. - `README.md`, GPLv2 headers on every file. ## Testing `keybinds/test_binds.js`, runnable with `node` (it strips the `.pragma` line and evaluates `Binds.js`), asserts `mods` and `group` against a fixture shaped like `hyprctl binds -j`. Visual check by the user. ## Out of scope Search box (add if the list outgrows a screen, ~80 binds today). Submaps (none in use).