diff --git a/flake.lock b/flake.lock
index 3e54286..aef6c4d 100644
--- a/flake.lock
+++ b/flake.lock
@@ -156,11 +156,11 @@
         "nixpkgs-stable": "nixpkgs-stable_2"
       },
       "locked": {
-        "lastModified": 1736215843,
-        "narHash": "sha256-xFcqxrwIBTI+V1XG5BBW3Eg2IAESLq2abFnE+rWc8Vk=",
+        "lastModified": 1736327656,
+        "narHash": "sha256-vDli473KKyf13uexB4Ja9Jt7KmeUSbHbeuwIDP0M2yM=",
         "owner": "nix-community",
         "repo": "emacs-overlay",
-        "rev": "c4b02b4be54b35b6bf0cd6b33ef01e33b5a041af",
+        "rev": "42b7368d193ad1939c32e87b48e970423f22f242",
         "type": "github"
       },
       "original": {
@@ -582,11 +582,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1736204492,
-        "narHash": "sha256-CoBPRgkUex9Iz6qGSzi/BFVUQjndB0PmME2B6eEyeCs=",
+        "lastModified": 1736336279,
+        "narHash": "sha256-9Xp2X7ofKY4h39vUbd4coNambsG7Y/9axLFyTXaXOMU=",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "20665c6efa83d71020c8730f26706258ba5c6b2a",
+        "rev": "45bcdbc910dc5131943bb6f7edb156617898fd1a",
         "type": "github"
       },
       "original": {
@@ -687,11 +687,11 @@
     "lix": {
       "flake": false,
       "locked": {
-        "lastModified": 1736036352,
-        "narHash": "sha256-bJzjEWrsGJJTaYfScHfwCG4dXbHXyXQ604kvbWc/3Fg=",
+        "lastModified": 1736275188,
+        "narHash": "sha256-IWu1aN1MeRCtx0PYIKTvG5iDSOx/JVegm4Y+0lAZGTE=",
         "ref": "refs/heads/main",
-        "rev": "8c1ece93cc21b7c2fff4031b4de7a40d919bf4eb",
-        "revCount": 16603,
+        "rev": "3413ab56292f12ac03ee49270bcaf16038020cb3",
+        "revCount": 16605,
         "type": "git",
         "url": "https://git@git.lix.systems/lix-project/lix"
       },
@@ -900,11 +900,11 @@
     },
     "nixosHardware": {
       "locked": {
-        "lastModified": 1736237814,
-        "narHash": "sha256-uTdscVaKjnRnBIMuu/oWwdiGhYd/JOQ4YZGHeCoroqs=",
+        "lastModified": 1736283893,
+        "narHash": "sha256-BG1FfTexFwNty5VhYjaQLMR6CMPfI3QRcaZrFQYu2EM=",
         "owner": "NixOS",
         "repo": "nixos-hardware",
-        "rev": "ca30f8501ab452ca687a7fdcb2d43e1fb1732317",
+        "rev": "4f339f6be2b61662f957c2ee9eda0fa597d8a6d6",
         "type": "github"
       },
       "original": {
@@ -1009,11 +1009,11 @@
     },
     "nixpkgs-stable_2": {
       "locked": {
-        "lastModified": 1736061677,
-        "narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=",
+        "lastModified": 1736200483,
+        "narHash": "sha256-JO+lFN2HsCwSLMUWXHeOad6QUxOuwe9UOAF/iSl1J4I=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36",
+        "rev": "3f0a8ac25fb674611b98089ca3a5dd6480175751",
         "type": "github"
       },
       "original": {
diff --git a/hmModules/emacs/default.nix b/hmModules/emacs/default.nix
index b1d061c..ffeeb43 100644
--- a/hmModules/emacs/default.nix
+++ b/hmModules/emacs/default.nix
@@ -52,23 +52,12 @@ in
       en_US-large
       it_IT
     ]);
-  home.activation.cloneCcrEmacsFlake =
-    let
-      path = lib.makeBinPath (
-        with pkgs;
-        [
-          git
-          openssh
-        ]
-      );
-    in
-    lib.hm.dag.entryAfter [ "writeBoundary" ] ''
-      PATH=$PATH:${path}
-      if [ ! -d "$HOME/.config/emacs" ]; then
-        mkdir "$HOME/.config/emacs"
-          $DRY_RUN_CMD ln -s "$HOME/projects/aciceri/nixfleet/hmModules/emacs/init.el" "$HOME/.config/emacs/init.el"
-          $DRY_RUN_CMD ln -s "$HOME/.config/emacs" "$HOME/emacs"
-        fi
-      $DRY_RUN_CMD ln -sfn ${treesitGrammars} "$HOME/.config/emacs/tree-sitter"
-    '';
+  home.activation.linkEmacsConfig = lib.hm.dag.entryAnywhere ''
+    if [ ! -d "$HOME/.config/emacs" ]; then
+      $DRY_RUN_CMD mkdir "$HOME/.config/emacs"
+      $DRY_RUN_CMD ln -s "$HOME/projects/aciceri/nixfleet/hmModules/emacs/init.el" "$HOME/.config/emacs/init.el"
+      $DRY_RUN_CMD ln -s "$HOME/.config/emacs" "$HOME/emacs"
+    fi
+    $DRY_RUN_CMD ln -sfn ${treesitGrammars} "$HOME/.config/emacs/tree-sitter"
+  '';
 }
diff --git a/hmModules/emacs/init.el b/hmModules/emacs/init.el
index f33aa1d..68ba3d2 100644
--- a/hmModules/emacs/init.el
+++ b/hmModules/emacs/init.el
@@ -507,6 +507,9 @@
 (use-package dockerfile-ts-mode
   :mode "Dockerfile\\'")
 
+(use-package lean4-mode
+  :mode "\\.lean\\'")
+
 (use-package python-ts-mode
   :hook ((python-ts-mode . (lambda ()
 			     (require 'eglot)
@@ -559,6 +562,9 @@
 (use-package sh-mode
   :hook (sh-mode . bash-ts-mode))
 
+(use-package kdl-ts-mode
+  :mode "\\.kdl\\'")
+
 (use-package gptscript-mode
   :mode "\\.gpt\\'")
 
@@ -1006,24 +1012,26 @@ This is meant to be an helper to be called from the window manager."
 
 ;;; Experiments, remove from here
 
+
 (defun ccr/test ()
   "test"
   (interactive)
   (with-selected-frame 
-      (make-frame '((name . "emacs-run-launcher")
+      (make-frame '((name . "floating")
                     (minibuffer . only)
-                    (fullscreen . 0) ; no fullscreen
-                    (undecorated . t) ; remove title bar
+                    (fullscreen . 0)	; no fullscreen
+                    (undecorated . t)	; remove title bar
                     ;;(auto-raise . t) ; focus on this frame
                     ;;(tool-bar-lines . 0)
                     ;;(menu-bar-lines . 0)
                     (internal-border-width . 10)
-                    (width . 80)
-                    (height . 11)))
+                    (width . 50)
+                    (height . 10)))
     (unwind-protect
-	(completing-read "ciao " '("foo" "bar") nil t "")
+	(completing-read "ciao " '("foo" "bar" "pippo") nil t "")
       (delete-frame))))
 
 
+
 (provide 'init)
 ;;; init.el ends here
diff --git a/hmModules/gpg/default.nix b/hmModules/gpg/default.nix
index d3aa919..a894c90 100644
--- a/hmModules/gpg/default.nix
+++ b/hmModules/gpg/default.nix
@@ -9,7 +9,7 @@
           name = "pinentry-rofi-with-env";
           runtimeInputs = with pkgs; [
             coreutils
-            rofi
+            rofi-wayland
           ];
           text = ''
             "${pkgs.pinentry-rofi}/bin/pinentry-rofi" "$@"
diff --git a/hmModules/hyprland/default.nix b/hmModules/hyprland/default.nix
index 43d5a84..2596638 100644
--- a/hmModules/hyprland/default.nix
+++ b/hmModules/hyprland/default.nix
@@ -62,7 +62,7 @@ in
     cursorTheme = {
       name = "catppuccin-mocha-sapphire";
       package = pkgs.catppuccin-cursors;
-      size = 40;
+      size = 38;
     };
   };
 
diff --git a/hmModules/niri/config.kdl b/hmModules/niri/config.kdl
new file mode 100644
index 0000000..5a3b61f
--- /dev/null
+++ b/hmModules/niri/config.kdl
@@ -0,0 +1,533 @@
+// This config is in the KDL format: https://kdl.dev
+// "/-" comments out the following node.
+// Check the wiki for a full description of the configuration:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Overview
+
+// Input device configuration.
+// Find the full list of options on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Input
+input {
+    keyboard {
+        xkb {
+            layout "us"
+            // options "grp:win_space_toggle,compose:ralt,ctrl:nocaps"
+        }
+    }
+
+    // Next sections include libinput settings.
+    // Omitting settings disables them, or leaves them at their default values.
+    touchpad {
+        // off
+        tap
+        // dwt
+        // dwtp
+        natural-scroll
+        // accel-speed 0.2
+        // accel-profile "flat"
+        // scroll-method "two-finger"
+        // disabled-on-external-mouse
+    }
+
+    mouse {
+        // off
+        // natural-scroll
+        // accel-speed 0.2
+        // accel-profile "flat"
+        // scroll-method "no-scroll"
+    }
+
+    trackpoint {
+        // off
+        // natural-scroll
+        // accel-speed 0.2
+        // accel-profile "flat"
+        // scroll-method "on-button-down"
+        // scroll-button 273
+        // middle-emulation
+    }
+
+    // Uncomment this to make the mouse warp to the center of newly focused windows.
+    warp-mouse-to-focus
+
+    // Focus windows and outputs automatically when moving the mouse into them.
+    // Setting max-scroll-amount="0%" makes it work only on windows already fully on screen.
+    focus-follows-mouse max-scroll-amount="0%"
+}
+
+cursor {
+    xcursor-theme "catppuccin-mocha-sapphire"
+    xcursor-size 38
+    hide-when-typing
+    hide-after-inactive-ms 10000
+}
+
+spawn-at-startup "xwayland-satellite"
+
+environment {
+    QT_QPA_PLATFORM "wayland"
+    DISPLAY ":0"
+}
+
+
+// You can configure outputs by their name, which you can find
+// by running `niri msg outputs` while inside a niri instance.
+// The built-in laptop monitor is usually called "eDP-1".
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Outputs
+// Remember to uncomment the node by removing "/-"!
+/-output "eDP-1" {
+    // Uncomment this line to disable this output.
+    // off
+
+    // Resolution and, optionally, refresh rate of the output.
+    // The format is "<width>x<height>" or "<width>x<height>@<refresh rate>".
+    // If the refresh rate is omitted, niri will pick the highest refresh rate
+    // for the resolution.
+    // If the mode is omitted altogether or is invalid, niri will pick one automatically.
+    // Run `niri msg outputs` while inside a niri instance to list all outputs and their modes.
+    mode "1920x1080@120.030"
+
+    // You can use integer or fractional scale, for example use 1.5 for 150% scale.
+    scale 2
+
+    // Transform allows to rotate the output counter-clockwise, valid values are:
+    // normal, 90, 180, 270, flipped, flipped-90, flipped-180 and flipped-270.
+    transform "normal"
+
+    // Position of the output in the global coordinate space.
+    // This affects directional monitor actions like "focus-monitor-left", and cursor movement.
+    // The cursor can only move between directly adjacent outputs.
+    // Output scale and rotation has to be taken into account for positioning:
+    // outputs are sized in logical, or scaled, pixels.
+    // For example, a 3840×2160 output with scale 2.0 will have a logical size of 1920×1080,
+    // so to put another output directly adjacent to it on the right, set its x to 1920.
+    // If the position is unset or results in an overlap, the output is instead placed
+    // automatically.
+    position x=1280 y=0
+}
+
+// Settings that influence how windows are positioned and sized.
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Layout
+layout {
+    // Set gaps around windows in logical pixels.
+    gaps 16
+
+    // When to center a column when changing focus, options are:
+    // - "never", default behavior, focusing an off-screen column will keep at the left
+    //   or right edge of the screen.
+    // - "always", the focused column will always be centered.
+    // - "on-overflow", focusing a column will center it if it doesn't fit
+    //   together with the previously focused column.
+    center-focused-column "never"
+
+    // You can customize the widths that "switch-preset-column-width" (Mod+R) toggles between.
+    preset-column-widths {
+        // Proportion sets the width as a fraction of the output width, taking gaps into account.
+        // For example, you can perfectly fit four windows sized "proportion 0.25" on an output.
+        // The default preset widths are 1/3, 1/2 and 2/3 of the output.
+        proportion 0.33333
+        proportion 0.5
+        proportion 0.66667
+
+        // Fixed sets the width in logical pixels exactly.
+        // fixed 1920
+    }
+
+    // You can also customize the heights that "switch-preset-window-height" (Mod+Shift+R) toggles between.
+    // preset-window-heights { }
+
+    // You can change the default width of the new windows.
+    default-column-width { proportion 0.5; }
+    // If you leave the brackets empty, the windows themselves will decide their initial width.
+    // default-column-width {}
+
+    // By default focus ring and border are rendered as a solid background rectangle
+    // behind windows. That is, they will show up through semitransparent windows.
+    // This is because windows using client-side decorations can have an arbitrary shape.
+    //
+    // If you don't like that, you should uncomment `prefer-no-csd` below.
+    // Niri will draw focus ring and border *around* windows that agree to omit their
+    // client-side decorations.
+    //
+    // Alternatively, you can override it with a window rule called
+    // `draw-border-with-background`.
+
+    // You can change how the focus ring looks.
+    focus-ring {
+        // Uncomment this line to disable the focus ring.
+        // off
+
+        // How many logical pixels the ring extends out from the windows.
+        width 2
+
+        // Colors can be set in a variety of ways:
+        // - CSS named colors: "red"
+        // - RGB hex: "#rgb", "#rgba", "#rrggbb", "#rrggbbaa"
+        // - CSS-like notation: "rgb(255, 127, 0)", rgba(), hsl() and a few others.
+
+        // Color of the ring on the active monitor.
+        active-color "#7fc8ff"
+
+        // Color of the ring on inactive monitors.
+        inactive-color "#505050"
+
+        // You can also use gradients. They take precedence over solid colors.
+        // Gradients are rendered the same as CSS linear-gradient(angle, from, to).
+        // The angle is the same as in linear-gradient, and is optional,
+        // defaulting to 180 (top-to-bottom gradient).
+        // You can use any CSS linear-gradient tool on the web to set these up.
+        // Changing the color space is also supported, check the wiki for more info.
+        //
+        // active-gradient from="#80c8ff" to="#bbddff" angle=45
+
+        // You can also color the gradient relative to the entire view
+        // of the workspace, rather than relative to just the window itself.
+        // To do that, set relative-to="workspace-view".
+        //
+        // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+    }
+
+    // You can also add a border. It's similar to the focus ring, but always visible.
+    border {
+        // The settings are the same as for the focus ring.
+        // If you enable the border, you probably want to disable the focus ring.
+        off
+
+        width 4
+        active-color "#ffc87f"
+        inactive-color "#505050"
+
+        // active-gradient from="#ffbb66" to="#ffc880" angle=45 relative-to="workspace-view"
+        // inactive-gradient from="#505050" to="#808080" angle=45 relative-to="workspace-view"
+    }
+
+    // Struts shrink the area occupied by windows, similarly to layer-shell panels.
+    // You can think of them as a kind of outer gaps. They are set in logical pixels.
+    // Left and right struts will cause the next window to the side to always be visible.
+    // Top and bottom struts will simply add outer gaps in addition to the area occupied by
+    // layer-shell panels and regular gaps.
+    struts {
+        // left 64
+        // right 64
+        // top 64
+        // bottom 64
+    }
+}
+
+// Add lines like this to spawn processes at startup.
+// Note that running niri as a session supports xdg-desktop-autostart,
+// which may be more convenient to use.
+// See the binds section below for more spawn examples.
+spawn-at-startup "waypaper" "--wallpaper" "~/.config/niri/wallpaper.png"
+
+// Uncomment this line to ask the clients to omit their client-side decorations if possible.
+// If the client will specifically ask for CSD, the request will be honored.
+// Additionally, clients will be informed that they are tiled, removing some client-side rounded corners.
+// This option will also fix border/focus ring drawing behind some semitransparent windows.
+// After enabling or disabling this, you need to restart the apps for this to take effect.
+prefer-no-csd
+
+// You can change the path where screenshots are saved.
+// A ~ at the front will be expanded to the home directory.
+// The path is formatted with strftime(3) to give you the screenshot date and time.
+screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"
+
+// You can also set this to null to disable saving screenshots to disk.
+// screenshot-path null
+
+// Animation settings.
+// The wiki explains how to configure individual animations:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Animations
+animations {
+    // Uncomment to turn off all animations.
+    // off
+
+    // Slow down all animations by this factor. Values below 1 speed them up instead.
+    // slowdown 3.0
+}
+
+// Window rules let you adjust behavior for individual windows.
+// Find more information on the wiki:
+// https://github.com/YaLTeR/niri/wiki/Configuration:-Window-Rules
+
+// Work around WezTerm's initial configure bug
+// by setting an empty default-column-width.
+window-rule {
+    // This regular expression is intentionally made as specific as possible,
+    // since this is the default config, and we want no false positives.
+    // You can get away with just app-id="wezterm" if you want.
+    match app-id=r#"^org\.wezfurlong\.wezterm$"#
+    default-column-width {}
+}
+
+// Example: block out two password managers from screen capture.
+// (This example rule is commented out with a "/-" in front.)
+/-window-rule {
+    match app-id=r#"^org\.keepassxc\.KeePassXC$"#
+    match app-id=r#"^org\.gnome\.World\.Secrets$"#
+
+    block-out-from "screen-capture"
+
+    // Use this instead if you want them visible on third-party screenshot tools.
+    // block-out-from "screencast"
+}
+
+window-rule {
+    geometry-corner-radius 4
+    clip-to-geometry true
+}
+
+window-rule {
+    match app-id=r#"^spotify$"#
+    open-maximized true
+    open-on-workspace "spotify"
+}
+
+window-rule {
+    match app-id=r#"^Slack$"#
+    open-maximized true
+}
+
+window-rule {
+    match app-id=r#"^Element"#
+    open-maximized true
+}
+
+
+
+
+
+
+binds {
+    // Keys consist of modifiers separated by + signs, followed by an XKB key name
+    // in the end. To find an XKB name for a particular key, you may use a program
+    // like wev.
+    //
+    // "Mod" is a special modifier equal to Super when running on a TTY, and to Alt
+    // when running as a winit window.
+    //
+    // Most actions that you can bind here can also be invoked programmatically with
+    // `niri msg action do-something`.
+
+    // Mod-Shift-/, which is usually the same as Mod-?,
+    // shows a list of important hotkeys.
+    Mod+Shift+Slash { show-hotkey-overlay; }
+
+    // Suggested binds for running programs: terminal, app launcher, screen locker.
+    Mod+T { spawn "footclient"; }
+    Mod+D { spawn "rofi" "-show" "drun"; }
+    Mod+W { spawn "rofi" "-show" "window"; }
+    Mod+P { spawn "rofi-pass" "--clip"; }
+    Mod+X { spawn "emacsclient" "-c"; }
+    Mod+B { spawn "firefox"; }
+    Mod+RETURN { spawn "emacsclient" "-c" "--eval" "(ccr/start-eshell)"; }
+    Mod+M { spawn "emacsclient" "-c" "--eval" "(notmuch-search \"tag:new\")"; }
+    Mod+G { spawn "emacsclient" "-c" "--eval" "(switch-to-buffer (gptel \"*ChatGPT*\"))"; }
+    Mod+Shift+C { spawn "emacsclient" "-c" "--eval" "(org-roam-dailies-capture-today)"; }
+    Super+Alt+L { spawn "swaylock"; }
+
+
+    // Example volume keys mappings for PipeWire & WirePlumber.
+    // The allow-when-locked=true property makes them work even when the session is locked.
+    XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; }
+    XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; }
+    XF86AudioMute        allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; }
+    XF86AudioMicMute     allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; }
+
+    Mod+Shift+period { spawn "brightnessctl" "s" "5%+"; }
+    Mod+Shift+comma { spawn "brightnessctl" "s" "5%-"; }
+    Mod+XF86MonBrightnessUp { spawn "brightnessctl" "s" "5%+"; }
+    Mod+XF86MonBrightnessDown { spawn "brightnessctl" "s" "5%-"; }
+
+    Mod+Q { close-window; }
+
+    Mod+Left  { focus-column-left; }
+    Mod+Down  { focus-window-down; }
+    Mod+Up    { focus-window-up; }
+    Mod+Right { focus-column-right; }
+    Mod+H     { focus-column-left; }
+    Mod+J     { focus-window-down; }
+    Mod+K     { focus-window-up; }
+    Mod+L     { focus-column-right; }
+
+    Mod+Ctrl+Left  { move-column-left; }
+    Mod+Ctrl+Down  { move-window-down; }
+    Mod+Ctrl+Up    { move-window-up; }
+    Mod+Ctrl+Right { move-column-right; }
+    Mod+Ctrl+H     { move-column-left; }
+    Mod+Ctrl+J     { move-window-down; }
+    Mod+Ctrl+K     { move-window-up; }
+    Mod+Ctrl+L     { move-column-right; }
+
+    // Alternative commands that move across workspaces when reaching
+    // the first or last window in a column.
+    // Mod+J     { focus-window-or-workspace-down; }
+    // Mod+K     { focus-window-or-workspace-up; }
+    // Mod+Ctrl+J     { move-window-down-or-to-workspace-down; }
+    // Mod+Ctrl+K     { move-window-up-or-to-workspace-up; }
+
+    Mod+Home { focus-column-first; }
+    Mod+End  { focus-column-last; }
+    Mod+Ctrl+Home { move-column-to-first; }
+    Mod+Ctrl+End  { move-column-to-last; }
+
+    Mod+Shift+Left  { focus-monitor-left; }
+    Mod+Shift+Down  { focus-monitor-down; }
+    Mod+Shift+Up    { focus-monitor-up; }
+    Mod+Shift+Right { focus-monitor-right; }
+    Mod+Shift+H     { focus-monitor-left; }
+    Mod+Shift+J     { focus-monitor-down; }
+    Mod+Shift+K     { focus-monitor-up; }
+    Mod+Shift+L     { focus-monitor-right; }
+
+    Mod+Shift+Ctrl+Left  { move-column-to-monitor-left; }
+    Mod+Shift+Ctrl+Down  { move-column-to-monitor-down; }
+    Mod+Shift+Ctrl+Up    { move-column-to-monitor-up; }
+    Mod+Shift+Ctrl+Right { move-column-to-monitor-right; }
+    Mod+Shift+Ctrl+H     { move-column-to-monitor-left; }
+    Mod+Shift+Ctrl+J     { move-column-to-monitor-down; }
+    Mod+Shift+Ctrl+K     { move-column-to-monitor-up; }
+    Mod+Shift+Ctrl+L     { move-column-to-monitor-right; }
+
+    // Alternatively, there are commands to move just a single window:
+    // Mod+Shift+Ctrl+Left  { move-window-to-monitor-left; }
+    // ...
+
+    // And you can also move a whole workspace to another monitor:
+    // Mod+Shift+Ctrl+Left  { move-workspace-to-monitor-left; }
+    // ...
+
+    Mod+Page_Down      { focus-workspace-down; }
+    Mod+Page_Up        { focus-workspace-up; }
+    Mod+U              { focus-workspace-down; }
+    Mod+I              { focus-workspace-up; }
+    Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
+    Mod+Ctrl+Page_Up   { move-column-to-workspace-up; }
+    Mod+Ctrl+U         { move-column-to-workspace-down; }
+    Mod+Ctrl+I         { move-column-to-workspace-up; }
+
+    // Alternatively, there are commands to move just a single window:
+    // Mod+Ctrl+Page_Down { move-window-to-workspace-down; }
+    // ...
+
+    Mod+Shift+Page_Down { move-workspace-down; }
+    Mod+Shift+Page_Up   { move-workspace-up; }
+    Mod+Shift+U         { move-workspace-down; }
+    Mod+Shift+I         { move-workspace-up; }
+
+    // You can bind mouse wheel scroll ticks using the following syntax.
+    // These binds will change direction based on the natural-scroll setting.
+    //
+    // To avoid scrolling through workspaces really fast, you can use
+    // the cooldown-ms property. The bind will be rate-limited to this value.
+    // You can set a cooldown on any bind, but it's most useful for the wheel.
+    Mod+WheelScrollDown      cooldown-ms=150 { focus-workspace-down; }
+    Mod+WheelScrollUp        cooldown-ms=150 { focus-workspace-up; }
+    Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
+    Mod+Ctrl+WheelScrollUp   cooldown-ms=150 { move-column-to-workspace-up; }
+
+    Mod+WheelScrollRight      { focus-column-right; }
+    Mod+WheelScrollLeft       { focus-column-left; }
+    Mod+Ctrl+WheelScrollRight { move-column-right; }
+    Mod+Ctrl+WheelScrollLeft  { move-column-left; }
+
+    // Usually scrolling up and down with Shift in applications results in
+    // horizontal scrolling; these binds replicate that.
+    Mod+Shift+WheelScrollDown      { focus-column-right; }
+    Mod+Shift+WheelScrollUp        { focus-column-left; }
+    Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
+    Mod+Ctrl+Shift+WheelScrollUp   { move-column-left; }
+
+    // Similarly, you can bind touchpad scroll "ticks".
+    // Touchpad scrolling is continuous, so for these binds it is split into
+    // discrete intervals.
+    // These binds are also affected by touchpad's natural-scroll, so these
+    // example binds are "inverted", since we have natural-scroll enabled for
+    // touchpads by default.
+    // Mod+TouchpadScrollDown { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02+"; }
+    // Mod+TouchpadScrollUp   { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.02-"; }
+
+    // You can refer to workspaces by index. However, keep in mind that
+    // niri is a dynamic workspace system, so these commands are kind of
+    // "best effort". Trying to refer to a workspace index bigger than
+    // the current workspace count will instead refer to the bottommost
+    // (empty) workspace.
+    //
+    // For example, with 2 workspaces + 1 empty, indices 3, 4, 5 and so on
+    // will all refer to the 3rd workspace.
+    Mod+1 { focus-workspace 1; }
+    Mod+2 { focus-workspace 2; }
+    Mod+3 { focus-workspace 3; }
+    Mod+4 { focus-workspace 4; }
+    Mod+5 { focus-workspace 5; }
+    Mod+6 { focus-workspace 6; }
+    Mod+7 { focus-workspace 7; }
+    Mod+8 { focus-workspace 8; }
+    Mod+9 { focus-workspace 9; }
+    Mod+Ctrl+1 { move-column-to-workspace 1; }
+    Mod+Ctrl+2 { move-column-to-workspace 2; }
+    Mod+Ctrl+3 { move-column-to-workspace 3; }
+    Mod+Ctrl+4 { move-column-to-workspace 4; }
+    Mod+Ctrl+5 { move-column-to-workspace 5; }
+    Mod+Ctrl+6 { move-column-to-workspace 6; }
+    Mod+Ctrl+7 { move-column-to-workspace 7; }
+    Mod+Ctrl+8 { move-column-to-workspace 8; }
+    Mod+Ctrl+9 { move-column-to-workspace 9; }
+
+    // Alternatively, there are commands to move just a single window:
+    // Mod+Ctrl+1 { move-window-to-workspace 1; }
+
+    // Switches focus between the current and the previous workspace.
+    // Mod+Tab { focus-workspace-previous; }
+
+    // Consume one window from the right into the focused column.
+    Mod+Comma  { consume-window-into-column; }
+    // Expel one window from the focused column to the right.
+    Mod+Period { expel-window-from-column; }
+
+    // There are also commands that consume or expel a single window to the side.
+    Mod+BracketLeft  { consume-or-expel-window-left; }
+    Mod+BracketRight { consume-or-expel-window-right; }
+
+    Mod+R { switch-preset-column-width; }
+    Mod+Shift+R { switch-preset-window-height; }
+    Mod+Ctrl+R { reset-window-height; }
+    Mod+F { maximize-column; }
+    Mod+Shift+F { fullscreen-window; }
+    Mod+C { center-column; }
+
+    // Finer width adjustments.
+    // This command can also:
+    // * set width in pixels: "1000"
+    // * adjust width in pixels: "-5" or "+5"
+    // * set width as a percentage of screen width: "25%"
+    // * adjust width as a percentage of screen width: "-10%" or "+10%"
+    // Pixel sizes use logical, or scaled, pixels. I.e. on an output with scale 2.0,
+    // set-column-width "100" will make the column occupy 200 physical screen pixels.
+    Mod+Minus { set-column-width "-10%"; }
+    Mod+Equal { set-column-width "+10%"; }
+
+    // Finer height adjustments when in column with other windows.
+    Mod+Shift+Minus { set-window-height "-10%"; }
+    Mod+Shift+Equal { set-window-height "+10%"; }
+
+    // Actions to switch layouts.
+    // Note: if you uncomment these, make sure you do NOT have
+    // a matching layout switch hotkey configured in xkb options above.
+    // Having both at once on the same hotkey will break the switching,
+    // since it will switch twice upon pressing the hotkey (once by xkb, once by niri).
+    // Mod+Space       { switch-layout "next"; }
+    // Mod+Shift+Space { switch-layout "prev"; }
+
+    Mod+S { screenshot; }
+    Mod+Ctrl+S { screenshot-window; }
+
+    // The quit action will show a confirmation dialog to avoid accidental exits.
+    Mod+Shift+E { quit; }
+    Ctrl+Alt+Delete { quit; }
+
+    // Powers off the monitors. To turn them back on, do any input like
+    // moving the mouse or pressing any other key.
+    Mod+Shift+P { power-off-monitors; }
+}
diff --git a/hmModules/niri/default.nix b/hmModules/niri/default.nix
new file mode 100644
index 0000000..c59f988
--- /dev/null
+++ b/hmModules/niri/default.nix
@@ -0,0 +1,231 @@
+{
+  pkgs,
+  lib,
+  config,
+  ...
+}:
+{
+  home.packages = with pkgs; [
+    niri
+    waypaper
+    xwayland-satellite
+  ];
+  systemd.user.targets.niri-session = {
+    Unit = {
+      Description = "Niri session";
+      BindsTo = [ "graphical-session.target" ];
+      Wants = [
+        "graphical-session-pre.target"
+        "xdg-desktop-autostart.target"
+      ];
+      After = [ "graphical-session-pre.target" ];
+      Before = [ "xdg-desktop-autostart.target" ];
+    };
+  };
+
+  home.file."${config.xdg.configHome}/niri/wallpaper.png" = {
+    source = ../hyprland/wallpaper.png;
+  };
+
+  home.activation.linkNiriConfig = lib.hm.dag.entryAnywhere ''
+    if [ ! -e "$HOME/.config/niri/config.kdl" ]; then
+      $DRY_RUN_CMD ln -s "$HOME/projects/aciceri/nixfleet/hmModules/niri/config.kdl" "$HOME/.config/niri/config.kdl"
+    fi
+  '';
+
+  programs.rofi = {
+    enable = true;
+    package = pkgs.rofi-wayland;
+    theme =
+      let
+        inherit (config.lib.formats.rasi) mkLiteral;
+        cfg = config.programs.fzf.catppuccin;
+        palette = (lib.importJSON "${config.catppuccin.sources.palette}/palette.json").${cfg.flavor}.colors;
+        selectColor = color: palette.${color}.hex;
+
+      in
+      lib.mkForce {
+        "*" = {
+          # blue = mkLiteral "#0000FF";
+          # white = mkLiteral "#FFFFFF";
+          # black = mkLiteral "#000000";
+          # grey = mkLiteral "#eeeeee";
+
+          blue = mkLiteral (selectColor "blue");
+          white = mkLiteral "#FFFFFF";
+          black = mkLiteral "#000000";
+          grey = mkLiteral "#eeeeee";
+
+          spacing = 2;
+          background-color = mkLiteral "#00000000";
+          border-color = mkLiteral "#444444FF";
+          anchor = mkLiteral "north";
+          location = mkLiteral "center";
+        };
+
+        "window" = {
+          transparency = "real";
+          background-color = mkLiteral "#00000000";
+          border = 0;
+          padding = mkLiteral "0% 0% 1em 0%";
+          x-offset = 0;
+          y-offset = mkLiteral "-10%";
+        };
+
+        "mainbox" = {
+          padding = mkLiteral "0px";
+          border = 0;
+          spacing = mkLiteral "1%";
+        };
+
+        "message" = {
+          border = 0;
+          border-radius = mkLiteral "4px";
+          padding = mkLiteral "1em";
+          background-color = mkLiteral "@white";
+          text-color = mkLiteral "@black";
+        };
+
+        "textbox normal" = {
+          text-color = mkLiteral "#002B36FF";
+          padding = 0;
+          border = 0;
+        };
+
+        "listview" = {
+          fixed-height = 1;
+          border = 0;
+          padding = mkLiteral "1em";
+          reverse = false;
+          border-radius = mkLiteral "4px";
+
+          columns = 1;
+          background-color = mkLiteral "@white";
+        };
+
+        "element" = {
+          border = 0;
+          padding = mkLiteral "2px";
+          highlight = mkLiteral "bold";
+        };
+
+        "element-text" = {
+          background-color = mkLiteral "inherit";
+          text-color = mkLiteral "inherit";
+        };
+
+        "element normal.normal" = {
+          text-color = mkLiteral "#002B36FF";
+          background-color = mkLiteral "#F5F5F500";
+        };
+
+        "element normal.urgent" = {
+          text-color = mkLiteral "#D75F00FF";
+          background-color = mkLiteral "#F5F5F5FF";
+        };
+
+        "element normal.active" = {
+          text-color = mkLiteral "#005F87FF";
+          background-color = mkLiteral "#F5F5F5FF";
+        };
+
+        "element selected.normal" = {
+          text-color = mkLiteral "#F5F5F5FF";
+          background-color = mkLiteral "#4271AEFF";
+        };
+
+        "element selected.urgent" = {
+          text-color = mkLiteral "#F5F5F5FF";
+          background-color = mkLiteral "#D75F00FF";
+        };
+
+        "element selected.active" = {
+          text-color = mkLiteral "#F5F5F5FF";
+          background-color = mkLiteral "#005F87FF";
+        };
+
+        "element alternate.normal" = {
+          text-color = mkLiteral "#002B36FF";
+          background-color = mkLiteral "#D0D0D0FF";
+        };
+
+        "element alternate.urgent" = {
+          text-color = mkLiteral "#D75F00FF";
+          background-color = mkLiteral "#D0D0D0FF";
+        };
+
+        "element alternate.active" = {
+          text-color = mkLiteral "#005F87FF";
+          background-color = mkLiteral "#D0D0D0FF";
+        };
+
+        "scrollbar" = {
+          border = 0;
+          padding = 0;
+        };
+
+        "inputbar" = {
+          spacing = 0;
+          border = 0;
+          padding = mkLiteral "0.5em 1em";
+          background-color = mkLiteral "@grey";
+          index = 0;
+
+          border-radius = mkLiteral "4px";
+
+          children = map mkLiteral [
+            "prompt"
+            "textbox-prompt-colon"
+            "entry"
+            "case-indicator"
+          ];
+        };
+
+        "inputbar normal" = {
+          foreground-color = mkLiteral "#002B36FF";
+          background-color = mkLiteral "#F5F5F500";
+        };
+
+        "mode-switcher" = {
+          border = 0;
+          padding = mkLiteral "0.5em 1em";
+          background-color = mkLiteral "@grey";
+          index = 10;
+        };
+
+        "button selected" = {
+          text-color = mkLiteral "#4271AEFF";
+        };
+
+        "textbox-prompt-colon" = {
+          expand = false;
+          str = ":";
+          margin = mkLiteral "0px 0.3em 0em 0em";
+          text-color = mkLiteral "@black";
+        };
+
+        "error-message" = {
+          border = 0;
+          border-radius = mkLiteral "4px";
+          padding = mkLiteral "1em";
+          background-color = mkLiteral "#FF8888";
+          text-color = mkLiteral "@black";
+        };
+      };
+    extraConfig = {
+      modi = "drun,window,ssh";
+      combi-modes = [
+        "drun"
+        "window"
+        "ssh"
+      ];
+    };
+    font = "Iosevka Comfy 12";
+    terminal = "footclient";
+    pass = {
+      enable = true;
+      package = pkgs.rofi-pass-wayland;
+    };
+    plugins = [ pkgs.rofi-calc ];
+  };
+}
diff --git a/hmModules/swayidle/default.nix b/hmModules/swayidle/default.nix
index 60e3ed0..ccd150b 100644
--- a/hmModules/swayidle/default.nix
+++ b/hmModules/swayidle/default.nix
@@ -52,6 +52,6 @@
   # Otherwise it will start only after Sway and will not work with Hyprland
   systemd.user.services.swayidle = {
     Unit.PartOf = lib.mkForce [ ];
-    Install.WantedBy = lib.mkForce [ "hyprland-session.target" ];
+    Install.WantedBy = lib.mkForce [ "graphical-session-pre.target" ];
   };
 }
diff --git a/hmModules/waybar/default.nix b/hmModules/waybar/default.nix
index 5705986..5bd7bb9 100644
--- a/hmModules/waybar/default.nix
+++ b/hmModules/waybar/default.nix
@@ -18,8 +18,12 @@
         modules-left = [
           "wlr/mode"
           "hyprland/workspaces"
+          "niri/workspaces"
+        ];
+        modules-center = [
+          "hyprland/window"
+          "niri/window"
         ];
-        modules-center = [ "wlr/window" ];
         modules-right = [
           "network"
           "tray"
diff --git a/hmModules/zellij/default.nix b/hmModules/zellij/default.nix
index 45a8487..9e75788 100644
--- a/hmModules/zellij/default.nix
+++ b/hmModules/zellij/default.nix
@@ -9,7 +9,7 @@ let
     url = "https://github.com/dj95/zjstatus/releases/download/v0.17.0/zjstatus.wasm";
     hash = "sha256-IgTfSl24Eap+0zhfiwTvmdVy/dryPxfEF7LhVNVXe+U=";
   };
-  cfg = config.programs.fzf.catppuccin;
+  cfg = config.catppuccin.fzf;
   palette = (lib.importJSON "${config.catppuccin.sources.palette}/palette.json").${cfg.flavor}.colors;
   selectColor = color: palette.${color}.hex;
   color_fg = selectColor "text";
diff --git a/hosts/default.nix b/hosts/default.nix
index 7488615..9b4c7c9 100644
--- a/hosts/default.nix
+++ b/hosts/default.nix
@@ -73,7 +73,6 @@
           inputs.catppuccin.nixosModules.catppuccin
         ];
         extraHmModules = [
-          # inputs.ccrEmacs.hmModules.default
           "${inputs.homeManagerGitWorkspace}/modules/services/git-workspace.nix"
           inputs.vscode-server.nixosModules.home
           inputs.catppuccin.homeManagerModules.catppuccin
diff --git a/hosts/kirk/default.nix b/hosts/kirk/default.nix
index 1e60076..ad2ad2e 100644
--- a/hosts/kirk/default.nix
+++ b/hosts/kirk/default.nix
@@ -54,6 +54,7 @@
       "password-store"
       "slack"
       "hyprland"
+      "niri"
       "udiskie"
       "xdg"
       "spotify"
diff --git a/hosts/picard/default.nix b/hosts/picard/default.nix
index 42bf4f9..13cbb3b 100644
--- a/hosts/picard/default.nix
+++ b/hosts/picard/default.nix
@@ -62,6 +62,7 @@
       "password-store"
       "slack"
       "hyprland"
+      "niri"
       "udiskie"
       "xdg"
       "spotify"
@@ -91,6 +92,7 @@
       "vial"
       "chirp"
       "sdrangel"
+      "discord"
     ];
     extraGroups = [ "plugdev" ];
     backupPaths = [ ];
diff --git a/modules/greetd/default.nix b/modules/greetd/default.nix
index 5a6e826..2f9707e 100644
--- a/modules/greetd/default.nix
+++ b/modules/greetd/default.nix
@@ -23,6 +23,15 @@ let
         Exec=cosmic-session
       '';
     })
