diff --git a/hmModules/foot/default.nix b/hmModules/foot/default.nix
index a40f2a5..1d46469 100644
--- a/hmModules/foot/default.nix
+++ b/hmModules/foot/default.nix
@@ -43,7 +43,7 @@ lib.mkMerge [
           scrollback-up-page = "Control+Shift+k";
           scrollback-down-page = "Control+Shift+j";
           search-start = "Control+Shift+s";
-          pipe-command-output = ''[sh -c "f=$(mktemp); cat - > $f; footclient hx $f; rm $f"] Control+Shift+g'';
+          pipe-command-output = ''[sh -c 'f=$(mktemp); cat - > $f; footclient hx $f; rm $f'] Control+Shift+g'';
         };
 
         mouse = {
@@ -63,7 +63,7 @@ lib.mkMerge [
         onEvent = "fish_preexec";
       };
       foot_cmd_end = {
-        body = ''echo -en "\e]133;D\e\\'';
+        body = ''echo -en "\e]133;D\e\\"'';
         onEvent = "fish_postexec";
       };
     };
diff --git a/hmModules/hyprland/default.nix b/hmModules/hyprland/default.nix
index 6ea8431..821ad1e 100644
--- a/hmModules/hyprland/default.nix
+++ b/hmModules/hyprland/default.nix
@@ -1,17 +1,16 @@
 {
   config,
   pkgs,
-  lib,
   ...
 }: let
-  screenshotScript = pkgs.writeShellScript "screenshot.sh" ''
+  screenshotScript = pkgs.writeShellScriptBin "screenshot.sh" ''
     filename="$HOME/shots/$(date --iso-8601=seconds).png"
     coords="$(${pkgs.slurp}/bin/slurp)"
     ${pkgs.grim}/bin/grim -t png -g "$coords" "$filename"
     wl-copy -t image/png < $filename
   '';
   hyprland = config.wayland.windowManager.hyprland.package;
-  switchMonitorScript = pkgs.writeShellScript "switch-monitor.sh" ''
+  switchMonitorScript = pkgs.writeShellScriptBin "switch-monitor.sh" ''
     if [[ "$(${hyprland}/bin/hyprctl monitors) | grep '\sDP-[0-9]+'" ]]; then
       if [[ $1 == "open" ]]; then
         ${hyprland}/bin/hyprctl keyword monitor "eDP-1,1920x1080,3760x230,1"
@@ -32,7 +31,15 @@ in {
     ../foot
   ];
 
-  home.packages = with pkgs; [wl-clipboard waypipe];
+  home.packages = with pkgs; [
+    wl-clipboard
+    waypipe
+    switchMonitorScript
+    screenshotScript
+    hyprpaper
+    fuzzel
+    brightnessctl
+  ];
 
   systemd.user.sessionVariables = {
     NIXOS_OZONE_WL = "1";
@@ -98,133 +105,11 @@ in {
 
   wayland.windowManager.hyprland = {
     enable = true;
-    extraConfig = ''
-           cursor {
-      hide_on_key_press = true
-      enable_hyprcursor = true
-      zoom_rigid = true
-           }
-
-           env = HYPRCURSOR_THEME,catppuccin-mocha-sapphire
-           env = HYPRCURSOR_SIZE,48
-           env = XCURSOR_THEME,catppuccin-mocha-sapphire
-           env = XCURSOR_SIZE,48
-
-           $mod = SUPER
-
-           input {
-             touchpad {
-               disable_while_typing = true # set to true while playing
-             }
-           }
-
-           monitor = HDMI-A-1, 2560x1440, 0x0, 1 # picard
-           monitor = eDP-1, 1920x1080, 0x0, 1 # kirk
-
-           bindl=,switch:off:Lid Switch,exec,${switchMonitorScript} open
-           bindl=,switch:on:Lid Switch,exec,${switchMonitorScript} close
-
-           exec-once = ${pkgs.hyprpaper}/bin/hyprpaper
-
-           windowrulev2 = tile, class:^(Spotify)$
-           windowrulev2 = workspace 9, class:^(Spotify)$
-           windowrulev2 = float, title:^(floating)$
-
-           bind = $mod, b, exec, firefox
-           bind = $mod, t, exec, footclient
-           bind = $mod, RETURN, exec, emacsclient -c --eval "(ccr/start-eshell)"
-           bind = $mod SHIFT, g, exec, emacsclient -c --eval "(ccr/start-chatgpt)"
-           bind = $mod, x, exec, emacsclient -c
-           bind = $mod SHIFT, n, exec, emacsclient --eval '(ccr/org-capture "n")' -c -F '((name . "floating"))'
-           bind = $mod SHIFT, w, exec, emacsclient --eval '(ccr/org-capture "j")' -c -F '((name . "floating"))'
-           bind = $mod, y, exec, ${pkgs.waypipe}/bin/waypipe --compress lz4=10 ssh picard.fleet emacsclient -c
-           bind = $mod, d, exec, ${pkgs.fuzzel}/bin/fuzzel --background-color=253559cc --border-radius=5 --border-width=0
-           bind = $mod, s, exec, ${screenshotScript}
-           bind = , XF86MonBrightnessUp, exec, ${pkgs.brightnessctl}/bin/brightnessctl s +5%
-           bind = , XF86MonBrightnessDown, exec, ${pkgs.brightnessctl}/bin/brightnessctl s 5%-
-           bind = $mod, code:60, exec, ${pkgs.brightnessctl}/bin/brightnessctl s +5%
-           bind = $mod, code:59, exec, ${pkgs.brightnessctl}/bin/brightnessctl s 5%-
-
-           bind = $mod SHIFT, t, togglegroup
-           bind = $mod, G, changegroupactive
-           bind = $mod SHIFT, q, killactive
-           bind = $mod SHIFT, f, fullscreen, 0
-           bind = $mod SHIFT, e, exit
-
-           bind = $mod, h, movefocus, l
-           bind = $mod, l, movefocus, r
-           bind = $mod, k, movefocus, u
-           bind = $mod, j, movefocus, d
-
-           bind = $mod SHIFT, h, movewindow, l
-           bind = $mod SHIFT, l, movewindow, r
-           bind = $mod SHIFT, k, movewindow, u
-           bind = $mod SHIFT, j ,movewindow, d
-
-           bind = $mod, p, movecurrentworkspacetomonitor, r
-           bind = $mod, o, movecurrentworkspacetomonitor, l
-
-           bindm=ALT,mouse:272,movewindow
-
-           bind = $mod, 1, workspace, 1
-           bind = $mod, 2, workspace, 2
-           bind = $mod, 3, workspace, 3
-           bind = $mod, 4, workspace, 4
-           bind = $mod, 5, workspace, 5
-           bind = $mod, 6, workspace, 6
-           bind = $mod, 7, workspace, 7
-           bind = $mod, 8, workspace, 8
-           bind = $mod, 9, workspace, 9
-           bind = $mod, 0, workspace, 10
-
-           bind = $mod SHIFT, 1, movetoworkspace, 1
-           bind = $mod SHIFT, 2, movetoworkspace, 2
-           bind = $mod SHIFT, 3, movetoworkspace, 3
-           bind = $mod SHIFT, 4, movetoworkspace, 4
-           bind = $mod SHIFT, 5, movetoworkspace, 5
-           bind = $mod SHIFT, 6, movetoworkspace, 6
-           bind = $mod SHIFT, 7, movetoworkspace, 7
-           bind = $mod SHIFT, 8, movetoworkspace, 8
-           bind = $mod SHIFT, 9, movetoworkspace, 9
-           bind = $mod SHIFT, 0, movetoworkspace, 10
-
-           general {
-             gaps_in = 0
-             gaps_out = 0
-             border_size = 1
-             col.active_border = rgba(AF8D61FF) rgba(CEB153FF) rgba(7B8387FF) 45deg
-             col.inactive_border = rgba(AF8D6166)
-           }
-
-           decoration {
-             # See https://wiki.hyprland.org/Configuring/Variables/ for more
-
-             rounding = 2
-             # blur = true
-             # blur_size = 8
-             # blur_passes = 1
-             # blur_new_optimizations = true
-
-             drop_shadow = true
-             shadow_range = 4
-             shadow_render_power = 3
-             col.shadow = rgba(a8cfee11)
-           }
-
-           animations {
-             enabled = true
-
-             # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
-
-             bezier = myBezier, 0.05, 0.9, 0.1, 1.05
-
-             animation = windows, 1, 3, myBezier
-             animation = windowsOut, 1, 3, default, popin 80%
-             animation = border, 1, 5, default
-             animation = borderangle, 1, 4, default
-             animation = fade, 1, 3, default
-             animation = workspaces, 1, 3, default
-           }
-    '';
+    plugins = with pkgs.hyprlandPlugins; [
+      hy3
+      hyprspace
+    ];
+    # TODO migrate to structured options
+    extraConfig = builtins.readFile ./hyprland.conf;
   };
 }
diff --git a/hmModules/hyprland/hyprland.conf b/hmModules/hyprland/hyprland.conf
new file mode 100644
index 0000000..cfc9db7
--- /dev/null
+++ b/hmModules/hyprland/hyprland.conf
@@ -0,0 +1,184 @@
+cursor {
+  hide_on_key_press = true
+  enable_hyprcursor = true
+  zoom_rigid = true
+}
+
+env = HYPRCURSOR_THEME,catppuccin-mocha-sapphire
+env = HYPRCURSOR_SIZE,48
+env = XCURSOR_THEME,catppuccin-mocha-sapphire
+env = XCURSOR_SIZE,48
+
+$mod = SUPER
+
+input {
+  touchpad {
+    disable_while_typing = true # set to true while playing
+  }
+}
+
+monitor = HDMI-A-1, 2560x1440, 0x0, 1 # picard
+monitor = eDP-1, 1920x1080, 0x0, 1 # kirk
+
+bindl=,switch:off:Lid Switch,exec,switch-monitor.sh open
+bindl=,switch:on:Lid Switch,exec,switch-monitor.sh close
+
+exec-once = hyprpaper
+
+windowrulev2 = tile, class:^(Spotify)$
+windowrulev2 = workspace 9, class:^(Spotify)$
+windowrulev2 = float, title:^(floating)$
+
+bind = $mod, b, exec, firefox
+bind = $mod, t, exec, footclient
+bind = $mod, y, exec, waypipe --compress lz4=10 ssh picard.fleet emacsclient -c
+bind = $mod, d, exec, fuzzel --background-color=253559cc --border-radius=5 --border-width=0
+bind = $mod, s, exec, screenshot.sh
+bind = , XF86MonBrightnessUp, exec, brightnessctl s +5%
+bind = , XF86MonBrightnessDown, exec, brightnessctl s 5%-
+bind = $mod, code:60, exec, brightnessctl s +5%
+bind = $mod, code:59, exec, brightnessctl s 5%-
+
+bind = $mod SHIFT, t, hy3:makegroup, tab, ephemeral
+bind = $mod SHIFT, q, killactive
+bind = $mod SHIFT, f, fullscreen, 0
+bind = $mod SHIFT, e, exit
+
+bind = $mod, h, hy3:movefocus, l
+bind = $mod, l, hy3:movefocus, r
+bind = $mod, k, hy3:movefocus, u
+bind = $mod, j, hy3:movefocus, d
+
+bind = $mod SHIFT, h, hy3:movewindow, l
+bind = $mod SHIFT, l, hy3:movewindow, r
+bind = $mod SHIFT, k, hy3:movewindow, u
+bind = $mod SHIFT, j ,hy3:movewindow, d
+
+bind = $mod, v, hy3:makegroup, v
+bind = $mod SHIFT, v, hy3:makegroup, h
+
+bind = $mod, p, movecurrentworkspacetomonitor, r
+bind = $mod, o, movecurrentworkspacetomonitor, l
+
+bindm=ALT,mouse:272,hy3:movewindow
+
+bind = $mod, 1, workspace, 1
+bind = $mod, 2, workspace, 2
+bind = $mod, 3, workspace, 3
+bind = $mod, 4, workspace, 4
+bind = $mod, 5, workspace, 5
+bind = $mod, 6, workspace, 6
+bind = $mod, 7, workspace, 7
+bind = $mod, 8, workspace, 8
+bind = $mod, 9, workspace, 9
+bind = $mod, 0, workspace, 10
+
+bind = $mod SHIFT, 1, movetoworkspace, 1
+bind = $mod SHIFT, 2, movetoworkspace, 2
+bind = $mod SHIFT, 3, movetoworkspace, 3
+bind = $mod SHIFT, 4, movetoworkspace, 4
+bind = $mod SHIFT, 5, movetoworkspace, 5
+bind = $mod SHIFT, 6, movetoworkspace, 6
+bind = $mod SHIFT, 7, movetoworkspace, 7
+bind = $mod SHIFT, 8, movetoworkspace, 8
+bind = $mod SHIFT, 9, movetoworkspace, 9
+bind = $mod SHIFT, 0, movetoworkspace, 10
+
+general {
+  layout = hy3
+  gaps_in = 8
+  gaps_out = 5
+}
+
+decoration {
+  rounding = 8
+
+  drop_shadow = true
+  shadow_range = 4
+  shadow_render_power = 3
+  col.shadow = rgba(a8cfee11)
+}
+
+animations {
+  enabled = true
+
+  bezier = myBezier, 0.05, 0.9, 0.1, 1.05
+
+  animation = windows, 1, 3, myBezier
+  animation = windowsOut, 1, 3, default, popin 80%
+  animation = border, 1, 5, default
+  animation = borderangle, 1, 4, default
+  animation = fade, 1, 3, default
+  animation = workspaces, 1, 3, default
+}
+
+plugin {
+  hy3 {
+    # disable gaps when only one window is onscreen
+    # 0 - always show gaps
+    # 1 - hide gaps with a single window onscreen
+    # 2 - 1 but also show the window border
+    no_gaps_when_only = 0 # default: 0
+
+    # policy controlling what happens when a node is removed from a group,
+    # leaving only a group
+    # 0 = remove the nested group
+    # 1 = keep the nested group
+    # 2 = keep the nested group only if its parent is a tab group
+    node_collapse_policy = 2 # default: 2
+
+    # offset from group split direction when only one window is in a group
+    group_inset = 0 # default: 10
+
+    # if a tab group will automatically be created for the first window spawned in a workspace
+    tab_first_window = false
+
+    # tab group settings
+    tabs {
+      # height of the tab bar
+      height =  20
+
+      # padding between the tab bar and its focused node
+      padding = 10
+
+      # the tab bar should animate in/out from the top instead of below the window
+      from_top = false
+
+      # rounding of tab bar corners
+      rounding = 4
+
+      # render the window title on the bar
+      render_text = true
+
+      # center the window title
+      text_center = true
+
+      # font to render the window title with
+      text_font = Fira Code
+
+      # height of the window title
+      text_height = 14
+      
+      # left padding of the window title
+      text_padding = 4
+
+      # active tab bar segment color
+      # col.active = <color> # default: 0xff32b4ff
+
+      # urgent tab bar segment color
+      # col.urgent = <color> # default: 0xffff4f4f
+
+      # inactive tab bar segment color
+      # col.inactive = <color> # default: 0x80808080
+
+      # active tab bar text color
+      # col.text.active = <color> # default: 0xff000000
+
+      # urgent tab bar text color
+      # col.text.urgent = <color> # default: 0xff000000
+
+      # inactive tab bar text color
+      # col.text.inactive = <color> # default: 0xff000000
+    }
+  }
+}
diff --git a/hmModules/hyprland/hyprpaper.nix b/hmModules/hyprland/hyprpaper.nix
index d6ab105..73e3148 100644
--- a/hmModules/hyprland/hyprpaper.nix
+++ b/hmModules/hyprland/hyprpaper.nix
@@ -2,6 +2,7 @@ let
   wallpaper = ./wallpaper.png;
 in {
   xdg.configFile."hypr/hyprpaper.conf".text = ''
+    splash = false
     preload = ${wallpaper}
     wallpaper = eDP-1,${wallpaper}
     wallpaper = DP-1,${wallpaper}
diff --git a/hosts/kirk/default.nix b/hosts/kirk/default.nix
index cc529d1..64873e6 100644
--- a/hosts/kirk/default.nix
+++ b/hosts/kirk/default.nix
@@ -47,7 +47,6 @@
       "helix"
       "shell"
       "element"
-      "emacs"
       "firefox"
       "gpg"
       "mpv"
diff --git a/hosts/sisko/default.nix b/hosts/sisko/default.nix
index b685f19..c6c2050 100644
--- a/hosts/sisko/default.nix
+++ b/hosts/sisko/default.nix
@@ -78,10 +78,15 @@
     efi.canTouchEfiVariables = false;
   };
 
+  hardware.deviceTree.enable = true;
+  hardware.deviceTree.name = "rockchip/rk3588-rock-5b.dtb";
+  boot.loader.systemd-boot.installDeviceTree = true;
+
   boot.initrd.availableKernelModules = [
     "nvme"
     "xhci_pci"
     "ahci"
+    "usb_storage"
   ];
 
   boot.kernelParams = [