me like nix
0

Configure Feed

Select the types of activity you want to include in your feed.

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