From 79264914662e8d7823c2fc8537038b77b3c6b9ab Mon Sep 17 00:00:00 2001 From: m3tam3re Date: Sat, 1 Aug 2026 10:53:09 +0200 Subject: [PATCH 1/3] feat: migrate Hyprland configuration to Lua --- profiles/contexts/desktop/wm/hyprland.nix | 593 +++++++++++++++------- 1 file changed, 415 insertions(+), 178 deletions(-) diff --git a/profiles/contexts/desktop/wm/hyprland.nix b/profiles/contexts/desktop/wm/hyprland.nix index 29fe613..e9e924d 100644 --- a/profiles/contexts/desktop/wm/hyprland.nix +++ b/profiles/contexts/desktop/wm/hyprland.nix @@ -6,95 +6,148 @@ }: with lib; let cfg = config.desktop.wm.hyprland; + lua = lib.generators.mkLuaInline; + luaString = builtins.toJSON; + + mkEnvVar = name: value: { + _args = [ + name + value + ]; + }; + + modKey = key: lua ''mainMod .. " + ${key}"''; + mkDispatcher = expression: lua expression; + execCmd = command: "hl.dsp.exec_cmd(${luaString command})"; + execExpr = expression: "hl.dsp.exec_cmd(${expression})"; + + mkBinding = keys: dispatcher: { + _args = [ + keys + (mkDispatcher dispatcher) + ]; + }; + mkBindingWithOptions = keys: dispatcher: options: { + _args = [ + keys + (mkDispatcher dispatcher) + options + ]; + }; + + startupCommand = command: { + _args = [ + "hyprland.start" + (lua '' + function() + hl.exec_cmd(${luaString command}) + end + '') + ]; + }; + + focusWorkspace = workspace: "hl.dsp.focus({ workspace = ${luaString workspace} })"; + moveToWorkspace = workspace: "hl.dsp.window.move({ workspace = ${luaString workspace} })"; in { options.desktop.wm.hyprland.enable = mkEnableOption "Hyprland window manager"; config = mkIf cfg.enable { wayland.windowManager.hyprland = { - configType = "hyprlang"; + configType = "lua"; + extraLuaFiles."00-dms" = { + autoLoad = true; + content = '' + -- DMS setup/runtime owns these modules. Load only the Lua equivalents + -- of the pre-migration active sources, before local Home Manager + -- settings, preserving the old source-first order without enabling new + -- DMS default binds or rules. + -- + -- Keep fresh Home Manager generations usable before DMS has written + -- ~/.config/hypr/dms/*.lua. + local function require_if_present(module) + if package.searchpath(module, package.path) ~= nil then + require(module) + end + end + + require_if_present("dms.colors") + require_if_present("dms.layout") + require_if_present("dms.outputs") + ''; + }; settings = { - xwayland = { - force_zero_scaling = true; + mainMod = { + _var = "SUPER"; }; - source = [ - "~/.config/hypr/dms/colors.conf" - "~/.config/hypr/dms/layout.conf" - "~/.config/hypr/dms/outputs.conf" - ]; - exec-once = [ - "vibetyper" - ]; - - env = [ - "XCURSOR_SIZE,32" - "HYPRCURSOR_THEME,Bibata-Modern-Ice" - "WLR_NO_HARDWARE_CURSORS,1" - "XDG_CURRENT_DESKTOP,Hyprland" - "XDG_SESSION_TYPE,wayland" - "XDG_SESSION_DESKTOP,Hyprland" - "XKB_DEFAULT_LAYOUT,de" - "NIXOS_OZONE_WL,1" - "QT_QPA_PLATFORM,wayland;xcb" - "QT_QPA_PLATFORMTHEME,gtk3" - "QT_QPA_PLATFORMTHEME_QT6,gtk3" - ]; - - input = { - kb_layout = "us"; - kb_variant = ""; - kb_model = ""; - kb_rules = ""; - kb_options = "ctrl:nocaps"; - follow_mouse = 1; + terminal = { + _var = "ghostty"; }; - general = { - gaps_in = 5; - gaps_out = 5; - border_size = 1; - layout = "dwindle"; - }; - - decoration = { - shadow = { - enabled = true; - range = 60; - render_power = 3; - # color = "rgba(${config.colorScheme.palette.base00}66)"; - offset = "1 2"; - scale = 0.97; + config = { + xwayland = { + force_zero_scaling = true; }; - rounding = 8; - blur = { + input = { + kb_layout = "us"; + kb_variant = ""; + kb_model = ""; + kb_rules = ""; + kb_options = "ctrl:nocaps"; + follow_mouse = 1; + }; + general = { + gaps_in = 5; + gaps_out = 5; + border_size = 1; + layout = "dwindle"; + }; + decoration = { + shadow = { + enabled = true; + range = 60; + render_power = 3; + # color = "rgba(${config.colorScheme.palette.base00}66)"; + offset = "1 2"; + scale = 0.97; + }; + rounding = 8; + blur = { + enabled = true; + size = 3; + passes = 3; + }; + active_opacity = 0.9; + inactive_opacity = 0.5; + }; + animations = { enabled = true; - size = 3; - passes = 3; + }; + dwindle = { + # pseudotile = true; # TODO + preserve_split = true; + }; + master = { + new_status = "master"; }; - active_opacity = 0.9; - inactive_opacity = 0.5; }; - animations = { - enabled = true; - bezier = "myBezier, 0.05, 0.9, 0.1, 1.05"; - animation = [ - "windows, 1, 7, myBezier" - "windowsOut, 1, 7, default, popin 80%" - "border, 1, 10, default" - "borderangle, 1, 8, default" - "fade, 1, 7, default" - "workspaces, 1, 6, default" - ]; - }; + on = [ + (startupCommand "vibetyper") + ]; - dwindle = { - # pseudotile = true; # TODO - preserve_split = true; - }; - - master = { - new_status = "master"; - }; + "env" = [ + (mkEnvVar "XCURSOR_SIZE" "32") + (mkEnvVar "HYPRCURSOR_THEME" "Bibata-Modern-Ice") + (mkEnvVar "WLR_NO_HARDWARE_CURSORS" "1") + (mkEnvVar "XDG_CURRENT_DESKTOP" "Hyprland") + (mkEnvVar "XDG_SESSION_TYPE" "wayland") + (mkEnvVar "XDG_SESSION_DESKTOP" "Hyprland") + (mkEnvVar "XKB_DEFAULT_LAYOUT" "de") + (mkEnvVar "NIXOS_OZONE_WL" "1") + (mkEnvVar "QT_QPA_PLATFORM" "wayland;xcb") + (mkEnvVar "QT_QPA_PLATFORMTHEME" "gtk3") + (mkEnvVar "QT_QPA_PLATFORMTHEME_QT6" "gtk3") + ]; device = [ # Alle normalen Keyboards explizit auf de setzen: @@ -141,114 +194,298 @@ in { } ]; - windowrule = [ - "match:class file_progress, float on" - "match:class confirm, float on" - "match:class dialog, float on" - "match:class download, float on" - "match:class notification, float on" - "match:class error, float on" - "match:class splash, float on" - "match:class confirmreset, float on" - "match:title Open File, float on" - "match:title branchdialog, float on" - "match:class pavucontrol-qt, float on" - "match:class pavucontrol, float on" - "match:class class:^(espanso)$, float on" - "match:class wlogout, fullscreen on" - "match:title wlogout, float on" - "match:title wlogout, fullscreen on" - "match:class mpv, float on" - "match:class mpv, idle_inhibit focus" - "match:class mpv, opacity 1.0 override" - "match:title ^(Media viewer)$, float on" - "match:title ^(Volume Control)$, float on" - "match:title ^(Picture-in-Picture)$, float on" - "match:title ^(floating-pomodoro)$, float on" - "match:title ^(floating-pomodoro)$, size 250 50" - "match:title ^(floating-pomodoro)$, move 12 (monitor_h-150)" - "match:title ^(floating-pomodoro)$, pin on" - "match:initial_title .*streamlabs.com.*, float on" - "match:initial_title .*streamlabs.com.*, pin on" - "match:initial_title .*streamlabs.com.*, size 800 400" - "match:initial_title .*alert-box.*, move 100%-820 102" - "match:initial_title .*chat-box.*, move 100%-820 512" - "match:initial_title .*streamlabs.com.*, opacity 0.5 override" - "match:initial_title .*streamlabs.com.*, idle_inhibit focus" - "match:initial_title .*streamlabs.com.*, no_anim on" - "match:initial_title .*streamlabs.com.*, decorate off" - "match:initial_title .*streamlabs.com.*, no_shadow on" - "match:initial_title .*streamlabs.com.*, no_blur on" - "match:class ^vibe-typer$, match:title ^Recording Indicator$, no_blur on" - "match:class ^vibe-typer$, match:title ^Recording Indicator$, no_shadow on" - "match:class ^vibe-typer$, match:title ^Recording Indicator$, no_anim on" - "match:class ^vibe-typer$, match:title ^Recording Indicator$, border_size 0" - "match:class ^vibe-typer$, match:title ^Recording Indicator$, no_focus on" - "border_color rgb(ffffff), match:xwayland 1" + curve = { + _args = [ + "myBezier" + (lua ''{ type = "bezier", points = { { 0.05, 0.9 }, { 0.1, 1.05 } } }'') + ]; + }; + + animation = [ + { + leaf = "windows"; + enabled = true; + speed = 7; + bezier = "myBezier"; + } + { + leaf = "windowsOut"; + enabled = true; + speed = 7; + bezier = "default"; + style = "popin 80%"; + } + { + leaf = "border"; + enabled = true; + speed = 10; + bezier = "default"; + } + { + leaf = "borderangle"; + enabled = true; + speed = 8; + bezier = "default"; + } + { + leaf = "fade"; + enabled = true; + speed = 7; + bezier = "default"; + } + { + leaf = "workspaces"; + enabled = true; + speed = 6; + bezier = "default"; + } ]; - "$mainMod" = "SUPER"; - "$terminal" = "ghostty"; - - bind = [ - # "$mainMod, return, exec, $terminal nu -c zellij-ps" - "$mainMod, t, exec, $terminal -e nu -c 'nitch; exec nu'" - "$mainMod SHIFT, t, exec, launch-timer" - "$mainMod, n, exec, $terminal -e nvim" - "$mainMod, z, exec, uwsm app -- zeditor" - "$mainMod, o, exec, hyprctl dispatch setprop activewindow opaque toggle" - "$mainMod, r, exec, hyprctl dispatch focuswindow \"initialtitle:.*alert-box.*\" && hyprctl dispatch moveactive exact 4300 102 && hyprctl dispatch focuswindow \"initialtitle:.*chat-box.*\" && hyprctl dispatch moveactive exact 4300 512" - "$mainMod, b, exec, uwsm app -- thunar" - "$mainMod SHIFT, B, exec, uwsm app -- vivaldi" - "$mainMod, Escape, exec, uwsm app -- dms ipc call powermenu toggle" - # "$mainMod, Space, togglefloating" - "$mainMod, q, killactive" - "$mainMod, M, exit" - "$mainMod, F, fullscreen" - "$mainMod SHIFT, V, togglefloating" - "$mainMod, D, exec, uwsm app -- dms ipc call spotlight toggle" - "$mainMod, V, exec, uwsm app -- dms ipc call clipboard toggle" - "$mainMod, C, exec, bash -c 'FILE=/tmp/screenshot_$(date +%s).png; grim -g \"$(slurp)\" \"$FILE\" && ksnip \"$FILE\"'" - "$mainMod SHIFT, S, exec, uwsm app -- rofi -show emoji" - "$mainMod, P, exec, uwsm app -- rofi-pass" - "$mainMod SHIFT, P, pseudo" - "$mainMod, R, exec, stt-ptt start" - "$mainMod, S, exec, stt-ptt start" - # "$mainMod, J, togglesplit" # TODO - "$mainMod, h, movefocus, l" - "$mainMod, l, movefocus, r" - "$mainMod, k, movefocus, u" - "$mainMod, j, movefocus, d" - "$mainMod, 1, workspace, 1" - "$mainMod, 2, workspace, 2" - "$mainMod, 3, workspace, 3" - "$mainMod, 4, workspace, 4" - "$mainMod, 5, workspace, 5" - "$mainMod, 6, workspace, 6" - "$mainMod, 7, workspace, 7" - "$mainMod, 8, workspace, 8" - "$mainMod, 9, workspace, 9" - "$mainMod, 0, workspace, 10" - "$mainMod SHIFT, 1, movetoworkspace, 1" - "$mainMod SHIFT, 2, movetoworkspace, 2" - "$mainMod SHIFT, 3, movetoworkspace, 3" - "$mainMod SHIFT, 4, movetoworkspace, 4" - "$mainMod SHIFT, 5, movetoworkspace, 5" - "$mainMod SHIFT, 6, movetoworkspace, 6" - "$mainMod SHIFT, 7, movetoworkspace, 7" - "$mainMod SHIFT, 8, movetoworkspace, 8" - "$mainMod SHIFT, 9, movetoworkspace, 9" - "$mainMod SHIFT, 0, movetoworkspace, 10" - "$mainMod, mouse_down, workspace, e+1" - "$mainMod, mouse_up, workspace, e-1" + window_rule = [ + { + match.class = "file_progress"; + float = true; + } + { + match.class = "confirm"; + float = true; + } + { + match.class = "dialog"; + float = true; + } + { + match.class = "download"; + float = true; + } + { + match.class = "notification"; + float = true; + } + { + match.class = "error"; + float = true; + } + { + match.class = "splash"; + float = true; + } + { + match.class = "confirmreset"; + float = true; + } + { + match.title = "Open File"; + float = true; + } + { + match.title = "branchdialog"; + float = true; + } + { + match.class = "pavucontrol-qt"; + float = true; + } + { + match.class = "pavucontrol"; + float = true; + } + { + match.class = "class:^(espanso)$"; + float = true; + } + { + match.class = "wlogout"; + fullscreen = true; + } + { + match.title = "wlogout"; + float = true; + } + { + match.title = "wlogout"; + fullscreen = true; + } + { + match.class = "mpv"; + float = true; + } + { + match.class = "mpv"; + idle_inhibit = "focus"; + } + { + match.class = "mpv"; + opacity = "1.0 override"; + } + { + match.title = "^(Media viewer)$"; + float = true; + } + { + match.title = "^(Volume Control)$"; + float = true; + } + { + match.title = "^(Picture-in-Picture)$"; + float = true; + } + { + match.title = "^(floating-pomodoro)$"; + float = true; + } + { + match.title = "^(floating-pomodoro)$"; + size = "250 50"; + } + { + match.title = "^(floating-pomodoro)$"; + move = "12 (monitor_h-150)"; + } + { + match.title = "^(floating-pomodoro)$"; + pin = true; + } + { + match.initial_title = ".*streamlabs.com.*"; + float = true; + } + { + match.initial_title = ".*streamlabs.com.*"; + pin = true; + } + { + match.initial_title = ".*streamlabs.com.*"; + size = "800 400"; + } + { + match.initial_title = ".*alert-box.*"; + move = "100%-820 102"; + } + { + match.initial_title = ".*chat-box.*"; + move = "100%-820 512"; + } + { + match.initial_title = ".*streamlabs.com.*"; + opacity = "0.5 override"; + } + { + match.initial_title = ".*streamlabs.com.*"; + idle_inhibit = "focus"; + } + { + match.initial_title = ".*streamlabs.com.*"; + no_anim = true; + } + { + match.initial_title = ".*streamlabs.com.*"; + decorate = false; + } + { + match.initial_title = ".*streamlabs.com.*"; + no_shadow = true; + } + { + match.initial_title = ".*streamlabs.com.*"; + no_blur = true; + } + { + match = { + class = "^vibe-typer$"; + title = "^Recording Indicator$"; + }; + no_blur = true; + } + { + match = { + class = "^vibe-typer$"; + title = "^Recording Indicator$"; + }; + no_shadow = true; + } + { + match = { + class = "^vibe-typer$"; + title = "^Recording Indicator$"; + }; + no_anim = true; + } + { + match = { + class = "^vibe-typer$"; + title = "^Recording Indicator$"; + }; + border_size = 0; + } + { + match = { + class = "^vibe-typer$"; + title = "^Recording Indicator$"; + }; + no_focus = true; + } + { + match.xwayland = true; + border_color = "rgb(ffffff)"; + } ]; - bindr = [ - ]; - - bindm = [ - "$mainMod, mouse:272, movewindow" - "$mainMod, mouse:273, resizewindow" + "bind" = [ + # mainMod + return intentionally remains disabled from the previous config. + (mkBinding (modKey "t") (execExpr ''terminal .. " -e nu -c 'nitch; exec nu'"'')) + (mkBinding (modKey "SHIFT + t") (execCmd "launch-timer")) + (mkBinding (modKey "n") (execExpr ''terminal .. " -e nvim"'')) + (mkBinding (modKey "z") (execCmd "uwsm app -- zeditor")) + (mkBinding (modKey "o") ''hl.dsp.window.set_prop({ prop = "opaque", value = "toggle" })'') + (mkBinding (modKey "r") ( + execCmd ''hyprctl dispatch focuswindow "initialtitle:.*alert-box.*" && hyprctl dispatch moveactive exact 4300 102 && hyprctl dispatch focuswindow "initialtitle:.*chat-box.*" && hyprctl dispatch moveactive exact 4300 512'' + )) + (mkBinding (modKey "b") (execCmd "uwsm app -- thunar")) + (mkBinding (modKey "SHIFT + B") (execCmd "uwsm app -- vivaldi")) + (mkBinding (modKey "Escape") (execCmd "uwsm app -- dms ipc call powermenu toggle")) + (mkBinding (modKey "q") "hl.dsp.window.close()") + (mkBinding (modKey "M") "hl.dsp.exit()") + (mkBinding (modKey "F") "hl.dsp.window.fullscreen({})") + (mkBinding (modKey "SHIFT + V") ''hl.dsp.window.float({ action = "toggle" })'') + (mkBinding (modKey "D") (execCmd "uwsm app -- dms ipc call spotlight toggle")) + (mkBinding (modKey "V") (execCmd "uwsm app -- dms ipc call clipboard toggle")) + (mkBinding (modKey "C") ( + execCmd "bash -c 'FILE=/tmp/screenshot_$(date +%s).png; grim -g \"$(slurp)\" \"$FILE\" && ksnip \"$FILE\"'" + )) + (mkBinding (modKey "SHIFT + S") (execCmd "uwsm app -- rofi -show emoji")) + (mkBinding (modKey "P") (execCmd "uwsm app -- rofi-pass")) + (mkBinding (modKey "SHIFT + P") "hl.dsp.window.pseudo({})") + (mkBinding (modKey "R") (execCmd "stt-ptt start")) + (mkBinding (modKey "S") (execCmd "stt-ptt start")) + (mkBinding (modKey "h") ''hl.dsp.focus({ direction = "l" })'') + (mkBinding (modKey "l") ''hl.dsp.focus({ direction = "r" })'') + (mkBinding (modKey "k") ''hl.dsp.focus({ direction = "u" })'') + (mkBinding (modKey "j") ''hl.dsp.focus({ direction = "d" })'') + (mkBinding (modKey "1") (focusWorkspace "1")) + (mkBinding (modKey "2") (focusWorkspace "2")) + (mkBinding (modKey "3") (focusWorkspace "3")) + (mkBinding (modKey "4") (focusWorkspace "4")) + (mkBinding (modKey "5") (focusWorkspace "5")) + (mkBinding (modKey "6") (focusWorkspace "6")) + (mkBinding (modKey "7") (focusWorkspace "7")) + (mkBinding (modKey "8") (focusWorkspace "8")) + (mkBinding (modKey "9") (focusWorkspace "9")) + (mkBinding (modKey "0") (focusWorkspace "10")) + (mkBinding (modKey "SHIFT + 1") (moveToWorkspace "1")) + (mkBinding (modKey "SHIFT + 2") (moveToWorkspace "2")) + (mkBinding (modKey "SHIFT + 3") (moveToWorkspace "3")) + (mkBinding (modKey "SHIFT + 4") (moveToWorkspace "4")) + (mkBinding (modKey "SHIFT + 5") (moveToWorkspace "5")) + (mkBinding (modKey "SHIFT + 6") (moveToWorkspace "6")) + (mkBinding (modKey "SHIFT + 7") (moveToWorkspace "7")) + (mkBinding (modKey "SHIFT + 8") (moveToWorkspace "8")) + (mkBinding (modKey "SHIFT + 9") (moveToWorkspace "9")) + (mkBinding (modKey "SHIFT + 0") (moveToWorkspace "10")) + (mkBinding (modKey "mouse_down") (focusWorkspace "e+1")) + (mkBinding (modKey "mouse_up") (focusWorkspace "e-1")) + (mkBindingWithOptions (modKey "mouse:272") "hl.dsp.window.drag()" {mouse = true;}) + (mkBindingWithOptions (modKey "mouse:273") "hl.dsp.window.resize()" {mouse = true;}) ]; }; }; From 516f9d74e0be79dfa5fc29c98f2d1e5b04fdf4eb Mon Sep 17 00:00:00 2001 From: m3tam3re Date: Sun, 2 Aug 2026 13:41:01 +0200 Subject: [PATCH 2/3] chore: -aionui --- flake.lock | 16 ++++++++-------- profiles/sets/coding/agents/agents.nix | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index c82519f..6468bc6 100644 --- a/flake.lock +++ b/flake.lock @@ -99,16 +99,16 @@ ] }, "locked": { - "lastModified": 1774505501, - "narHash": "sha256-7UiRrDptj7yuEFwToOfdunUMz/i3jRLR7CmMoYQjq6k=", + "lastModified": 1785348116, + "narHash": "sha256-AVycTcomtfvQJ/AHvMg5xu7lVoOzDXxjN+pV7mqUIQ4=", "owner": "basecamp", "repo": "basecamp-cli", - "rev": "f087e6ef84002503d0dbc75ea1c8c928a8928d9e", + "rev": "e1059fb123a03295ce6176272e4bbaf43d7971c6", "type": "github" }, "original": { "owner": "basecamp", - "ref": "v0.7.2", + "ref": "v0.8.0-rc.1", "repo": "basecamp-cli", "type": "github" } @@ -314,11 +314,11 @@ "openspec": "openspec" }, "locked": { - "lastModified": 1785395945, - "narHash": "sha256-/J1bkZi7tb+DxUN3G9bJBCxaJpG4373L+AjxF8SoX9M=", + "lastModified": 1785670526, + "narHash": "sha256-tC1CW+Kxh9ZZxJC0y472i0KoieMqNwNi+AiCmS4n7To=", "ref": "refs/heads/master", - "rev": "e3ebb76b1c26ecc3311d65b25fa38d70313b6804", - "revCount": 371, + "rev": "69fce234a8607cd3e71233831564b8ceeba70626", + "revCount": 374, "type": "git", "url": "ssh://gitea@code.m3ta.dev/m3tam3re/nixpkgs" }, diff --git a/profiles/sets/coding/agents/agents.nix b/profiles/sets/coding/agents/agents.nix index d607afb..6181025 100644 --- a/profiles/sets/coding/agents/agents.nix +++ b/profiles/sets/coding/agents/agents.nix @@ -64,7 +64,6 @@ home.packages = with pkgs; [ agenix-cli agent-browser - aionui m3taHomeInputs.agent-lib.packages.${pkgs.stdenv.hostPlatform.system}.agent-lib-cli beads crunch From 0db970c16105550061809a54b94afc7b1f469ce3 Mon Sep 17 00:00:00 2001 From: m3tam3re Date: Sun, 2 Aug 2026 16:34:20 +0200 Subject: [PATCH 3/3] feat: docker-sbx --- profiles/sets/coding/agents/agents.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/profiles/sets/coding/agents/agents.nix b/profiles/sets/coding/agents/agents.nix index 6181025..fe87bf3 100644 --- a/profiles/sets/coding/agents/agents.nix +++ b/profiles/sets/coding/agents/agents.nix @@ -67,6 +67,7 @@ m3taHomeInputs.agent-lib.packages.${pkgs.stdenv.hostPlatform.system}.agent-lib-cli beads crunch + docker-sbx herdr pi-coding-agent (qmd.override {