me like nix
1{ pkgs, inputs, ... }:
2
3{
4 # Import the home-manager modules you want to use
5 imports = [
6 inputs.catppuccin.homeModules.catppuccin
7 inputs.niri.homeModules.niri
8 inputs.zen-browser.homeModules.beta
9 ];
10
11 programs.niri = {
12 enable = true;
13 settings = {
14 window-rules = [
15 {
16 geometry-corner-radius = {
17 top-left = 12.0;
18 top-right = 12.0;
19 bottom-left = 12.0;
20 bottom-right = 12.0;
21 };
22 clip-to-geometry = true;
23 draw-border-with-background = false;
24 }
25 ];
26 layout = {
27 struts = {
28 top = 0;
29 bottom = 0;
30 };
31 };
32 gestures = {
33 hot-corners = {
34 enable = false;
35 };
36 };
37 binds = {
38 "Mod+d".action.spawn = "fuzzel";
39 "Mod+e".action.spawn = "bemoji";
40 "Mod+n".action.spawn = "networkmanager_dmenu";
41 "Mod+a".action.spawn = "alacritty";
42 "Mod+h".action = {
43 focus-column-left = { };
44 };
45 "Mod+j".action = {
46 focus-workspace-down = { };
47 };
48 "Mod+k".action = {
49 focus-workspace-up = { };
50 };
51 "Mod+l".action = {
52 focus-column-right = { };
53 };
54 "Mod+Shift+h".action = {
55 move-column-left = { };
56 };
57 "Mod+Shift+j".action = {
58 move-window-down-or-to-workspace-down = { };
59 };
60 "Mod+Shift+k".action = {
61 move-window-up-or-to-workspace-up = { };
62 };
63 "Mod+Shift+l".action = {
64 move-column-right = { };
65 };
66 "Mod+Down".action = {
67 move-workspace-down = { };
68 };
69 "Mod+Up".action = {
70 move-workspace-up = { };
71 };
72 "Mod+p".action = {
73 show-hotkey-overlay = { };
74 };
75 "Mod+o".action = {
76 toggle-overview = { };
77 };
78 "Mod+q".action = {
79 close-window = { };
80 };
81 "Mod+s".action = {
82 screenshot = {
83 show-pointer = true;
84 };
85 };
86 "Mod+1".action = {
87 set-column-width = "100%";
88 };
89 "Mod+2".action = {
90 set-column-width = "50%";
91 };
92 "XF86MonBrightnessDown".action.spawn = [
93 "brightnessctl"
94 "set"
95 "5%-"
96 ];
97 "XF86MonBrightnessUp".action.spawn = [
98 "brightnessctl"
99 "set"
100 "+5%"
101 ];
102 };
103 outputs = {
104 # External monitor - primary display at position (0, 0)
105 "DP-5" = {
106 scale = 2.0;
107 mode = {
108 width = 5120;
109 height = 2160;
110 refresh = 120.0;
111 };
112 position = {
113 x = 0;
114 y = 0;
115 };
116 };
117 "DP-1" = {
118 scale = 2.0;
119 mode = {
120 width = 5120;
121 height = 2160;
122 refresh = 120.0;
123 };
124 position = {
125 x = 0;
126 y = 0;
127 };
128 };
129 "DP-2" = {
130 scale = 2.0;
131 mode = {
132 width = 5120;
133 height = 2160;
134 refresh = 120.0;
135 };
136 position = {
137 x = 0;
138 y = 0;
139 };
140 };
141 "DP-7" = {
142 scale = 2.0;
143 mode = {
144 width = 5120;
145 height = 2160;
146 refresh = 120.0;
147 };
148 position = {
149 x = 0;
150 y = 0;
151 };
152 };
153 # Laptop display - secondary display positioned underneath
154 "eDP-1" = {
155 scale = 1.5;
156 mode = {
157 width = 2560;
158 height = 1600;
159 refresh = 165.0;
160 };
161 position = {
162 x = 0;
163 y = 1080; # Position underneath the external monitor (2160 / 2 scale = 1080 logical height)
164 };
165 };
166 };
167 spawn-at-startup = [
168 { command = [ "xwayland-satellite" ]; }
169 { command = [ "swww-daemon" ]; }
170 { command = [ "mako" ]; }
171 { command = [ "waybar" ]; }
172 { command = [ "wl-paste --watch cliphist store" ]; }
173 ];
174 environment = {
175 DISPLAY = ":0";
176 };
177 };
178 };
179
180 # Allow unfree packages
181 nixpkgs.config.allowUnfree = true;
182
183 nixpkgs.config.permittedInsecurePackages = [
184 "libsoup-2.74.3"
185 ];
186
187 programs.waybar = {
188 enable = true;
189 settings = {
190 mainBar = {
191 height = 8;
192 spacing = 0;
193
194 modules-left = [
195 "custom/media"
196 ];
197
198 modules-center = [
199 "clock"
200 ];
201
202 modules-right = [
203 "mpd"
204 "pulseaudio"
205 "network"
206 "power-profiles-daemon"
207 "cpu"
208 "memory"
209 "temperature"
210 "backlight"
211 "sway/language"
212 "battery"
213 "battery#bat2"
214 "custom/power"
215 ];
216
217 "keyboard-state" = {
218 numlock = true;
219 capslock = true;
220 format = "{name} {icon}";
221 format-icons = {
222 locked = " ";
223 unlocked = " ";
224 };
225 };
226
227 mpd = {
228 format = "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ";
229 format-disconnected = "Disconnected ";
230 format-stopped = "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ";
231 unknown-tag = "N/A";
232 interval = 5;
233 consume-icons = {
234 on = " ";
235 };
236 random-icons = {
237 off = "<span color=\"#f53c3c\"></span> ";
238 on = " ";
239 };
240 repeat-icons = {
241 on = " ";
242 };
243 single-icons = {
244 on = "1 ";
245 };
246 state-icons = {
247 paused = "";
248 playing = "";
249 };
250 tooltip-format = "MPD (connected)";
251 tooltip-format-disconnected = "MPD (disconnected)";
252 };
253
254 idle_inhibitor = {
255 format = "{icon}";
256 format-icons = {
257 activated = " ";
258 deactivated = " ";
259 };
260 };
261
262 tray = {
263 spacing = 10;
264 };
265
266 clock = {
267 format = "{:%d-%m-%Y %H:%M}";
268 tooltip-format = "<big>{:%Y %B}</big>\n<tt><small>{calendar}</small></tt>";
269 format-alt = "{:%Y-%m-%d %H:%M:%S}";
270 };
271
272 cpu = {
273 format = "{usage}% ";
274 tooltip = false;
275 };
276
277 memory = {
278 format = "{}% ";
279 };
280
281 temperature = {
282 critical-threshold = 80;
283 format = "{temperatureC}°C {icon}";
284 format-icons = [
285 ""
286 ""
287 ""
288 ];
289 };
290
291 backlight = {
292 format = "{percent}% {icon}";
293 format-icons = [
294 ""
295 ""
296 ""
297 ""
298 ""
299 ""
300 ""
301 ""
302 ""
303 ];
304 };
305
306 battery = {
307 states = {
308 warning = 30;
309 critical = 15;
310 };
311 format = "{capacity}% {icon}";
312 format-full = "{capacity}% {icon}";
313 format-charging = "{capacity}% ";
314 format-plugged = "{capacity}% ";
315 format-alt = "{time} {icon}";
316 format-icons = [
317 ""
318 ""
319 ""
320 ""
321 ""
322 ];
323 };
324
325 "battery#bat2" = {
326 bat = "BAT2";
327 };
328
329 "power-profiles-daemon" = {
330 format = "{icon}";
331 tooltip-format = "Power profile: {profile}\nDriver: {driver}";
332 tooltip = true;
333 format-icons = {
334 default = "";
335 performance = "";
336 balanced = " ";
337 power-saver = " ";
338 };
339 };
340
341 network = {
342 format-wifi = "{essid} ({signalStrength}%) ";
343 format-ethernet = "{ipaddr}/{cidr} ";
344 tooltip-format = "{ifname} via {gwaddr} ";
345 format-linked = "{ifname} (No IP) ";
346 format-disconnected = "Disconnected ⚠";
347 format-alt = "{ifname}: {ipaddr}/{cidr}";
348 };
349
350 pulseaudio = {
351 format = "{volume}% {icon} {format_source}";
352 format-bluetooth = "{volume}% {icon} {format_source}";
353 format-bluetooth-muted = " {icon} {format_source}";
354 format-muted = " {format_source}";
355 format-source = "{volume}% ";
356 format-source-muted = " ";
357 format-icons = {
358 headphone = "";
359 hands-free = "";
360 headset = "";
361 phone = "";
362 portable = "";
363 car = "";
364 default = [
365 ""
366 " "
367 " "
368 ];
369 };
370 on-click = "pavucontrol";
371 };
372
373 "custom/media" = {
374 format = "{icon} {text}";
375 return-type = "json";
376 max-length = 40;
377 format-icons = {
378 spotify = " ";
379 default = "🎜 ";
380 };
381 escape = true;
382 exec = "$HOME/.config/waybar/mediaplayer.py 2> /dev/null";
383 };
384
385 "custom/power" = {
386 format = "⏻ ";
387 tooltip = false;
388 menu = "on-click";
389 menu-file = "${./waybar/power_menu.xml}";
390 menu-actions = {
391 shutdown = "shutdown";
392 reboot = "reboot";
393 suspend = "systemctl suspend";
394 hibernate = "systemctl hibernate";
395 };
396 };
397 };
398 };
399 style = builtins.readFile ./waybar/style.css;
400 };
401
402 programs.ssh = {
403 enable = true;
404 extraConfig = ''
405 Host *
406 IdentityAgent ~/.1password/agent.sock
407 '';
408 };
409
410 programs.awscli = {
411 enable = true;
412 settings = {
413 "default" = {
414 region = "us-east-1";
415 };
416 };
417 };
418
419 # All your user-specific packages
420 home.packages = with pkgs; [
421 helix
422 git
423 jujutsu # jj-cli
424 htop
425 zellij # terminal multiplexer
426 alacritty
427 fuzzel # Application launcher
428 bemoji # emoji picker
429 networkmanager_dmenu # network picker for fuzzel
430 waybar # Status bar (highly recommended)
431 mako # Notification daemon
432 swww # For setting wallpapers
433 cliphist # Clipboard history manager
434 pavucontrol # GUI for PulseAudio/PipeWire volume control
435 fd
436 ripgrep
437 yazi # tui file browser
438 gh # github cli
439 signal-desktop
440 xwayland-satellite # for running x11 apps
441 nixfmt-rfc-style # nix formatter
442 nil # nix language server
443 atac # postman-like TUI
444 trippy # network analyzer
445 rsync # file sync utility
446 udiskie # for mounting external drives
447 darktable # photo editing
448 zoxide
449 chromium
450 claude-code
451 nautilus # file browser
452 sqlitebrowser
453 gnome-characters # symbol picker
454 sendme # file transfer
455 desktop-file-utils # for managing .desktop files
456 flyctl # fly.io cli
457 vscode-json-languageserver
458 gnome-network-displays
459 doppler # secret management
460 rainfrog # db tui
461 loupe # image viewer
462 glycin-loaders # various format loaders for loupe
463 docker-compose
464 discord
465
466 # --- FONTS ARE IMPORTANT ---
467 # Berkeley Mono is the main system font, keeping JetBrains and Font Awesome for waybar
468 font-awesome
469 noto-fonts
470 noto-fonts-cjk-sans
471 noto-fonts-emoji
472 font-awesome # For icons in waybar, etc.
473 nerd-fonts.jetbrains-mono
474 # --- POLKIT AGENT (for 1Password GUI, etc.) ---
475 lxqt.lxqt-policykit # Lightweight polkit agent
476 ];
477
478 services.udiskie = {
479 enable = true;
480 tray = "auto";
481 automount = true;
482 };
483
484 catppuccin = {
485 enable = true;
486 flavor = "frappe";
487 };
488
489 programs.fuzzel.enable = true;
490
491 programs.direnv.enable = true;
492
493 programs.zellij = {
494 enable = true;
495 settings = {
496 keybinds = {
497 unbind = [
498 "Ctrl q"
499 "Ctrl o"
500 ];
501 normal = {
502 "bind \"Ctrl m\"" = {
503 SwitchToMode = "Session";
504 };
505 };
506 };
507 pane_frames = false;
508 ui = {
509 pane_frames.hide_session_name = true;
510 };
511 };
512 };
513
514 programs.zen-browser.enable = true;
515 # programs.swww.enable = true;
516 programs.zoxide = {
517 enable = true;
518 enableFishIntegration = true;
519 };
520
521 programs.obs-studio = {
522 enable = true;
523 plugins = with pkgs.obs-studio-plugins; [
524 obs-backgroundremoval
525 ];
526 };
527
528 # Program configurations
529 programs.git = {
530 enable = true;
531 userName = "seanaye";
532 userEmail = "hello@seanaye.ca";
533 extraConfig = {
534 init.defaultBranch = "main";
535 };
536 };
537 programs.jujutsu = {
538 enable = true;
539 settings.user = {
540 email = "hello@seanaye.ca";
541 name = "Sean Aye";
542 };
543 };
544
545 programs.home-manager.enable = true;
546
547 programs.fish = {
548 enable = true;
549 interactiveShellInit = ''
550 set fish_greeting
551 # Load 1Password CLI plugins
552 if test -f ~/.config/op/plugins.sh
553 source ~/.config/op/plugins.sh
554 end
555 '';
556 functions = {
557 s3edit = ''
558 set file (basename $argv[1])
559 set tmpfile /tmp/$file
560 aws s3 cp $argv[1] $tmpfile
561 and $EDITOR $tmpfile
562 and aws s3 cp $tmpfile $argv[1]
563 '';
564 };
565 };
566
567 programs.starship = {
568 enable = true;
569 enableFishIntegration = true;
570 };
571
572 programs.alacritty = {
573 enable = true;
574 settings = {
575 window = {
576 decorations = "none";
577 opacity = 0.9;
578 };
579 font = {
580 normal = {
581 family = "BerkeleyMono Nerd Font";
582 style = "Regular";
583 };
584 size = 12.0;
585 };
586 };
587
588 };
589
590 programs.helix = {
591 enable = true;
592 settings = {
593 editor = {
594 bufferline = "multiple";
595 file-picker = {
596 hidden = false;
597 git-ignore = true;
598 };
599 cursor-shape = {
600 insert = "bar";
601 normal = "block";
602 select = "underline";
603 };
604 line-number = "relative";
605 cursorline = true;
606 auto-format = true;
607 end-of-line-diagnostics = "hint";
608 soft-wrap = {
609 enable = true;
610 };
611 lsp = {
612 display-inlay-hints = true;
613 display-messages = true;
614 display-progress-messages = true;
615 };
616 inline-diagnostics = {
617 cursor-line = "hint";
618 };
619 };
620 keys = {
621 normal = {
622 esc = [
623 "keep_primary_selection"
624 "collapse_selection"
625 ];
626 };
627
628 };
629 };
630 languages = {
631
632 language-server.rust-analyzer = {
633 config = {
634 check = {
635 command = "clippy";
636 };
637 checkOnSave = true;
638 cargo = {
639 allFeatures = true;
640 };
641 };
642 };
643 language-server.deno-lsp = {
644 command = "deno";
645 args = [ "lsp" ];
646 config.deno.enable = true;
647 };
648
649 language = [
650 {
651 name = "html";
652 formatter = {
653 command = "prettier";
654 args = [
655 "--parser"
656 "html"
657 ];
658 };
659 }
660 {
661 name = "nix";
662 auto-format = true;
663 formatter = {
664 command = "${pkgs.nixfmt-rfc-style}/bin/nixfmt";
665 };
666 }
667 {
668 name = "kotlin";
669 auto-format = true;
670 }
671 {
672 name = "rust";
673 auto-format = true;
674 formatter = {
675 command = "rustfmt";
676 args = [
677 "--edition"
678 "2024"
679 ];
680 };
681 indent = {
682 tab-width = 4;
683 unit = "t";
684 };
685 }
686 {
687 name = "astro";
688 auto-format = true;
689 formatter = {
690 command = "npx";
691 args = [
692 "prettier"
693 "--plugin"
694 "prettier-plugin-astro"
695 "--parser"
696 "astro"
697 ];
698 };
699 }
700 {
701 name = "json";
702 auto-format = true;
703 }
704 {
705 name = "just";
706 auto-format = true;
707 formatter = {
708 command = "just";
709 args = [
710 "--justfile"
711 "/dev/stdin"
712 "--dump"
713 ];
714 };
715 }
716 {
717 name = "toml";
718 auto-format = true;
719 formatter = {
720 command = "taplo";
721 args = [
722 "format"
723 "-"
724 ];
725 };
726 }
727 # {
728 # name = "typescript";
729 # roots = [
730 # "deno.json"
731 # "deno.jsonc"
732 # ];
733 # file-types = [
734 # "ts"
735 # "tsx"
736 # ];
737 # auto-format = true;
738 # language-servers = [ "deno-lsp" ];
739 # }
740 ];
741 };
742 };
743
744 dconf.settings = {
745 "org/gnome/desktop/interface" = {
746 color-scheme = "prefer-dark";
747 enable-hot-corners = false;
748 };
749 };
750
751 # Font rendering configuration
752 fonts.fontconfig = {
753 enable = true;
754 defaultFonts = {
755 monospace = [ "BerkeleyMono Nerd Font" ];
756 sansSerif = [ "Noto Sans" ];
757 serif = [ "Noto Serif" ];
758 };
759 };
760
761 # Cursor configuration
762 home.pointerCursor = {
763 name = "Adwaita";
764 package = pkgs.adwaita-icon-theme;
765 size = 16;
766 x11.enable = true;
767 gtk.enable = true;
768 };
769
770 # Session variables
771 home.sessionVariables = {
772 EDITOR = "hx";
773 VISUAL = "hx";
774 SUDO_EDITOR = "hx";
775 SSH_AUTH_SOCK = "~/.1password/agent.sock";
776 };
777
778 # Set the state version for Home Manager
779 home.stateVersion = "25.05";
780}