+    (pkgs.writeTextFile {
+      name = "xorg-session.desktop";
+      destination = "/niri-session.desktop";
+      text = ''
+        [Desktop Entry]
+        Name=Niri
+        Exec=${lib.getExe' pkgs.niri "niri-session"}
+      '';
+    })
   ];
 in
 {
diff --git a/modules/xdg/default.nix b/modules/xdg/default.nix
index c1aa55a..8aaabf7 100644
--- a/modules/xdg/default.nix
+++ b/modules/xdg/default.nix
@@ -7,11 +7,13 @@
         xdg-desktop-portal-wlr
         xdg-desktop-portal-gtk
         xdg-desktop-portal-hyprland
+        xdg-desktop-portal-gnome
       ];
       extraPortals = with pkgs; [
         xdg-desktop-portal-wlr
         xdg-desktop-portal-gtk
         xdg-desktop-portal-hyprland
+        xdg-desktop-portal-gnome
       ];
       xdgOpenUsePortal = true;
       wlr.enable = true;
diff --git a/packages/emacs/default.nix b/packages/emacs/default.nix
index 9bb0125..cfff445 100644
--- a/packages/emacs/default.nix
+++ b/packages/emacs/default.nix
@@ -11,7 +11,12 @@ let
       inputs.emacs-overlay.overlays.emacs
     ]
   );
-  all-grammars = pkgs'.tree-sitter.withPlugins builtins.attrValues;
+  pkgs-with-tree-sitter-kdl =
+    (builtins.getFlake "github:aciceri/nixpkgs/23a675ee8313427610cf129dd2b52a69bf6a2a26")
+    .legacyPackages.${pkgs.stdenv.system};
+  # TODO remove when merged: https://github.com/NixOS/nixpkgs/pull/371287/files
+  # all-grammars = pkgs'.tree-sitter.withPlugins builtins.attrValues;
+  all-grammars = pkgs-with-tree-sitter-kdl.tree-sitter.withPlugins builtins.attrValues;
   treesitGrammars = pkgs'.runCommand "treesit-grammars" { } ''
     mkdir $out
     for f in ${all-grammars}/*
diff --git a/packages/emacs/packages.nix b/packages/emacs/packages.nix
index 9abb207..a3d9f0d 100644
--- a/packages/emacs/packages.nix
+++ b/packages/emacs/packages.nix
@@ -10,6 +10,7 @@ let
       version = args.src.rev;
       propagatedUserEnvPkgs = args.deps;
       buildInputs = args.deps;
+      postInstall = args.postInstall or "";
     };
 
   # *Attrset* containig extra emacs packages
@@ -60,6 +61,33 @@ let
         f
       ];
     };
+    lean4-mode = buildEmacsPackage {
+      name = "lean4-mode";
+      src = pkgs.fetchFromGitHub {
+        owner = "leanprover-community";
+        repo = "lean4-mode";
+        rev = "76895d8939111654a472cfc617cfd43fbf5f1eb6";
+        hash = "sha256-DLgdxd0m3SmJ9heJ/pe5k8bZCfvWdaKAF0BDYEkwlMQ=";
+      };
+      deps = [
+        epkgs.dash
+        melpaPackages.magit
+        melpaPackages.lsp-mode
+      ];
+      postInstall = ''
+        cp -r $src/data $LISPDIR
+      '';
+    };
+    kdl-ts-mode = buildEmacsPackage {
+      name = "kdl-ts-mode";
+      src = pkgs.fetchFromGitHub {
+        owner = "dataphract";
+        repo = "kdl-ts-mode";
+        rev = "3dbf116cd19261d8d70f456ae3385e1d20208452";
+        hash = "sha256-4bfKUzzLhBFg4TeGQD0dClumcO4caIBU8/uRncFVVFQ=";
+      };
+      deps = [ ];
+    };
   };
 
   # *List* containing emacs packages from (M)ELPA