Skip to content

feat: migrate Hyprland config from hyprlang to Lua with transparent IPC proxy#216

Open
notvcto wants to merge 1 commit into
dusklinux:mainfrom
notvcto:feat/lua-config
Open

feat: migrate Hyprland config from hyprlang to Lua with transparent IPC proxy#216
notvcto wants to merge 1 commit into
dusklinux:mainfrom
notvcto:feat/lua-config

Conversation

@notvcto
Copy link
Copy Markdown
Contributor

@notvcto notvcto commented May 12, 2026

Summary

Full migration of the Hyprland configuration from hyprlang (.conf) to native Lua (.lua). Every source file has been converted, all original .conf files removed, all user scripts audited and updated for Lua dispatch syntax, and a transparent IPC proxy layer ensures Waybar and other external tools continue to work without modification.


What changed

Core Hyprland config (.config/hypr/)

  • hyprland.lua — new entry point; Hyprland loads it directly, no .conf file required
  • source/*.lua — all config modules rewritten in Lua: appearance, autostart, environment_variables, input, keybinds, monitors, permissions, plugins, window_rules, workspace_rules
  • source/*.conf — all original .conf files removed; superseded by their .lua equivalents
  • source/*.conf.deprecated — originals preserved as .deprecated siblings for reference and easy reversion
  • source/animations/*.lua — all 20+ named animation presets converted to Lua; originals kept as .conf.deprecated
  • edit_here/source/*.lua — all user-editable overrides converted to Lua equivalents; .conf.deprecated originals kept alongside for reference

Lua IPC Proxy (user_scripts/hypr/hypr_lua_proxy.py)

Hyprland's Lua config mode changes how hyprctl dispatch works — old-style strings like workspace 3 or movetoworkspace 5 are no longer valid; the body is now evaluated as a Lua expression. This breaks Waybar workspace clicks and any external tool that calls hyprctl dispatch with the old syntax.

The proxy solves this transparently:

  • Command socket — a Python asyncio Unix socket server that intercepts dispatch calls, translates them into valid Lua expressions (hl.dsp.focus({workspace=3})), and forwards them to the real Hyprland socket
  • Event socket — a socat passthrough relay (zero Python overhead, pure kernel-level pipe) so Waybar's workspace indicators update in real time
  • Tools calling hyprctl dispatch through the proxy require zero changes

Waybar integration (user_scripts/waybar/)

  • waybar_autostart.sh — major rewrite; spawns the Python proxy and socat event relay as persistent systemd-run units (hypr-lua-proxy and hypr-socat-proxy) so they survive parent cgroup cleanup after the script exits; calls systemctl reset-failed before each launch to clear stale unit state; creates the proxy socket directory explicitly before socat binds into it, fixing a race condition where socat failed on boot because the directory didn't exist yet; injects HYPRLAND_INSTANCE_SIGNATURE=lua_proxy via systemd-run --setenv= so Waybar talks to the proxy sockets instead of Hyprland directly
  • dusky_waybars.sh — updated to use systemd-run --setenv= for the same injection, ensuring Waybar config switching also preserves workspace click functionality

User scripts

  • multi_monitor_workspace.sh — added lua_dispatch() which emits proper Lua expressions for workspace, movetoworkspace, and movetoworkspacesilent; banked navigation logic preserved
  • dusky_session.sh — Lua dispatch syntax for session exit and workspace dispatch
  • spotify_toggle.sh — Lua dispatch syntax for special workspace toggle
  • rofi_mako.sh — replaced hyprctl dispatch exec with uwsm-app (correct UWSM-aware launch)
  • keybindings.sh — shows a user-facing notice for the __lua dispatcher (Lua mode keybinds are not externally replayable via hyprctl dispatch)
  • hypr_anim.sh — animation preset switcher updated to source .lua presets

Control Center (user_scripts/dusky_system/control_center/dusky_config.yaml)

  • Hypr Reload button now triggers a desktop notification confirming the reload succeeded
  • Waybar config switching now routes through waybar_autostart.sh to maintain the proxy on every config change
  • Lua config mode badge added to the About / System section

Matugen (.config/matugen/)

  • config.toml — added [templates.hyprland_lua] entry with post_hook = 'hyprctl reload || :'; in Lua mode dofile() only runs at load time, so without this hook border and decoration colors would not update when the wallpaper changes
  • templates/hyprland-colors.lua — new Matugen template that generates the Lua color file sourced by hyprland.lua
  • templates/razer_sync.sh — new template that syncs the active theme's primary color to a Razer keyboard via polychromatic-cli; skips silently if polychromatic-cli is not installed or no matching device is found (RAZER_DEVICE env var configurable)

Waybar config

  • .config/waybar/01_horizontal_block/config.jsonc — new horizontal block layout

Test plan

  • Hyprland starts cleanly with hyprland.lua as entry point (no .conf required)
  • All modules load without errors (hyprctl reload clean)
  • Workspace switching via Super+1–10 works
  • Banked workspace navigation (Super+1–10 across banks) works
  • Waybar workspace clicks work (via proxy)
  • Waybar workspace indicator updates in real time (event relay)
  • Waybar config switching (CC dropdown + dusky_waybars.sh) preserves workspace clicks
  • Proxy and socat survive reboot as persistent systemd units
  • CC Hypr Reload button reloads config and shows notification
  • Animation switching (hypr_anim.sh) works with .lua presets
  • Session logout / workspace dispatch (dusky_session.sh) works
  • Keybindings rofi shows notice for __lua dispatcher
  • Wallpaper change updates border/decoration colors (matugen post_hook)
  • Proxy starts cleanly on boot with no race condition

@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 12, 2026

Amended the PR commit to include a fix for shader_menu.sh
hyprctl keyword silently no-ops in Lua config mode (exits 0 but does nothing), so rewrote shader application to use hl.config({decoration={screen_shader='...'}}) via hyprctl eval instead of relying on hyprshade

@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 12, 2026

Note: Some Control Center features are still broken after this migration, screen rotation and fractional scaling confirmed so far. Investigating and will push fixes before this is ready to merge. Do not merge yet.

@notvcto notvcto marked this pull request as draft May 12, 2026 20:08
@notvcto notvcto force-pushed the feat/lua-config branch from 61a42b0 to 35480be Compare May 12, 2026 20:35
@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 12, 2026

Fixes pushed. Screen rotation, fractional scaling, blur toggle, and workspace manager ephemeral layout are all updated to use the Lua-mode equivalents. Should be ready to merge.

@notvcto notvcto marked this pull request as ready for review May 12, 2026 20:38
@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 12, 2026

More issues found via a full audit pass. 22 total across scripts, TUI tools, and setup scripts. Working through them now.

@notvcto notvcto marked this pull request as draft May 12, 2026 20:52
@dusklinux
Copy link
Copy Markdown
Owner

you're insane! wtf bro, i've been working on the port myself, its taking a while cuz i'm redoing all the configs not just porting them. but i'll look at how you happen to have done things and borrow a few things where i need them but damnn this is so much to merge, leave it up as a draft and i'll come back to this when i need something. thanks!

@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 13, 2026

@dusklinux All the Hypr configs are pretty much ported over to Lua, I'm just working on making everything else work around the new Lua logic
SHOULD be good to merge by the end of today/early tomorrow - unless I find something else I missed

Converts all source files from .conf (hyprlang) to .lua for
Hyprland's native Lua config mode.

- hyprland.lua: new Lua entry point; hyprland.conf kept as stub
- source/*.lua: all modules rewritten in Lua syntax
- source/animations/*.lua: all animation presets converted
- edit_here/: user-editable Lua overrides replace .conf equivalents
- hypr_lua_proxy.py: asyncio command-socket proxy that translates
  old-style dispatch strings (workspace N, movetoworkspace, etc.)
  into valid Lua expressions; event socket handled by socat
- waybar_autostart.sh: starts proxy + socat relay before launching waybar;
  race-safe socket detection retries until Hyprland socket is ready
- dusky_waybars.sh: uses systemd-run --setenv to inject proxy signature
- keybindings.sh: graceful notice for __lua dispatcher (non-replayable)
- rofi_mako.sh: replace hyprctl dispatch exec with uwsm-app
- dusky_session.sh: Lua dispatch syntax for exit and workspace
- spotify_toggle.sh: Lua dispatch syntax for special workspace
- dusky_config.yaml: CC reload feedback, Lua config badge, waybar fix
- matugen/config.toml: add hyprctl reload post_hook to hyprland_lua
  template so border/decoration colors update on wallpaper change
- matugen/templates/razer_sync.sh: sync theme color to Razer keyboard
  via Polychromatic; skips silently if not installed or no device found
@notvcto notvcto force-pushed the feat/lua-config branch from 35480be to 563ff4e Compare May 13, 2026 16:57
@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 13, 2026

Update: Full audit complete. All Control Center features, UI tools, and app switchers have been fully bridged and tested against the new .lua architecture. Here's what changed:

  • App switchers now dynamically parse and update default_apps.lua using valid Lua string assignments (var = "value"), removing the old, destructive keybind-clobbering logic entirely.
  • Monitor TUI (dusky_monitor.sh) parsing issues with headless displays (null fields and shifted TSV columns) have been fixed.
  • dusky_config.yaml paths updated to ensure the Control Center UI editor buttons open the correct .lua files instead of the deprecated .conf files.
  • Blur, shadow, and opacity quick-toggles now use a hardened atomic awk/sed pipeline that respects Lua table assignments (blur = {, enabled = false,).
  • Keybinds parser rewritten via python patch to accurately extract modifiers and dispatcher arguments from the hl.bind(...) format instead of the old hyprlang comma-separated strings.

Everything is stable in my testing environment. Marking as ready for review.

@notvcto notvcto marked this pull request as ready for review May 13, 2026 18:45
@notvcto
Copy link
Copy Markdown
Contributor Author

notvcto commented May 13, 2026

looking back at this it would've been way funnier if I just tagged the commit feat: changes for the love of the game

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants