9.6 KiB
Hyprland Lua Migration Checklist
This checklist tracks the migration described in docs/tiling-wm-experience.md.
Guiding rule for shelling out:
- Prefer Lua for compositor/window/workspace state changes.
- Avoid
hyprctlfor window manipulation unless there is no usable Lua API. hyprctlremains acceptable for non-window-control escape hatches such ashyprctl reload.- External utilities remain acceptable where they are the real tool being launched, for example rofi, cliphist, grim/slurp/swappy, playerctl, hyprlock, and systemd commands.
0. Version And Build Base
- Update/confirm Hyprland Lua input at latest usable upstream target.
- Keep stable Hyprland path intact until Lua path is proven.
- Keep hy3 out of the Lua branch.
- Keep hyprNStack following the Lua Hyprland input.
- Rebuild hyprNStack against the Lua Hyprland branch.
- Add a forked hyprexpo input for the Lua Hyprland branch.
- Keep a cheap Lua check: parse config, execute against stub, reject
hyprctlin the Lua config's window/workspace manipulation path. - Add a real Hyprland Lua verifier check for the config parser path.
Current upstream note: latest Hyprland release observed during this migration is
v0.54.3; the Lua config input tracks PR 13817 and was already at the current
PR head c35a8a5 dated 2026-04-26. The non-Lua fallback remains pinned to the older
hy3/hyprexpo-compatible stack; the Lua branch uses forked hyprexpo branch
colonelpanic8/hyprland-plugins:hyprexpo-lua-hyprland.
1. Core Layout
- Primary layout is equal-width columns.
- No scrolling layout.
- No hy3 in Lua path.
- Dynamic redistribution on open/close via Lua-managed nStack count.
- Monocle/tabbed-style layout available.
- Direct jump to columns layout.
- Direct jump to monocle layout.
- Directional focus cycles in monocle.
- Visual indication of hidden monocle windows, currently notification.
- Make layout state per workspace instead of one global current layout.
- Preserve one-window smart gaps in the live config path.
- Use a persistent monocle indicator instead of a transient notification.
Smart-gaps note: nStack uses no_gaps_when_only = true; Hyprland workspace
rules are still applied at runtime for broader parity, but skipped during
--verify-config because the current Lua PR segfaults when rule bindings run in
verifier mode.
2. Workspace Behavior
Super+1..9focuses bounded workspaces.Super+Shift+1..9sends window without following.Super+Ctrl+1..9sends and follows.- Previous workspace per monitor uses Lua-tracked history.
- Implement next empty workspace focus in Lua.
- Implement move focused window to next empty workspace without following.
- Implement move focused window to next empty workspace and follow.
- Implement bounded workspace cycling
1..9in Lua, replacingworkspace-scroll.sh. - Implement workspace swap or decide whether native dispatcher is enough.
- Track current monitor workspace history explicitly, with native
previous_per_monitoras fallback.
3. Directional Navigation
Super+w/a/s/dfocuses windows.Super+Shift+w/a/s/dswaps windows.Hyper+w/a/s/dfocuses monitors.Hyper+Shift+w/a/s/dmoves windows to monitors.Super+znext monitor.Super+Shift+zmove to next monitor.- Replace any old cursor-follow/move scripts fully.
- Add required
Super+Ctrl+w/a/s/dmove-to-monitor behavior preserving useful focus. - Add "move to empty workspace on monitor in direction" without requiring
Hyper+Ctrl. - Route directional focus in monocle through deterministic Lua cycling.
- Live-verify directional focus in monocle behaves predictably.
4. Script Elimination Priority
- Core layout switching no longer uses scripts.
- Core column count logic no longer uses scripts or
hyprctl. - Replace
find-empty-workspace.sh. - Replace
workspace-goto-empty.sh. - Replace
workspace-move-to-empty.sh. - Replace
workspace-scroll.sh. - Replace
cycle-layout.sh. - Replace
movewindow-follow-cursor.sh. - Replace
gather-class.sh. - Replace
focus-next-class.sh. - Replace
raise-or-run.sh. - Replace minimize scripts if Lua can maintain hidden workspace state.
- Replace
swap-workspaces.sh. - Decide whether rofi-backed pickers remain scripts or become Lua-generated command pipes. Rofi itself remains external.
5. Overview And Window Discovery
- Restore visual hyprexpo for
Super+Taboverview. - Restore visual hyprexpo
bringmode forSuper+Shift+Tab. - Keep first-pass Lua numbered window picker on secondary bindings.
- Implement first-pass Lua-native go-to-window picker.
- Implement first-pass Lua-native bring-window picker.
- Implement first-pass Lua-native replace-window picker.
- Picker entries include icons.
- Picker entries include title/workspace.
- Hide scratchpad/minimized/internal windows from normal pickers.
- Decide whether picker data generation can be Lua-native with rofi as only external process.
Picker decision: current Lua API can query and manipulate windows directly, but does not expose a synchronous way to run rofi and consume its selected output. The first pass therefore uses Lua-native numbered submaps and notifications. A final rofi/icon picker would need either a small IPC bridge or an upstream Lua process-output/callback primitive.
Hyprexpo decision: hyprexpo is kept as the visual overview. The forked Lua
branch exposes hl.plugin.hyprexpo.expo(...), so the Lua config can invoke
toggle and bring directly without shelling out to hyprctl.
6. Scratchpads
- Preserve named scratchpads: element, gmail, htop, messages, slack, spotify, transmission, volume.
- Preserve dropdown terminal scratchpad.
- Scratchpads near-fullscreen and centered.
- Scratchpads hidden from normal listings/status bar.
- Toggling scratchpad exits fullscreen/monocle state first.
- Decide hyprscratch daemon is not needed in the Lua branch.
- Replace
hyprscratch togglewith Lua-managed scratchpad toggles. - Disable hyprscratch service on the Lua branch.
- Handle delayed class/title assignment with window class/title event adoption.
- Handle already-running app.
- Handle minimized app.
- Handle app on another workspace.
7. Minimization
- Implement minimize active window.
- Implement restore last minimized window.
- Exclude minimized windows from layout.
- Exclude minimized windows from normal go/bring lists.
- Implement minimized picker.
- Implement restore all minimized.
- Implement minimize other windows of current workspace class.
- Implement restore windows of focused class.
- Decide hidden workspace naming/state model for minimized windows.
- Hydrate minimized-window state from the hidden workspace on restore/picker paths.
8. Class-Aware Workflows
- Gather all windows of focused class onto current workspace.
- Focus next window of different/same class as desired parity.
- Browser raise-or-spawn.
- Window info command exposes class/title/workspace/address/pid.
- Window menus expose real window icons.
- Prefer Lua window queries over
hyprctl clients.
9. Status Bar Contract
- Confirm taffybar can still list normal workspaces.
- Confirm special scratchpad/minimize workspaces are filtered.
- Confirm active workspace per monitor remains visible.
- Confirm class/title/active/minimized/urgent metadata is available.
- Expose layout name/state if practical.
- Confirm workspace/window positioning remains enough for icon strips.
Layout state note: Lua writes $XDG_RUNTIME_DIR/hyprland-layout-state with the
active workspace, active layout, and per-workspace layout map. Taffybar still
needs a live readback check.
10. Session And Utilities
- Terminal binding preserved.
- Launcher/run menu preserved.
- Media keys preserved.
- Clipboard history binding preserved.
- Screenshot binding preserved.
- Lock binding preserved.
- Session startup target integration preserved.
hyprctl reloadmay remain available as a non-window-manipulation escape hatch.- Resolve
Hyper+wconflict: monitor focus must win; wallpaper picker needs another key. - Keep rofi utility commands as external commands unless there is a meaningful Lua replacement.
- Decide which shell utilities are acceptable because they are not Hyprland control scripts.
11. Validation
- Lua syntax check.
- Lua stub execution check.
hyprctlrejection in Lua config for window/workspace manipulation.- Real
Hyprland --verify-configcheck. - hyprNStack flake build check.
- hyprexpo Lua-branch flake build check.
ryzen-shinesystem dry-run.just switchactivates successfully and deploys branch-owned~/.config/hypr/hyprland.lua.- Re-run checks after Hyprland/Lua input confirmation.
- Try live compositor smoke test again after version bump.
- Document
--verify-configcaveats for Lua rule/plugin-specific config. - Eventually run
just switchonly when the branch is coherent enough for a live test.
Live-smoke note: this Hyprland binary exposes --verify-config but no
--headless CLI flag. just switch now installs the Lua branch binary and
deploys hyprland.lua, but the currently running compositor remains the old
0.53 process until the Hyprland session is restarted. A true compositor smoke
test still needs a session restart or a nested Wayland session that avoids
startup side effects.