me like nix
1{
2 pkgs,
3 inputs,
4 config,
5 ...
6}:
7
8{
9 # Import the home-manager modules you want to use
10 imports = [
11 inputs.catppuccin.homeModules.catppuccin
12 inputs.niri.homeModules.niri
13 inputs.zen-browser.homeModules.beta
14 inputs.agenix.homeManagerModules.default
15 ];
16
17 programs.niri = {
18 enable = true;
19 settings = {
20 window-rules = [
21 {
22 geometry-corner-radius = {
23 top-left = 5.0;
24 top-right = 5.0;
25 bottom-left = 5.0;
26 bottom-right = 5.0;
27 };
28 clip-to-geometry = true;
29 draw-border-with-background = false;
30 }
31 ];
32 debug = {
33 honor-xdg-activation-with-invalid-serial = { };
34 };
35 layout = {
36 focus-ring = {
37 width = 2;
38 active.color = "#8caaee";
39 inactive.color = "#414559";
40 };
41 struts = {
42 top = -6;
43 bottom = -6;
44 left = 0;
45 right = 0;
46 };
47 gaps = 8;
48 };
49 gestures = {
50 hot-corners = {
51 enable = false;
52 };
53 };
54 binds = {
55 "Mod+d".action.spawn = "fuzzel";
56 "Mod+e".action.spawn = "bemoji";
57 "Mod+n".action.spawn = "networkmanager_dmenu";
58 "Mod+a".action.spawn = "alacritty";
59 "Mod+h".action = {
60 focus-column-left = { };
61 };
62 "Mod+j".action = {
63 focus-workspace-down = { };
64 };
65 "Mod+k".action = {
66 focus-workspace-up = { };
67 };
68 "Mod+l".action = {
69 focus-column-right = { };
70 };
71 "Mod+Shift+h".action = {
72 move-column-left = { };
73 };
74 "Mod+Shift+j".action = {
75 move-window-down-or-to-workspace-down = { };
76 };
77 "Mod+Shift+k".action = {
78 move-window-up-or-to-workspace-up = { };
79 };
80 "Mod+Shift+l".action = {
81 move-column-right = { };
82 };
83 "Mod+Down".action = {
84 move-workspace-down = { };
85 };
86 "Mod+Up".action = {
87 move-workspace-up = { };
88 };
89 "Mod+p".action = {
90 show-hotkey-overlay = { };
91 };
92 "Mod+o".action = {
93 toggle-overview = { };
94 };
95 "Mod+q".action = {
96 close-window = { };
97 };
98 "Mod+f".action = {
99 toggle-window-floating = { };
100 };
101 "Mod+Shift+f".action = {
102 switch-focus-between-floating-and-tiling = { };
103 };
104 "Mod+m".action = {
105 fullscreen-window = { };
106 };
107 "Mod+s".action = {
108 screenshot = {
109 show-pointer = true;
110 };
111 };
112 "Mod+1".action = {
113 set-column-width = "100%";
114 };
115 "Mod+2".action = {
116 set-column-width = "50%";
117 };
118 "Mod+Minus".action = {
119 set-column-width = "-10%";
120 };
121 "Mod+Equal".action = {
122 set-column-width = "+10%";
123 };
124 "Mod+Shift+r".action.spawn = [
125 "sh"
126 "-c"
127 "pkill quickshell; quickshell &"
128 ];
129 "XF86MonBrightnessDown".action.spawn = [
130 "brightnessctl"
131 "set"
132 "5%-"
133 ];
134 "XF86MonBrightnessUp".action.spawn = [
135 "brightnessctl"
136 "set"
137 "+5%"
138 ];
139 };
140 outputs = {
141 # External monitor - primary display at position (0, 0)
142 "DP-5" = {
143 scale = 2.0;
144 mode = {
145 width = 5120;
146 height = 2160;
147 refresh = 120.0;
148 };
149 position = {
150 x = 0;
151 y = 0;
152 };
153 };
154 "DP-1" = {
155 scale = 2.0;
156 mode = {
157 width = 5120;
158 height = 2160;
159 refresh = 120.0;
160 };
161 position = {
162 x = 0;
163 y = 0;
164 };
165 };
166 "DP-2" = {
167 scale = 1.0;
168 mode = {
169 width = 5120;
170 height = 2160;
171 refresh = 120.0;
172 };
173 position = {
174 x = 0;
175 y = 0;
176 };
177 };
178 "DP-6" = {
179 scale = 2.0;
180 mode = {
181 width = 5120;
182 height = 2160;
183 refresh = 120.0;
184 };
185 position = {
186 x = 0;
187 y = 0;
188 };
189 };
190 "DP-7" = {
191 scale = 2.0;
192 mode = {
193 width = 5120;
194 height = 2160;
195 refresh = 120.0;
196 };
197 position = {
198 x = 0;
199 y = 0;
200 };
201 };
202 # Laptop display - secondary display positioned underneath
203 "eDP-1" = {
204 scale = 1.5;
205 mode = {
206 width = 2560;
207 height = 1600;
208 refresh = 165.0;
209 };
210 position = {
211 x = 0;
212 y = 1080; # Position underneath the external monitor (2160 / 2 scale = 1080 logical height)
213 };
214 };
215 };
216 spawn-at-startup = [
217 { command = [ "xwayland-satellite" ]; }
218 { command = [ "swww-daemon" ]; }
219 { command = [ "quickshell" ]; }
220 { command = [ "wl-paste --watch cliphist store" ]; }
221 ];
222 environment = {
223 DISPLAY = ":0";
224 };
225 };
226 };
227
228 # Allow unfree packages
229 nixpkgs.config.allowUnfree = true;
230
231 nixpkgs.config.permittedInsecurePackages = [
232 "libsoup-2.74.3"
233 ];
234
235 # Quickshell status bar
236 xdg.configFile."quickshell/shell.qml".source = ./quickshell/shell.qml;
237
238 programs.ssh = {
239 enable = true;
240 enableDefaultConfig = false;
241 matchBlocks = {
242 "*" = {
243 extraOptions = {
244 IdentityAgent = "${config.home.homeDirectory}/.1password/agent.sock";
245 };
246 };
247 };
248 };
249
250 programs.awscli = {
251 enable = true;
252 settings = {
253 "default" = {
254 region = "us-east-1";
255 };
256 };
257 };
258
259 # All your user-specific packages
260 home.packages = with pkgs; [
261 helix
262 git
263 jujutsu # jj-cli
264 htop
265 zellij # terminal multiplexer
266 alacritty
267 fuzzel # Application launcher
268 bemoji # emoji picker
269 networkmanager_dmenu # network picker for fuzzel
270 quickshell # Status bar (QML-based)
271 swww # For setting wallpapers
272 cliphist # Clipboard history manager
273 pavucontrol # GUI for PulseAudio/PipeWire volume control
274 fd
275 ripgrep
276 yazi # tui file browser
277 gh # github cli
278 signal-desktop
279 xwayland-satellite # for running x11 apps
280 nixfmt # nix formatter
281 nil # nix language server
282 atac # postman-like TUI
283 trippy # network analyzer
284 rsync # file sync utility
285 udiskie # for mounting external drives
286 darktable # photo editing
287 zoxide
288 chromium
289 claude-code
290 nautilus # file browser
291 sqlitebrowser
292 gnome-characters # symbol picker
293 sendme # file transfer
294 desktop-file-utils # for managing .desktop files
295 flyctl # fly.io cli
296 vscode-json-languageserver
297 gnome-network-displays
298 doppler # secret management
299 rainfrog # db tui
300 loupe # image viewer
301 glycin-loaders # various format loaders for loupe
302 docker-compose
303 discord
304 mangohud
305 prismlauncher # minecraft launcher
306 fastfetch
307 inputs.agenix.packages.${pkgs.system}.default # agenix CLI
308 age-plugin-yubikey # Yubikey support for agenix
309
310 # --- FONTS ARE IMPORTANT ---
311 # Berkeley Mono is the main system font, keeping JetBrains and Font Awesome for icons
312 font-awesome
313 noto-fonts
314 noto-fonts-cjk-sans
315 noto-fonts-color-emoji
316 nerd-fonts.jetbrains-mono
317 nerd-fonts.symbols-only
318 # --- POLKIT AGENT (for 1Password GUI, etc.) ---
319 lxqt.lxqt-policykit # Lightweight polkit agent
320 ];
321
322 services.udiskie = {
323 enable = true;
324 tray = "auto";
325 automount = true;
326 };
327
328 services.mako = {
329 enable = true;
330 settings = {
331 border-radius = 8;
332 border-size = 2;
333 padding = "12";
334 margin = "12";
335 font = "BerkeleyMono Nerd Font 11";
336 on-button-left = "invoke-default-action";
337 on-button-right = "dismiss";
338 };
339 };
340
341 catppuccin = {
342 enable = true;
343 flavor = "frappe";
344 };
345
346 programs.fuzzel.enable = true;
347
348 programs.direnv.enable = true;
349
350 programs.atuin = {
351 enable = true;
352 enableFishIntegration = true;
353 settings = {
354 filter_mode_shell_up_key_binding = "session";
355 };
356 };
357
358 programs.zellij = {
359 enable = true;
360 settings = {
361 keybinds = {
362 unbind = [
363 "Ctrl q"
364 "Ctrl o"
365 ];
366 normal = {
367 "bind \"Ctrl m\"" = {
368 SwitchToMode = "Session";
369 };
370 };
371 };
372 pane_frames = false;
373 show_startup_tips = false;
374 ui = {
375 pane_frames.hide_session_name = true;
376 };
377 };
378 };
379
380 programs.zen-browser.enable = true;
381 # programs.swww.enable = true;
382 programs.zoxide = {
383 enable = true;
384 enableFishIntegration = true;
385 };
386
387 programs.obs-studio = {
388 enable = true;
389 plugins = with pkgs.obs-studio-plugins; [
390 obs-backgroundremoval
391 ];
392 };
393
394 # Program configurations
395 programs.git = {
396 enable = true;
397 settings = {
398 user = {
399 name = "seanaye";
400 email = "hello@seanaye.ca";
401 };
402 init.defaultBranch = "main";
403 };
404 };
405 programs.jujutsu = {
406 enable = true;
407 settings = {
408 user = {
409 email = "hello@seanaye.ca";
410 name = "Sean Aye";
411 };
412 signing = {
413 sign-all = true;
414 behavior = "own";
415 backend = "ssh";
416 key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCIqgZ7kedxo+mOW7YG73Vp3zel3h180y3GKvHtRsXfGlpIIvRDy7pgCBQ4AGXYD4y78URQmFohYSAPqCPOPaWcU2un3XG9KvCzEsHmsbskPonitUmCiKvrKkb6oW4jCBtd7AEtBn+AiajAQFtPZ7NN2Df3AmTypvR6Irg7R+nxnfc9NTIHmGvxSDyWcbb4pguL20sctUSqGL6xGh8q/bqhdOThSimM+z9bEUNxK/5rPhwkNniMrp4pJcUrUiAh5/4DiRFG6KT+oeg+/myoz/Z1sPvAs7u/8JDQI4RshRD8Hu0oTkRBN6Hxj478q2SXbeBUZlD6IdjP3RhGpmSecoDdtWqKbpuV3eVRtQtba3KL86GBeV/bugaOdJ1Aud+1SOFJreAAuvxzMMKT+cdQZk6oOPP148DA/No+mDm/2S43lcdCXh79wA6YRAmKQ8jmZxTCtPutrvuZK1rguvvUlEoG/vhdNHh7eDa4Td07V6bjCRPUl8qk/e4M0E3pwsTlZc=";
417 };
418 };
419 };
420
421 programs.home-manager.enable = true;
422
423 programs.fish = {
424 enable = true;
425 shellAliases = {
426 agenix = "agenix -i ~/.config/agenix/yubikey-identity.txt";
427 };
428 interactiveShellInit = ''
429 set fish_greeting
430 # Set 1Password SSH agent socket
431 set -gx SSH_AUTH_SOCK ${config.home.homeDirectory}/.1password/agent.sock
432 # Load 1Password CLI plugins
433 if test -f ~/.config/op/plugins.sh
434 source ~/.config/op/plugins.sh
435 end
436 # Show fastfetch when inside zellij
437 if set -q ZELLIJ
438 fastfetch --logo small
439 end
440
441 function y
442 set tmp (mktemp -t "yazi-cwd.XXXXXX")
443 yazi $argv --cwd-file="$tmp"
444 if read -z cwd < "$tmp"; and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
445 builtin cd -- "$cwd"
446 end
447 rm -f -- "$tmp"
448 end
449 '';
450 functions = {
451 s3edit = ''
452 set file (basename $argv[1])
453 set tmpfile /tmp/$file
454 aws s3 cp $argv[1] $tmpfile
455 and $EDITOR $tmpfile
456 and aws s3 cp $tmpfile $argv[1]
457 '';
458 };
459 };
460
461 programs.starship = {
462 enable = true;
463 enableFishIntegration = true;
464 };
465
466 programs.alacritty = {
467 enable = true;
468 settings = {
469 terminal.shell = {
470 program = "zellij";
471 args = [
472 "options"
473 "--on-force-close"
474 "detach"
475 ];
476 };
477 window = {
478 decorations = "none";
479 opacity = 0.9;
480 };
481 font = {
482 normal = {
483 family = "BerkeleyMono Nerd Font";
484 style = "Regular";
485 };
486 size = 12.0;
487 };
488 };
489
490 };
491
492 programs.helix = {
493 enable = true;
494 settings = {
495 editor = {
496 bufferline = "multiple";
497 file-picker = {
498 hidden = false;
499 git-ignore = true;
500 };
501 cursor-shape = {
502 insert = "bar";
503 normal = "block";
504 select = "underline";
505 };
506 line-number = "relative";
507 cursorline = true;
508 auto-format = true;
509 end-of-line-diagnostics = "hint";
510 soft-wrap = {
511 enable = true;
512 };
513 lsp = {
514 display-inlay-hints = true;
515 display-messages = true;
516 display-progress-messages = true;
517 };
518 inline-diagnostics = {
519 cursor-line = "hint";
520 };
521 };
522 keys = {
523 normal = {
524 esc = [
525 "keep_primary_selection"
526 "collapse_selection"
527 ];
528 };
529
530 };
531 };
532 languages = {
533
534 language-server.rust-analyzer = {
535 config = {
536 check = {
537 command = "clippy";
538 };
539 checkOnSave = true;
540 cargo = {
541 allFeatures = true;
542 };
543 };
544 };
545 language-server.deno-lsp = {
546 command = "deno";
547 args = [ "lsp" ];
548 config.deno.enable = true;
549 };
550
551 language = [
552 {
553 name = "html";
554 formatter = {
555 command = "prettier";
556 args = [
557 "--parser"
558 "html"
559 ];
560 };
561 }
562 {
563 name = "nix";
564 auto-format = true;
565 formatter = {
566 command = "${pkgs.nixfmt}/bin/nixfmt";
567 };
568 }
569 {
570 name = "kotlin";
571 auto-format = true;
572 }
573 {
574 name = "rust";
575 auto-format = true;
576 formatter = {
577 command = "rustfmt";
578 args = [
579 "--edition"
580 "2024"
581 ];
582 };
583 indent = {
584 tab-width = 4;
585 unit = "t";
586 };
587 }
588 {
589 name = "astro";
590 auto-format = true;
591 formatter = {
592 command = "npx";
593 args = [
594 "prettier"
595 "--plugin"
596 "prettier-plugin-astro"
597 "--parser"
598 "astro"
599 ];
600 };
601 }
602 {
603 name = "json";
604 auto-format = true;
605 }
606 {
607 name = "just";
608 auto-format = true;
609 formatter = {
610 command = "just";
611 args = [
612 "--justfile"
613 "/dev/stdin"
614 "--dump"
615 ];
616 };
617 }
618 {
619 name = "toml";
620 auto-format = true;
621 formatter = {
622 command = "taplo";
623 args = [
624 "format"
625 "-"
626 ];
627 };
628 }
629 # {
630 # name = "typescript";
631 # roots = [
632 # "deno.json"
633 # "deno.jsonc"
634 # ];
635 # file-types = [
636 # "ts"
637 # "tsx"
638 # ];
639 # auto-format = true;
640 # language-servers = [ "deno-lsp" ];
641 # }
642 ];
643 };
644 };
645
646 dconf.settings = {
647 "org/gnome/desktop/interface" = {
648 color-scheme = "prefer-dark";
649 enable-hot-corners = false;
650 };
651 };
652
653 # Font rendering configuration
654 fonts.fontconfig = {
655 enable = true;
656 defaultFonts = {
657 monospace = [ "BerkeleyMono Nerd Font" ];
658 sansSerif = [ "Noto Sans" ];
659 serif = [ "Noto Serif" ];
660 };
661 };
662
663 # Cursor configuration
664 home.pointerCursor = {
665 name = "Adwaita";
666 package = pkgs.adwaita-icon-theme;
667 size = 16;
668 x11.enable = true;
669 gtk.enable = true;
670 };
671
672 # Session variables
673 home.sessionVariables = {
674 EDITOR = "hx";
675 VISUAL = "hx";
676 SUDO_EDITOR = "hx";
677 SSH_AUTH_SOCK = "${config.home.homeDirectory}/.1password/agent.sock";
678 };
679
680 # Yubikey identity for agenix (not secret - just a reference to the hardware key)
681 home.file.".config/agenix/yubikey-identity.txt".text = ''
682 # Serial: 26930059, Slot: 1
683 # Name: agenix
684 # Recipient: age1yubikey1qw64ag5lzvn9ekrflu5ruj4a6ucycscl6ctk39fjzf76jptsay39z442pxv
685 AGE-PLUGIN-YUBIKEY-1304E5QVZZD74FKSP8FMCT
686 '';
687
688 # Set the state version for Home Manager
689 home.stateVersion = "25.05";
690}