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 8let 9 zjctl = import ../../packages/zjctl.nix { inherit pkgs; }; 10 zrpc-wasm = import ../../packages/zrpc-wasm.nix { inherit pkgs; }; 11in 12{ 13 # Import the home-manager modules you want to use 14 imports = [ 15 inputs.catppuccin.homeModules.catppuccin 16 inputs.niri.homeModules.niri 17 inputs.zen-browser.homeModules.beta 18 inputs.agenix.homeManagerModules.default 19 ]; 20 21 # All your user-specific packages 22 home.packages = with pkgs; [ 23 helix 24 git 25 jujutsu # jj-cli 26 htop 27 iotop 28 ncdu 29 youtube-tui 30 yt-dlp # youtube-tui and mpv need this to resolve YouTube URLs 31 zellij # terminal multiplexer 32 alacritty 33 inputs.fsel.packages.${pkgs.system}.default # App launcher / fuzzy finder 34 inputs.mako-tui.packages.${pkgs.system}.default # Notification TUI 35 bemoji # emoji picker 36 networkmanager_dmenu # network picker for fuzzel 37 quickshell # Status bar (QML-based) 38 inputs.kaleidux.packages.${pkgs.system}.default # Dynamic wallpaper daemon 39 (import ../../packages/cclip.nix { inherit pkgs; }) # Clipboard history manager 40 pavucontrol # GUI for PulseAudio/PipeWire volume control 41 playerctl # MPRIS media player control 42 (element-desktop.override { 43 commandLineArgs = "--password-store=gnome-libsecret"; 44 }) 45 fd 46 ripgrep 47 # inputs.opencodex.packages.${pkgs.system}.default 48 yazi # tui file browser 49 gh # github cli 50 forgejo-cli 51 gh-dash # github dashboard TUI 52 diffnav # git diff viewer 53 signal-desktop 54 xwayland-satellite # for running x11 apps 55 nixfmt # nix formatter 56 nil # nix language server 57 atac # postman-like TUI 58 trippy # network analyzer 59 rsync # file sync utility 60 udiskie # for mounting external drives 61 darktable # photo editing 62 zoxide 63 chromium 64 claude-code 65 libnotify # for notify-send (claude-notify) 66 zjctl # Programmatic Zellij control 67 (pkgs.writeShellScriptBin "claude-notify" '' 68 PANE_ID="$ZELLIJ_PANE_ID" 69 SESSION="$ZELLIJ_SESSION_NAME" 70 ID_FILE="/tmp/claude-notify-''${PANE_ID}" 71 ( 72 { 73 read -r NOTIFY_ID 74 echo "$NOTIFY_ID" > "$ID_FILE" 75 while read -r line; do 76 if [ "$line" = "default" ]; then 77 WIN_ID=$(niri msg windows | ${pkgs.gnugrep}/bin/grep -B1 "$SESSION" | ${pkgs.gnugrep}/bin/grep -oP '(?<=Window ID )\d+') 78 if [ -n "$WIN_ID" ]; then 79 niri msg action focus-window --id "$WIN_ID" 80 fi 81 zjctl pane focus --pane "id:terminal:$PANE_ID" 82 fi 83 done 84 } < <(${pkgs.libnotify}/bin/notify-send "Claude Code" "Waiting for your approval" \ 85 --app-name=claude-code \ 86 --action=default=Open \ 87 --print-id \ 88 --wait) 89 rm -f "$ID_FILE" 90 ) & 91 '') 92 (pkgs.writeShellScriptBin "claude-notify-clear" '' 93 PANE_ID="$ZELLIJ_PANE_ID" 94 ID_FILE="/tmp/claude-notify-''${PANE_ID}" 95 if [ -f "$ID_FILE" ]; then 96 NOTIFY_ID=$(cat "$ID_FILE") 97 ${pkgs.dbus}/bin/dbus-send --session \ 98 --print-reply \ 99 --dest=org.freedesktop.Notifications \ 100 --type=method_call \ 101 /org/freedesktop/Notifications \ 102 org.freedesktop.Notifications.CloseNotification \ 103 "uint32:$NOTIFY_ID" >/dev/null 2>&1 104 rm -f "$ID_FILE" 105 fi 106 '') 107 nautilus # file browser 108 sqlitebrowser 109 gnome-characters # symbol picker 110 sendme # file transfer 111 desktop-file-utils # for managing .desktop files 112 flyctl # fly.io cli 113 vscode-json-languageserver 114 gnome-network-displays 115 rainfrog # db tui 116 just 117 loupe # image viewer 118 glycin-loaders # various format loaders for loupe 119 docker-compose 120 discord 121 mangohud 122 prismlauncher # minecraft launcher 123 fastfetch 124 inputs.agenix.packages.${pkgs.system}.default # agenix CLI 125 age-plugin-yubikey # Yubikey support for agenix 126 # --- FONTS ARE IMPORTANT --- 127 # Berkeley Mono is the main system font, keeping JetBrains and Font Awesome for icons 128 font-awesome 129 noto-fonts 130 noto-fonts-cjk-sans 131 noto-fonts-color-emoji 132 nerd-fonts.jetbrains-mono 133 nerd-fonts.symbols-only 134 # --- POLKIT AGENT (for 1Password GUI, etc.) --- 135 lxqt.lxqt-policykit # Lightweight polkit agent 136 ]; 137 138 programs.niri = { 139 enable = true; 140 settings = { 141 window-rules = [ 142 { 143 geometry-corner-radius = { 144 top-left = 5.0; 145 top-right = 5.0; 146 bottom-left = 5.0; 147 bottom-right = 5.0; 148 }; 149 clip-to-geometry = true; 150 draw-border-with-background = false; 151 } 152 { 153 matches = [ { app-id = "^steam_app_"; } ]; 154 border.enable = false; 155 open-fullscreen = true; 156 } 157 { 158 matches = [ { app-id = "^fsel$"; } ]; 159 open-floating = true; 160 default-column-width.fixed = 800; 161 default-window-height.fixed = 500; 162 } 163 { 164 matches = [ { app-id = "^mako-tui$"; } ]; 165 open-floating = true; 166 default-column-width.fixed = 800; 167 default-window-height.fixed = 500; 168 } 169 ]; 170 debug = { 171 honor-xdg-activation-with-invalid-serial = { }; 172 }; 173 layout = { 174 focus-ring = { 175 width = 2; 176 active.color = "#8caaee"; 177 inactive.color = "#414559"; 178 }; 179 struts = { 180 top = -6; 181 bottom = -6; 182 left = 0; 183 right = 0; 184 }; 185 gaps = 8; 186 }; 187 gestures = { 188 hot-corners = { 189 enable = false; 190 }; 191 }; 192 binds = { 193 "Mod+d".action.spawn = [ 194 "alacritty" 195 "--class" 196 "fsel" 197 "-e" 198 "fsel" 199 "--detach" 200 ]; 201 "Mod+c".action.spawn = [ 202 "alacritty" 203 "--class" 204 "fsel" 205 "-e" 206 "fsel" 207 "--cclip" 208 ]; 209 "Mod+e".action.spawn = "bemoji"; 210 "Mod+n".action.spawn = [ 211 "alacritty" 212 "--class" 213 "mako-tui" 214 "-e" 215 "mako-tui" 216 ]; 217 "Mod+a".action.spawn = "alacritty"; 218 "Mod+h".action = { 219 focus-column-left = { }; 220 }; 221 "Mod+j".action = { 222 focus-workspace-down = { }; 223 }; 224 "Mod+k".action = { 225 focus-workspace-up = { }; 226 }; 227 "Mod+l".action = { 228 focus-column-right = { }; 229 }; 230 "Mod+Shift+h".action = { 231 move-column-left = { }; 232 }; 233 "Mod+Shift+j".action = { 234 move-window-down-or-to-workspace-down = { }; 235 }; 236 "Mod+Shift+k".action = { 237 move-window-up-or-to-workspace-up = { }; 238 }; 239 "Mod+Shift+l".action = { 240 move-column-right = { }; 241 }; 242 "Mod+Down".action = { 243 move-workspace-down = { }; 244 }; 245 "Mod+Up".action = { 246 move-workspace-up = { }; 247 }; 248 "Mod+p".action = { 249 show-hotkey-overlay = { }; 250 }; 251 "Mod+o".action = { 252 toggle-overview = { }; 253 }; 254 "Mod+q".action = { 255 close-window = { }; 256 }; 257 "Mod+f".action = { 258 toggle-window-floating = { }; 259 }; 260 "Mod+Shift+f".action = { 261 switch-focus-between-floating-and-tiling = { }; 262 }; 263 "Mod+m".action = { 264 fullscreen-window = { }; 265 }; 266 "Mod+s".action = { 267 screenshot = { 268 show-pointer = true; 269 }; 270 }; 271 "Mod+1".action = { 272 set-column-width = "100%"; 273 }; 274 "Mod+2".action = { 275 set-column-width = "50%"; 276 }; 277 "Mod+Minus".action = { 278 set-column-width = "-10%"; 279 }; 280 "Mod+Equal".action = { 281 set-column-width = "+10%"; 282 }; 283 "Mod+Shift+q".action = { 284 quit = { }; 285 }; 286 "Mod+Shift+r".action.spawn = [ 287 "systemctl" 288 "--user" 289 "restart" 290 "quickshell.service" 291 ]; 292 "XF86AudioPlay".action.spawn = [ 293 "playerctl" 294 "play-pause" 295 ]; 296 "XF86AudioStop".action.spawn = [ 297 "playerctl" 298 "stop" 299 ]; 300 "XF86AudioNext".action.spawn = [ 301 "playerctl" 302 "next" 303 ]; 304 "XF86AudioPrev".action.spawn = [ 305 "playerctl" 306 "previous" 307 ]; 308 "XF86MonBrightnessDown".action.spawn = [ 309 "brightnessctl" 310 "set" 311 "5%-" 312 ]; 313 "XF86MonBrightnessUp".action.spawn = [ 314 "brightnessctl" 315 "set" 316 "+5%" 317 ]; 318 }; 319 outputs = { 320 # External monitor - primary display at position (0, 0) 321 "DP-5" = { 322 scale = 2.0; 323 mode = { 324 width = 5120; 325 height = 2160; 326 refresh = 120.0; 327 }; 328 position = { 329 x = 0; 330 y = 0; 331 }; 332 }; 333 "DP-1" = { 334 scale = 2.0; 335 mode = { 336 width = 5120; 337 height = 2160; 338 refresh = 120.0; 339 }; 340 position = { 341 x = 0; 342 y = 0; 343 }; 344 }; 345 "DP-2" = { 346 scale = 1.0; 347 mode = { 348 width = 5120; 349 height = 2160; 350 refresh = 120.0; 351 }; 352 position = { 353 x = 0; 354 y = 0; 355 }; 356 }; 357 "DP-6" = { 358 scale = 2.0; 359 mode = { 360 width = 5120; 361 height = 2160; 362 refresh = 120.0; 363 }; 364 position = { 365 x = 0; 366 y = 0; 367 }; 368 }; 369 "DP-7" = { 370 scale = 2.0; 371 mode = { 372 width = 5120; 373 height = 2160; 374 refresh = 120.0; 375 }; 376 position = { 377 x = 0; 378 y = 0; 379 }; 380 }; 381 # Laptop display - secondary display positioned underneath 382 "eDP-1" = { 383 scale = 1.5; 384 mode = { 385 width = 2560; 386 height = 1600; 387 refresh = 165.0; 388 }; 389 position = { 390 x = 0; 391 y = 1080; # Position underneath the external monitor (2160 / 2 scale = 1080 logical height) 392 }; 393 }; 394 }; 395 spawn-at-startup = [ 396 { command = [ "xwayland-satellite" ]; } 397 { command = [ "cclipd" ]; } 398 ]; 399 environment = { 400 DISPLAY = ":0"; 401 }; 402 }; 403 }; 404 405 # Allow unfree packages 406 nixpkgs.config.allowUnfree = true; 407 408 nixpkgs.config.permittedInsecurePackages = [ 409 "libsoup-2.74.3" 410 ]; 411 412 # Download wallpapers at activation time (skips dead URLs gracefully) 413 home.activation.downloadWallpapers = 414 let 415 wallpapers = import ./wallpapers.nix; 416 downloads = builtins.concatStringsSep "\n" ( 417 map (wp: '' 418 if [ ! -f "$DIR/${wp.filename}" ]; then 419 echo "Downloading ${wp.filename}..." 420 ${pkgs.curl}/bin/curl -fsSL -o "$DIR/${wp.filename}" ${ 421 builtins.replaceStrings [ "\"" ] [ "\\\"" ] wp.url 422 } || echo "WARNING: Failed to download ${wp.filename}, skipping" 423 fi 424 '') wallpapers 425 ); 426 in 427 config.lib.dag.entryAfter [ "writeBoundary" ] '' 428 DIR="${config.home.homeDirectory}/Pictures/Wallpapers" 429 mkdir -p "$DIR" 430 ${downloads} 431 ''; 432 433 # Kaleidux wallpaper daemon config 434 xdg.configFile."kaleidux/config.toml".text = '' 435 [global] 436 monitor-behavior = "independent" 437 video-ratio = 50 438 sorting = "loveit" 439 transition-time = 1000 440 441 [any] 442 path = "${config.home.homeDirectory}/Pictures/Wallpapers" 443 duration = "15m" 444 transition = { type = "fade" } 445 ''; 446 447 # Quickshell status bar 448 xdg.configFile."quickshell" = { 449 source = ./quickshell; 450 recursive = true; 451 }; 452 453 systemd.user.services.kaleidux = { 454 Unit = { 455 Description = "Kaleidux dynamic wallpaper daemon"; 456 After = [ "graphical-session.target" ]; 457 PartOf = [ "graphical-session.target" ]; 458 }; 459 Service = { 460 ExecStart = "${inputs.kaleidux.packages.${pkgs.system}.default}/bin/kaleidux-daemon"; 461 Restart = "on-failure"; 462 RestartSec = 2; 463 }; 464 Install = { 465 WantedBy = [ "graphical-session.target" ]; 466 }; 467 }; 468 469 systemd.user.services.quickshell = { 470 Unit = { 471 Description = "QuickShell status bar"; 472 After = [ "graphical-session.target" ]; 473 PartOf = [ "graphical-session.target" ]; 474 }; 475 Service = { 476 ExecStart = "${pkgs.quickshell}/bin/quickshell"; 477 Restart = "on-failure"; 478 RestartSec = 2; 479 }; 480 Install = { 481 WantedBy = [ "graphical-session.target" ]; 482 }; 483 }; 484 485 systemd.user.services.quickshell-reload = { 486 Unit = { 487 Description = "Reload QuickShell on wake or display change"; 488 After = [ 489 "quickshell.service" 490 "graphical-session.target" 491 ]; 492 PartOf = [ "graphical-session.target" ]; 493 }; 494 Service = { 495 Type = "simple"; 496 ExecStart = "${pkgs.writeShellScript "quickshell-reload" '' 497 LOCKFILE="/tmp/quickshell-reload.lock" 498 499 do_restart() { 500 ( 501 ${pkgs.util-linux}/bin/flock -xn 200 || exit 0 502 sleep 2 503 ${pkgs.systemd}/bin/systemctl --user restart quickshell.service 504 sleep 3 505 ) 200>"$LOCKFILE" 506 } 507 508 # Sleep/wake monitor 509 ${pkgs.dbus}/bin/dbus-monitor --system \ 510 "type='signal',interface='org.freedesktop.login1.Manager',member='PrepareForSleep'" 2>/dev/null | \ 511 while IFS= read -r line; do 512 if [[ "$line" == *"boolean false"* ]]; then 513 do_restart 514 fi 515 done & 516 517 # Display hotplug monitor 518 ${pkgs.systemd}/bin/udevadm monitor --property --subsystem-match=drm 2>/dev/null | \ 519 while IFS= read -r line; do 520 if [[ "$line" == *"HOTPLUG=1"* ]]; then 521 do_restart 522 fi 523 done & 524 525 wait 526 ''}"; 527 Restart = "on-failure"; 528 RestartSec = 5; 529 }; 530 Install = { 531 WantedBy = [ "graphical-session.target" ]; 532 }; 533 }; 534 535 programs.ssh = { 536 enable = true; 537 enableDefaultConfig = false; 538 matchBlocks = { 539 "*" = { 540 identityFile = [ 541 "${config.home.homeDirectory}/.ssh/id_ed25519_sk_rk" 542 "${config.home.homeDirectory}/.ssh/id_rsa.pub" 543 ]; 544 }; 545 }; 546 }; 547 548 programs.awscli = { 549 enable = true; 550 settings = { 551 "default" = { 552 region = "us-east-1"; 553 }; 554 }; 555 }; 556 557 services.udiskie = { 558 enable = true; 559 tray = "never"; 560 automount = true; 561 }; 562 563 services.mako = { 564 enable = true; 565 settings = { 566 border-radius = 8; 567 border-size = 2; 568 padding = "12"; 569 margin = "12"; 570 font = "BerkeleyMono Nerd Font 11"; 571 on-button-left = "invoke-default-action"; 572 on-button-right = "dismiss"; 573 }; 574 }; 575 576 catppuccin = { 577 enable = true; 578 flavor = "frappe"; 579 }; 580 581 programs.direnv.enable = true; 582 583 programs.atuin = { 584 enable = true; 585 enableFishIntegration = true; 586 daemon.enable = true; 587 settings = { 588 filter_mode_shell_up_key_binding = "session"; 589 }; 590 }; 591 592 programs.zellij = { 593 enable = true; 594 settings = { 595 keybinds = { 596 unbind = [ 597 "Ctrl q" 598 "Ctrl o" 599 ]; 600 normal = { 601 "bind \"Ctrl m\"" = { 602 SwitchToMode = "Session"; 603 }; 604 }; 605 }; 606 load_plugins = { 607 "\"file:~/.config/zellij/plugins/zrpc.wasm\"" = { }; 608 }; 609 pane_frames = false; 610 show_startup_tips = false; 611 ui = { 612 pane_frames.hide_session_name = true; 613 }; 614 }; 615 }; 616 617 xdg.configFile."zellij/plugins/zrpc.wasm".source = "${zrpc-wasm}/zrpc.wasm"; 618 619 home.file.".claude/settings.json".text = builtins.toJSON { 620 enabledPlugins = { 621 "rust-analyzer-lsp@claude-plugins-official" = true; 622 "typescript-lsp@claude-plugins-official" = true; 623 }; 624 hooks = { 625 Notification = [ 626 { 627 matcher = "permission_prompt"; 628 hooks = [ 629 { 630 type = "command"; 631 command = "claude-notify"; 632 } 633 ]; 634 } 635 ]; 636 Stop = [ 637 { 638 hooks = [ 639 { 640 type = "command"; 641 command = "claude-notify-clear"; 642 } 643 ]; 644 } 645 ]; 646 }; 647 }; 648 649 xdg.configFile."zellij/layouts/split.kdl".text = '' 650 layout { 651 tab { 652 pane size="50%" 653 pane split_direction="vertical" size="50%" { 654 pane 655 pane 656 } 657 } 658 } 659 ''; 660 661 xdg.configFile."gh-dash/config.yml".text = '' 662 prSections: 663 - title: My Pull Requests 664 filters: is:open author:@me 665 - title: Review Requested 666 filters: is:open review-requested:@me 667 issuesSections: 668 - title: My Issues 669 filters: is:open author:@me 670 pager: 671 diff: diffnav 672 keybindings: 673 prs: 674 - key: T 675 name: enhance 676 command: >- 677 zellij run -- gh enhance -R {{.RepoName}} {{.PrNumber}} 678 ''; 679 680 programs.zen-browser.enable = true; 681 # programs.swww.enable = true; 682 programs.zoxide = { 683 enable = true; 684 enableFishIntegration = true; 685 }; 686 687 programs.obs-studio = { 688 enable = true; 689 plugins = with pkgs.obs-studio-plugins; [ 690 obs-backgroundremoval 691 ]; 692 }; 693 694 # Program configurations 695 programs.mpv = { 696 enable = true; 697 scripts = [ pkgs.mpvScripts.mpris ]; 698 config.af = "loudnorm=I=-16:TP=-1.5:LRA=11"; 699 }; 700 xdg.configFile."youtube-tui/commands.yml".source = ./youtube-tui/commands.yml; 701 programs.git = { 702 enable = true; 703 settings = { 704 user = { 705 name = "seanaye"; 706 email = "hello@seanaye.ca"; 707 }; 708 init.defaultBranch = "main"; 709 commit.gpgSign = true; 710 gpg.format = "ssh"; 711 user.signingKey = "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOIgEteUEW06dnBHe2z8vNLwz2iMKe8bba6JgMmOUpcBAAAABHNzaDo= sean@framework16"; 712 gpg.ssh.allowedSignersFile = "${config.home.homeDirectory}/.ssh/allowed_signers"; 713 diff.tool = "diffnav"; 714 difftool.prompt = false; 715 "difftool \"diffnav\"".cmd = "diffnav \"$LOCAL\" \"$REMOTE\""; 716 }; 717 }; 718 programs.jujutsu = { 719 enable = true; 720 settings = { 721 user = { 722 email = "hello@seanaye.ca"; 723 name = "Sean Aye"; 724 }; 725 ui."diff-formatter" = ":git"; 726 signing = { 727 sign-all = true; 728 behavior = "own"; 729 backend = "ssh"; 730 key = "${config.home.homeDirectory}/.ssh/id_ed25519_sk_rk"; 731 backends.ssh.allowed-signers = "${config.home.homeDirectory}/.ssh/allowed_signers"; 732 }; 733 }; 734 }; 735 xdg.configFile."jj/conf.d/diffnav.toml".text = '' 736 [[--scope]] 737 --when.commands = ["diff", "show"] 738 [--scope.ui] 739 pager = "diffnav" 740 ''; 741 742 programs.home-manager.enable = true; 743 744 programs.fish = { 745 enable = true; 746 shellAliases = { 747 agenix = "agenix -i ~/.config/agenix/yubikey-identity.txt"; 748 }; 749 interactiveShellInit = '' 750 set fish_greeting 751 # Set 1Password SSH agent socket 752 set -gx SSH_AUTH_SOCK ${config.home.homeDirectory}/.1password/agent.sock 753 # Load 1Password CLI plugins 754 if test -f ~/.config/op/plugins.sh 755 source ~/.config/op/plugins.sh 756 end 757 # Auto-launch zellij if not already inside a session 758 # Use systemd-run to escape niri's session scope so the server 759 # survives logout 760 if not set -q ZELLIJ 761 systemd-run --user --scope zellij 762 else 763 fastfetch --logo small 764 end 765 766 function y 767 set tmp (mktemp -t "yazi-cwd.XXXXXX") 768 yazi $argv --cwd-file="$tmp" 769 if read -z cwd < "$tmp"; and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ] 770 builtin cd -- "$cwd" 771 end 772 rm -f -- "$tmp" 773 end 774 ''; 775 functions = { 776 s3edit = '' 777 set file (basename $argv[1]) 778 set tmpfile /tmp/$file 779 aws s3 cp $argv[1] $tmpfile 780 and $EDITOR $tmpfile 781 and aws s3 cp $tmpfile $argv[1] 782 ''; 783 }; 784 }; 785 786 programs.starship = { 787 enable = true; 788 enableFishIntegration = true; 789 }; 790 791 programs.alacritty = { 792 enable = true; 793 settings = { 794 terminal.shell.program = "fish"; 795 window = { 796 decorations = "none"; 797 opacity = 0.9; 798 }; 799 font = { 800 normal = { 801 family = "BerkeleyMono Nerd Font"; 802 style = "Regular"; 803 }; 804 size = 12.0; 805 }; 806 }; 807 808 }; 809 810 programs.helix = { 811 enable = true; 812 settings = { 813 editor = { 814 bufferline = "multiple"; 815 file-picker = { 816 hidden = false; 817 git-ignore = true; 818 }; 819 cursor-shape = { 820 insert = "bar"; 821 normal = "block"; 822 select = "underline"; 823 }; 824 line-number = "relative"; 825 cursorline = true; 826 auto-format = true; 827 end-of-line-diagnostics = "hint"; 828 soft-wrap = { 829 enable = true; 830 }; 831 lsp = { 832 display-inlay-hints = true; 833 display-messages = true; 834 display-progress-messages = true; 835 }; 836 inline-diagnostics = { 837 cursor-line = "hint"; 838 }; 839 }; 840 keys = { 841 normal = { 842 esc = [ 843 "keep_primary_selection" 844 "collapse_selection" 845 ]; 846 }; 847 848 }; 849 }; 850 languages = { 851 852 language-server.rust-analyzer = { 853 config = { 854 check = { 855 command = "clippy"; 856 }; 857 checkOnSave = true; 858 cargo = { 859 allFeatures = true; 860 }; 861 }; 862 }; 863 language-server.deno-lsp = { 864 command = "deno"; 865 args = [ "lsp" ]; 866 config.deno.enable = true; 867 }; 868 869 language = [ 870 { 871 name = "html"; 872 formatter = { 873 command = "prettier"; 874 args = [ 875 "--parser" 876 "html" 877 ]; 878 }; 879 } 880 { 881 name = "nix"; 882 auto-format = true; 883 formatter = { 884 command = "${pkgs.nixfmt}/bin/nixfmt"; 885 }; 886 } 887 { 888 name = "kotlin"; 889 auto-format = true; 890 } 891 { 892 name = "rust"; 893 auto-format = true; 894 formatter = { 895 command = "rustfmt"; 896 args = [ 897 "--edition" 898 "2024" 899 ]; 900 }; 901 indent = { 902 tab-width = 4; 903 unit = "t"; 904 }; 905 } 906 { 907 name = "astro"; 908 auto-format = true; 909 formatter = { 910 command = "npx"; 911 args = [ 912 "prettier" 913 "--plugin" 914 "prettier-plugin-astro" 915 "--parser" 916 "astro" 917 ]; 918 }; 919 } 920 { 921 name = "json"; 922 auto-format = true; 923 } 924 { 925 name = "just"; 926 auto-format = true; 927 formatter = { 928 command = "just"; 929 args = [ 930 "--justfile" 931 "/dev/stdin" 932 "--dump" 933 ]; 934 }; 935 } 936 { 937 name = "toml"; 938 auto-format = true; 939 formatter = { 940 command = "taplo"; 941 args = [ 942 "format" 943 "-" 944 ]; 945 }; 946 } 947 # { 948 # name = "typescript"; 949 # roots = [ 950 # "deno.json" 951 # "deno.jsonc" 952 # ]; 953 # file-types = [ 954 # "ts" 955 # "tsx" 956 # ]; 957 # auto-format = true; 958 # language-servers = [ "deno-lsp" ]; 959 # } 960 ]; 961 }; 962 }; 963 964 dconf.settings = { 965 "org/gnome/desktop/interface" = { 966 color-scheme = "prefer-dark"; 967 enable-hot-corners = false; 968 }; 969 }; 970 971 # Font rendering configuration 972 fonts.fontconfig = { 973 enable = true; 974 defaultFonts = { 975 monospace = [ "BerkeleyMono Nerd Font" ]; 976 sansSerif = [ "Noto Sans" ]; 977 serif = [ "Noto Serif" ]; 978 }; 979 }; 980 981 # Cursor configuration 982 home.pointerCursor = { 983 name = "Adwaita"; 984 package = pkgs.adwaita-icon-theme; 985 size = 16; 986 x11.enable = true; 987 gtk.enable = true; 988 }; 989 990 # Session variables 991 home.sessionVariables = { 992 EDITOR = "hx"; 993 VISUAL = "hx"; 994 SUDO_EDITOR = "hx"; 995 SSH_AUTH_SOCK = "${config.home.homeDirectory}/.1password/agent.sock"; 996 SSH_ASKPASS = "${pkgs.openssh-askpass}/bin/gnome-ssh-askpass3"; 997 SSH_ASKPASS_REQUIRE = "prefer"; 998 }; 999 1000 # SSH allowed signers for commit signature verification 1001 home.file.".ssh/allowed_signers".text = '' 1002 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= 1003 hello@seanaye.ca sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAILdilHXHdAP/V8Zq28EzHKtLAMMaFPu4+1det2N50QfhAAAABHNzaDo= sean@framework16 1004 ''; 1005 1006 # Yubikey identity for agenix (not secret - just a reference to the hardware key) 1007 home.file.".config/agenix/yubikey-identity.txt".text = '' 1008 # Serial: 26930059, Slot: 1 1009 # Name: agenix 1010 # Recipient: age1yubikey1qw64ag5lzvn9ekrflu5ruj4a6ucycscl6ctk39fjzf76jptsay39z442pxv 1011 AGE-PLUGIN-YUBIKEY-1304E5QVZZD74FKSP8FMCT 1012 ''; 1013 1014 # Same identity for sops (expects keys at this path by default) 1015 home.file.".config/sops/age/keys.txt".text = '' 1016 # Serial: 26930059, Slot: 1 1017 # Name: agenix 1018 # Recipient: age1yubikey1qw64ag5lzvn9ekrflu5ruj4a6ucycscl6ctk39fjzf76jptsay39z442pxv 1019 AGE-PLUGIN-YUBIKEY-1304E5QVZZD74FKSP8FMCT 1020 ''; 1021 1022 # yubikey sudo access 1023 home.file.".config/Yubico/u2f_keys".text = '' 1024 sean:2HY//CedY0ZSrKf57lT7abxG8+8bkPyxCfp/0HMlk/il/5W8pn4R5xLiZDcJtvL85U24h9IEIxa4CS22mpaDSA==,gcD/dpLdwvUFcGGPHS4qNsarH4lOEy1AJAT7zoC6BPlFRUYEa8DpVVKFTcvT6PotjnSHSrWWGb/f3U2k2jIOIw==,es256,+presence 1025 ''; 1026 1027 # Set the state version for Home Manager 1028 home.stateVersion = "25.05"; 1029}