Files
dotfiles/docs/hyprland-lua-migration-checklist.md

8.8 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 hyprctl for window manipulation unless there is no usable Lua API.
  • hyprctl remains acceptable for non-window-control escape hatches such as hyprctl 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/hyprexpo out of the Lua branch.
  • Keep hyprNStack following the Lua Hyprland input.
  • Rebuild hyprNStack against the Lua Hyprland branch.
  • Keep a cheap Lua check: parse config, execute against stub, reject hyprctl in 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.

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..9 focuses bounded workspaces.
  • Super+Shift+1..9 sends window without following.
  • Super+Ctrl+1..9 sends 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..9 in Lua, replacing workspace-scroll.sh.
  • Implement workspace swap or decide whether native dispatcher is enough.
  • Track current monitor workspace history explicitly, with native previous_per_monitor as fallback.

3. Directional Navigation

  • Super+w/a/s/d focuses windows.
  • Super+Shift+w/a/s/d swaps windows.
  • Hyper+w/a/s/d focuses monitors.
  • Hyper+Shift+w/a/s/d moves windows to monitors.
  • Super+z next monitor.
  • Super+Shift+z move to next monitor.
  • Replace any old cursor-follow/move scripts fully.
  • Add required Super+Ctrl+w/a/s/d move-to-monitor behavior preserving useful focus.
  • Add "move to empty workspace on monitor in direction" without requiring Hyper+Ctrl.
  • 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

  • Replace hyprexpo with the first-pass Lua numbered window picker.
  • Implement first-pass Super+Tab overview via Lua window picker.
  • Implement first-pass Super+Shift+Tab bring overview via Lua window picker.
  • 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.

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 toggle with 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.

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 reload may remain available as a non-window-manipulation escape hatch.
  • Resolve Hyper+w conflict: 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.
  • hyprctl rejection in Lua config for window/workspace manipulation.
  • Real Hyprland --verify-config check.
  • hyprNStack flake build check.
  • ryzen-shine system dry-run.
  • Re-run checks after Hyprland/Lua input confirmation.
  • Try live compositor smoke test again after version bump.
  • Document --verify-config caveats for Lua rule/plugin-specific config.
  • Eventually run just switch only when the branch is coherent enough for a live test.

Live-smoke note: this Hyprland binary exposes --verify-config but no --headless CLI flag. A true compositor smoke test still needs either a nested Wayland session that avoids startup side effects or an intentional just switch.