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