{ inputs, getFlakePkg', lib, pkgs, config, ... }: let inherit (config) rice; niri = getFlakePkg' inputs.niri "niri-unstable"; xwayland-satellite = getFlakePkg' inputs.niri "xwayland-satellite-unstable"; niri-session-direct = pkgs.writeShellScript "niri-session-direct" '' systemctl --user import-environment dbus-update-activation-environment --all systemctl --user start niri-session-bridge.service & exec ${lib.getExe niri} --session ''; in { imports = [ inputs.niri-tag.nixosModules.niri-tag inputs.niri-s76.nixosModules.default ]; user.desktops.niri = { enable = true; config = let template = builtins.readFile ./niri.kdl; baseConfig = with rice; lib.replaceStrings [ "%CURSOR%" "%ROUNDING%" "%GAPS%" "%BORDER%" "%ACTIVE%" "%INACTIVE%" "%SATELLITE%" ] [ cursor.name (toString borders.rounding) (toString borders.gaps) (toString borders.thickness) palette.shortHex.bright.yellow palette.shortHex.normal.white (lib.getExe xwayland-satellite) ] template; in baseConfig; }; environment.systemPackages = [ niri xwayland-satellite ]; environment.etc."greetd/wayland-sessions/niri.desktop".text = '' [Desktop Entry] Name=Niri Comment=A scrollable-tiling Wayland compositor Exec=${niri-session-direct} Type=Application DesktopNames=niri ''; programs.niri = { enable = true; package = niri; }; services.niri-tag = { enable = true; prepopulate = 10; strict = true; scratchpads = { "chrome-listen.lobotomise.me__-Default" = 99; "Bitwarden" = 101; }; }; services.niri-s76-bridge.enable = true; # niri runs directly from greetd (not as a user service), # so that it stays inside the logind session scope for proper polkit/dbus access. systemd.user.services.niri.wantedBy = lib.mkForce [ ]; systemd.user.services.niri.enable = lib.mkForce false; # bridge service to activate graphical-session.target for the direct-launched niri. # waits for niri IPC readiness before pulling in the target. systemd.user.services.niri-session-bridge = { unitConfig = { Description = "Activate graphical-session.target for direct-launched niri"; BindsTo = [ "graphical-session.target" ]; Before = [ "graphical-session.target" ]; Wants = [ "graphical-session-pre.target" ]; After = [ "graphical-session-pre.target" ]; }; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStart = "${lib.getExe niri} msg version"; }; }; }