| name | Nix Ecosystem |
| description | This skill should be used when the user asks to "write nix", "nix expression", "flake.nix", "home-manager config", "programs.*", "services.*", or works with Nix language, flakes, or Home Manager. Provides comprehensive Nix ecosystem patterns and best practices. |
Only evaluates needed attributes
let expensive = builtins.trace "Computing expensive" (1 + 1); in { a = 1; b = expensive; }.a # Does not compute expensive
All Nix functions are pure. Same inputs always produce same outputs. Pure function - always returns same result for same input double = x: x * 2;Avoid side effects; use derivations for build actions
buildResult = pkgs.stdenv.mkDerivation { ... };
Primary data structure in Nix Basic attribute set { attr1 = value1; attr2 = value2; }Access patterns
set.attr set."attr-with-dashes"
Recursive attribute set
rec { a = 1; b = a + 1; }
Local bindings for complex expressions let helper = x: x + 1; value = helper 5; in value * 2 Bring attribute set into scope with pkgs; [ git vim tmux ] Avoid nested with; prefer explicit references for clarity Copy attributes from another set { inherit (pkgs) git vim; inherit name version; } Modify or extend nixpkgs final: prev: { myPackage = prev.myPackage.override { ... }; } Do you need to modify existing packages or add new ones globally? Use overlays to extend nixpkgs Use local package definitions with callPackage Dependency injection pattern myPackage = pkgs.callPackage ./package.nix { }; Standard package builder pkgs.stdenv.mkDerivation { pname = "mypackage"; version = "1.0.0"; src = fetchFromGitHub { ... };nativeBuildInputs = [ pkgs.cmake ]; buildInputs = [ pkgs.openssl ];
installPhase = '' mkdir -p $out/bin cp mypackage $out/bin/ ''; }
Required attributes: pname, version, src Standard phases: unpackPhase, patchPhase, configurePhase, buildPhase, installPhase Dependency specification in derivations { # Tools run at build time (compilers, build tools) nativeBuildInputs = [ cmake pkg-config ];Libraries linked at runtime
buildInputs = [ openssl zlib ]; }
NixOS/Home Manager module structure { config, lib, pkgs, ... }: { options.myModule = { enable = lib.mkEnableOption "my module"; setting = lib.mkOption { type = lib.types.str; default = "value"; description = "A setting"; }; };config = lib.mkIf config.myModule.enable { # configuration when enabled }; }
Define module options with types and defaults options.myOption = lib.mkOption { type = lib.types.bool; default = false; description = "Enable my feature"; example = true; }; Common types: lib.types.bool, lib.types.str, lib.types.listOf, lib.types.attrsOf Shorthand for boolean enable option enable = lib.mkEnableOption "my service"; Directly referencing absolute paths breaks reproducibility Use fetchurl, fetchFromGitHub, or relative paths within the repository Multiple nested with statements reduce code clarity Prefer explicit attribute access (pkgs.git) for better readability Recursive attribute sets can be hard to understand and maintain Use let-in for complex recursive definitions Using string interpolation for path operations is error-prone Use lib functions for path manipulation (lib.concatStringsSep, builtins.path) Basic structure of a flake.nix file { description = "Project description";inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; };
outputs = { self, nixpkgs, ... }@inputs: { # output attributes }; }
Derivations for nix build packages.x86_64-linux.default = pkgs.hello; Development environments for nix develop devShells.x86_64-linux.default = pkgs.mkShell { packages = [ pkgs.nodejs ]; }; Runnable applications for nix run apps.x86_64-linux.default = { type = "app"; program = "${pkgs.hello}/bin/hello"; }; Nixpkgs overlays overlays.default = final: prev: { myPackage = prev.callPackage ./myPackage.nix { }; }; NixOS modules nixosModules.default = { config, lib, pkgs, ... }: { options.services.myService = { ... }; config = { ... }; }; Home Manager modules homeManagerModules.default = { config, lib, pkgs, ... }: { options.programs.myProgram = { ... }; config = { ... }; }; Full NixOS system configurations nixosConfigurations.hostname = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix ]; }; Home Manager configurations homeConfigurations."user@host" = home-manager.lib.homeManagerConfiguration { pkgs = nixpkgs.legacyPackages.x86_64-linux; modules = [ ./home.nix ]; }; Reference GitHub repositories as flake inputs inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; # Specific branch stable.url = "github:NixOS/nixpkgs/nixos-24.11"; # Specific revision pinned.url = "github:owner/repo/abc123def"; }; Share input between flakes to avoid duplication home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; Non-flake inputs for legacy repositories my-source = { url = "github:owner/repo"; flake = false; }; Generate outputs for multiple systems outputs = { self, nixpkgs, ... }: let systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs systems; in { packages = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; in { default = pkgs.hello; } ); }; Does your flake need to support multiple platforms? Use per-system pattern with genAttrs or flake-utils Define outputs for single system directly Development environment with packages and hooks devShells.default = pkgs.mkShell { packages = with pkgs; [ nodejs yarn ]; shellHook = '' echo "Development environment ready" ''; }; Update all inputs to their latest versions Regular dependency updates Update a specific input Selective updates to test compatibility Display all flake outputs Exploring available packages and configurations Validate flake and run checks CI/CD validation, pre-commit checks Standard Home Manager module structure { config, pkgs, lib, ... }: { options.custom.feature = { enable = lib.mkEnableOption "feature description"; };config = lib.mkIf config.custom.feature.enable { # configuration when enabled }; }
Organize modules by program name home-manager/programs/git.nix home-manager/programs/neovim.nix home-manager/programs/tmux.nix Organize modules by category home-manager/development/default.nix home-manager/shell/default.nix home-manager/editors/default.nix Import multiple modules imports = [ ./programs/git.nix ./programs/neovim.nix ./shell/fish.nix ]; Enable a program with defaults programs.git.enable = true; Enable and configure a program programs.git = { enable = true; userName = "name"; userEmail = "email"; extraConfig = { core.editor = "nvim"; init.defaultBranch = "main"; }; }; Does Home Manager provide built-in module for this program? Use programs.* with configuration options Use home.file or xdg.configFile for manual configuration Use alternative package version programs.git = { enable = true; package = pkgs.gitFull; }; Manage dotfiles directly home.file.".config/app/config" = { source = ./config; # or text = '' key = value ''; }; XDG config directory files xdg.configFile."app/config".source = ./config; Environment variables for login shells home.sessionVariables = { EDITOR = "nvim"; PAGER = "less"; }; Add directories to PATH home.sessionPath = [ "$HOME/.local/bin" ]; Git version control configuration programs.git = { enable = true; userName = "Your Name"; userEmail = "email@example.com"; signing = { key = "KEY_ID"; signByDefault = true; }; aliases = { co = "checkout"; st = "status"; }; extraConfig = { core.editor = "nvim"; }; }; Neovim editor configuration programs.neovim = { enable = true; viAlias = true; vimAlias = true; plugins = with pkgs.vimPlugins; [ vim-commentary vim-surround ]; extraConfig = '' set number set relativenumber ''; extraLuaConfig = '' vim.opt.expandtab = true ''; }; Fish shell configuration programs.fish = { enable = true; shellInit = '' set -g fish_greeting ''; shellAliases = { ll = "ls -lah"; }; functions = { gitignore = "curl -sL https://www.gitignore.io/api/$argv"; }; plugins = [ { name = "z"; src = pkgs.fishPlugins.z.src; } ]; }; Terminal multiplexer configuration programs.tmux = { enable = true; terminal = "screen-256color"; keyMode = "vi"; plugins = with pkgs.tmuxPlugins; [ sensible yank ]; extraConfig = '' set -g mouse on ''; }; Directory-specific environment loader programs.direnv = { enable = true; nix-direnv.enable = true; enableBashIntegration = true; enableZshIntegration = true; }; Use programs.\* when available instead of manual configuration Set home.stateVersion to your initial HM version and do not change after initial setup unless migrating Group related configurations in separate modules for maintainability Use lib.mkIf for conditional configuration Prefer xdg.configFile over home.file for XDG-compliant apps Use home.packages for additional packages not configured via programs.* Track Home Manager state version for compatibility home.stateVersion = "24.11"; # Current stable. 25.05 (upcoming). Do not change after initial setup unless migrating HM 24.11+ (25.05 upcoming) supports minimal mode for faster evaluation imports = [ "${modulesPath}/programs/fzf.nix" ]; Advanced users optimizing evaluation time Understand Nix expression requirements 1. Identify target: flake, module, derivation, or expression 2. Check existing patterns in project 3. Consult Serena memories for conventions Write idiomatic Nix code 1. Follow patterns from decision trees 2. Use appropriate lib functions 3. Apply best practices for target type Verify Nix expression correctness 1. Check syntax with nix flake check 2. Verify evaluation with nix eval 3. Test build with nix build Style inconsistency in Nix expression Note issue, suggest formatting Evaluation error or type mismatch Debug with --show-trace, fix expression Build failure in derivation Analyze build log, present options to user Impure expression breaking reproducibility Block operation, require pure alternatives Use lib functions for complex operations Follow project's existing Nix patterns Maintain reproducibility in all expressions Impure paths and absolute references Nested with statements Overusing rec for attribute sets Architecture and module dependency analysis for Nix configurations Implementation of flake outputs, Home Manager modules, and NixOS configurations Nix expression validation, formatting, and best practices enforcement Symbol operations for navigating Nix expressions and module definitions Fetch latest nixpkgs and Home Manager documentation Debug evaluation errors and understand derivation failures Basic NixOS configuration with Home Manager nixosConfigurations.hostname = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix home-manager.nixosModules.home-manager ]; specialArgs = { inherit inputs; }; }; Standalone Home Manager without NixOS homeConfigurations."user@host" = home-manager.lib.homeManagerConfiguration { pkgs = nixpkgs.legacyPackages.x86_64-linux; modules = [ ./home.nix ]; extraSpecialArgs = { inherit inputs; }; }; Home Manager as a NixOS module { imports = [ home-manager.nixosModules.home-manager ];home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; home-manager.users.username = import ./home.nix; }