{ config, pkgs, lib, ... }: let profileBin = "${config.home.profileDirectory}/bin"; # System binaries path - same on both NixOS and Darwin systemBin = "/run/current-system/sw/bin"; defaultBin = "/nix/var/nix/profiles/default/bin"; darwinHomebrewDir = if pkgs.stdenv.hostPlatform.isAarch64 then "/opt/homebrew" else "/usr/local"; homebrewBin = "${darwinHomebrewDir}/bin"; homebrewSbin = "${darwinHomebrewDir}/sbin"; homebrewPaths = if pkgs.stdenv.hostPlatform.isDarwin then lib.unique [ homebrewBin homebrewSbin ] else [ ]; # Add common macOS system paths that may contain user-installed CLIs macosSystemPaths = if pkgs.stdenv.hostPlatform.isDarwin then [ "/usr/local/bin" "/usr/bin" "/bin" "/usr/sbin" "/sbin" ] else [ ]; formatPathList = paths: lib.concatMapStrings (path: " \"${path}\"\n") paths; in { imports = [ ./starship ]; programs.nushell.enable = lib.mkDefault true; programs.nushell.extraConfig = '' # Dotfiles QA validation command def dotfiles-qa [] { let dotfiles_dir = "${config.home.homeDirectory}/Development/dotfiles" print $"(ansi green_bold)Running dotfiles QA validation...(ansi reset)\n" # Step 1: Format check print $"(ansi blue)1. Formatting nix files...(ansi reset)" cd $dotfiles_dir nix fmt . if $env.LAST_EXIT_CODE != 0 { print $"(ansi red_bold)✗ Formatting failed(ansi reset)" return } print $"(ansi green)✓ Formatting complete(ansi reset)\n" # Step 2: Flake check print $"(ansi blue)2. Running flake check...(ansi reset)" nix flake check if $env.LAST_EXIT_CODE != 0 { print $"(ansi red_bold)✗ Flake check failed(ansi reset)" return } print $"(ansi green)✓ Flake check passed(ansi reset)\n" # Step 3: Build (without activation) print $"(ansi blue)3. Building darwin configuration (no activation)...(ansi reset)" darwin-rebuild build --flake $"($dotfiles_dir)#macbook-pro" if $env.LAST_EXIT_CODE != 0 { print $"(ansi yellow)⚠ Build had warnings, but may still work(ansi reset)\n" } else { print $"(ansi green)✓ Build successful(ansi reset)\n" } print $"(ansi green_bold)✓ Core QA checks passed!(ansi reset)" } # Beads helper functions for AI agent workflows # Safe Beads initialization with git repository check def bd-init [] { if not (".git" | path exists) and not (".git" | path type) == "dir" { print $"(ansi red_bold)Error: Not in a git repository(ansi reset)" print "Beads requires a git repository. Initialize git first:" print " git init" return } if (".beads" | path exists) { print $"(ansi yellow)Beads already initialized in this project(ansi reset)" return } print $"(ansi green)Initializing Beads...(ansi reset)" bd init if $env.LAST_EXIT_CODE == 0 { print $"(ansi green_bold)✓ Beads initialized successfully(ansi reset)" print "" print "Next steps:" print " bd create --title \"Your task\" --type feature" print " bd ready" } } # View ready tasks with structured output def bd-ready [] { if not (".beads" | path exists) { print $"(ansi red)Not a Beads project. Run 'bd-init' first.(ansi reset)" return } let ready_tasks = (bd ready --json | from json) if ($ready_tasks | is-empty) { print $"(ansi yellow)No ready tasks(ansi reset)" return } print $"(ansi green_bold)Ready Tasks:(ansi reset)\n" $ready_tasks | each {|task| print $"(ansi cyan)[$($task.id)](ansi reset) ($task.title)" print $" Type: ($task.type) | Priority: ($task.priority) | Status: ($task.status)" if ($task.description? != null) and ($task.description | str length) > 0 { print $" ($task.description)" } print "" } | ignore } # Sync Beads database with git def bd-sync [] { if not (".beads" | path exists) { print $"(ansi red)Not a Beads project(ansi reset)" return } print $"(ansi blue)Syncing Beads database...(ansi reset)" bd sync if $env.LAST_EXIT_CODE == 0 { print $"(ansi green)✓ Sync complete(ansi reset)" } } ''; programs.nushell.envFile.text = '' # Set XDG Base Directory environment variables $env.XDG_CONFIG_HOME = "${config.xdg.configHome}" $env.XDG_DATA_HOME = "${config.xdg.dataHome}" $env.XDG_CACHE_HOME = "${config.xdg.cacheHome}" let nix_paths = [ ${ formatPathList [ profileBin systemBin defaultBin ] } ] let homebrew_paths = [ ${formatPathList homebrewPaths} ] let macos_system_paths = [ ${formatPathList macosSystemPaths} ] let path_candidates = ($nix_paths | append $homebrew_paths | append $macos_system_paths | flatten) if ($env.PATH? == null) { $env.PATH = $path_candidates } else { for path in $path_candidates { if not ($env.PATH | any {|it| $it == $path}) { $env.PATH = ($env.PATH | append $path) } } } $env.NIX_PROFILES = "/run/current-system/sw ${config.home.profileDirectory}" # Load sops-managed API keys as environment variables let secrets_dir = "${config.xdg.configHome}/secrets" def --env load-secret [secret_name: string, env_var: string] { let secret_file = ($secrets_dir | path join $secret_name) if ($secret_file | path exists) { let secret_value = (open --raw $secret_file | str trim) {} | insert $env_var $secret_value | load-env } } load-secret "zai-api-key" "ZAI_API_KEY" load-secret "openai-api-key" "OPENAI_API_KEY" load-secret "openrouter-api-key" "OPENROUTER_API_KEY" load-secret "moonshot-api-key" "MOONSHOT_API_KEY" load-secret "anthropic-api-key" "ANTHROPIC_API_KEY" load-secret "exa-api-key" "EXA_API_KEY" load-secret "fal-api-key" "FAL_API_KEY" load-secret "groq-api-key" "GROQ_API_KEY" load-secret "firecrawl-api-key" "FIRECRAWL_API_KEY" ''; }