Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component...
npx skills add randoneering/randoneering-agent-guide --skill "nix"
Install specific skill from multi-skill repository
# Description
Nix/NixOS package development, maintenance, and system configuration. Triggers: .nix, flake.nix, default.nix, nixpkgs, derivation, buildRustPackage, buildPythonPackage, NixOS modules. Covers package development, nixpkgs contributions, NixOS configuration, flakes, derivations, overlays, and troubleshooting build failures.
# SKILL.md
name: nix
description: "Nix/NixOS package development, maintenance, and system configuration. Triggers: .nix, flake.nix, default.nix, nixpkgs, derivation, buildRustPackage, buildPythonPackage, NixOS modules. Covers package development, nixpkgs contributions, NixOS configuration, flakes, derivations, overlays, and troubleshooting build failures."
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Nix/NixOS Development Workflow
Comprehensive guidelines for Nix package development, nixpkgs maintenance, NixOS configuration, and build troubleshooting.
Tool Grid
| Task | Command | Notes |
|---|---|---|
| Build package | nix-build -A <attr> |
Legacy builder |
| Build with flakes | nix build .#<package> |
Modern flake-based |
| Develop environment | nix develop |
Enter dev shell with dependencies |
| Run package | nix run .#<package> |
Execute from flake |
| Show derivation | nix show-derivation |
Inspect build inputs |
| Search packages | nix search nixpkgs <query> |
Find packages |
| Update flake inputs | nix flake update |
Update all inputs |
| Build NixOS config | nixos-rebuild build |
Test config without activation |
| Check syntax | nix-instantiate --parse |
Validate Nix syntax |
| Evaluate expression | nix-instantiate --eval |
Check attribute values |
| Format code | nixfmt or alejandra |
Format Nix files |
Critical Nix Principles
Purity and Reproducibility
- Builds MUST be pure and reproducible
- MUST NOT access network during build phase
- MUST declare all dependencies explicitly
- Use
fetchFromGitHub,fetchurl, etc. in fetchers, not in build phase - Use
nix-hashornix-prefetch-urlto get correct hashes
Immutability
- Derivations are immutable once built
- MUST NOT modify
/nix/storecontents - Use overlays for local modifications
- Patches go in
patches/directory, referenced in derivation
Package Development
Derivation Structure
Standard derivation template:
{ lib
, stdenv
, fetchFromGitHub
, buildRustPackage # or buildPythonPackage, buildGoModule, etc.
, pkg-config
, openssl
, ...
}:
buildRustPackage rec {
pname = "package-name";
version = "1.0.0";
src = fetchFromGitHub {
owner = "owner-name";
repo = "repo-name";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
cargoHash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
nativeBuildInputs = [ pkg-config ];
buildInputs = [ openssl ];
meta = with lib; {
description = "Short package description";
homepage = "https://example.com";
license = licenses.mit;
maintainers = with maintainers; [ your-handle ];
mainProgram = "executable-name";
};
}
Build Input Classification
nativeBuildInputs: Tools needed at build time (run on build platform)
- Examples: pkg-config, cmake, cargo, rustc, makeWrapper
- These execute during the build
buildInputs: Libraries needed at build AND runtime (target platform)
- Examples: openssl, sqlite, postgresql
- Linked into the final binary
propagatedBuildInputs: Dependencies that consumers also need
- Examples: Python/Node libraries that import other libraries
- Automatically added to dependent packages
checkInputs: Dependencies only for running tests
- Examples: pytest, cargo-nextest
- Only needed when doCheck = true
Language-Specific Builders
Rust Packages
buildRustPackage rec {
pname = "rust-app";
version = "1.0.0";
src = fetchFromGitHub { ... };
cargoHash = "sha256-..."; # Use lib.fakeHash initially, update after first build
# Optional: Lock file handling
cargoLock = {
lockFile = ./Cargo.lock;
outputHashes = {
"dependency-0.1.0" = "sha256-...";
};
};
# Build-time flags
cargoBuildFlags = [ "--all-features" ];
# Skip tests if they require network/special setup
doCheck = false;
meta = { ... };
}
Python Packages
buildPythonPackage rec {
pname = "python-pkg";
version = "1.0.0";
pyproject = true; # For pyproject.toml-based projects
src = fetchPypi {
inherit pname version;
hash = "sha256-...";
};
build-system = [ setuptools ]; # or hatchling, poetry-core, etc.
dependencies = [
requests
pydantic
];
optional-dependencies = {
dev = [ pytest black ];
};
pythonImportsCheck = [ "module_name" ];
meta = { ... };
}
Node.js Packages
buildNpmPackage rec {
pname = "node-app";
version = "1.0.0";
src = fetchFromGitHub { ... };
npmDepsHash = "sha256-...";
# Optional: Custom build phase
buildPhase = ''
npm run build
'';
installPhase = ''
mkdir -p $out/bin
cp -r dist $out/
makeWrapper ${nodejs}/bin/node $out/bin/${pname} \
--add-flags "$out/dist/index.js"
'';
meta = { ... };
}
Fetchers
fetchFromGitHub
src = fetchFromGitHub {
owner = "owner-name";
repo = "repo-name";
rev = "v${version}"; # or commit hash
hash = "sha256-..."; # Use lib.fakeHash initially
# Optional:
fetchSubmodules = true;
};
fetchurl
src = fetchurl {
url = "https://example.com/file-${version}.tar.gz";
hash = "sha256-...";
};
fetchPypi
src = fetchPypi {
inherit pname version;
hash = "sha256-...";
# Optional:
extension = "zip";
};
Hash Management
Getting correct hashes:
1. Use lib.fakeHash or lib.fakeSha256 initially
2. Run build, it will fail with actual hash
3. Copy actual hash into derivation
4. Rebuild to verify
# Initial attempt
hash = lib.fakeHash;
# After failure, copy the hash from error message
hash = "sha256-Abc123...";
For Rust crates:
# Prefetch cargo dependencies
nix-prefetch-url --unpack "https://crates.io/api/v1/crates/package/1.0.0/download"
Flakes
Flake Structure
Standard flake template:
{
description = "Package or system description";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
packages.default = pkgs.callPackage ./default.nix { };
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
rustc
cargo
pkg-config
openssl
];
};
# For NixOS modules
nixosModules.default = import ./module.nix;
});
}
Flake Updates
# Update all inputs
nix flake update
# Update specific input
nix flake lock --update-input nixpkgs
# Show flake metadata
nix flake metadata
# Check flake for issues
nix flake check
NixOS Configuration
Module Structure
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.myservice;
in
{
options.services.myservice = {
enable = mkEnableOption "myservice";
package = mkOption {
type = types.package;
default = pkgs.myservice;
description = "Package to use for myservice";
};
port = mkOption {
type = types.port;
default = 8080;
description = "Port to listen on";
};
settings = mkOption {
type = types.attrs;
default = { };
description = "Additional settings";
};
};
config = mkIf cfg.enable {
systemd.services.myservice = {
description = "My Service";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/myservice --port ${toString cfg.port}";
Restart = "always";
User = "myservice";
Group = "myservice";
};
};
users.users.myservice = {
isSystemUser = true;
group = "myservice";
};
users.groups.myservice = { };
};
}
Common NixOS Patterns
Service with configuration file:
config = mkIf cfg.enable {
environment.etc."myservice/config.json".text = builtins.toJSON cfg.settings;
systemd.services.myservice = {
serviceConfig = {
ExecStart = "${cfg.package}/bin/myservice --config /etc/myservice/config.json";
};
};
};
Conditional package installation:
environment.systemPackages = optional cfg.enable cfg.package;
Overlays
Creating Overlays
# overlays/default.nix
final: prev: {
mypackage = prev.mypackage.overrideAttrs (old: {
version = "2.0.0";
src = prev.fetchFromGitHub {
owner = "owner";
repo = "repo";
rev = "v2.0.0";
hash = "sha256-...";
};
});
# Add new package
newpackage = prev.callPackage ./packages/newpackage.nix { };
}
Using Overlays in Configuration
# configuration.nix
{ config, pkgs, ... }:
{
nixpkgs.overlays = [
(import ./overlays/default.nix)
];
}
Troubleshooting Build Failures
Common Issues
Missing dependencies:
# Check what's in the build environment
nix-build --keep-failed
cd /tmp/nix-build-*
# Inspect what's available
Hash mismatches:
- Upstream changed release without version bump
- Fetch different source (git tag vs release tarball)
- Use lib.fakeHash and copy correct hash from error
Cross-compilation issues:
- Check nativeBuildInputs vs buildInputs
- Some tools must be native (run during build)
- Libraries should be in buildInputs (linked into output)
Cargo/NPM dependency issues:
- Update cargoHash / npmDepsHash
- Check for git dependencies in Cargo.toml
- May need outputHashes for git dependencies
Test failures:
- Set doCheck = false if tests require network/special setup
- Use checkPhase to customize test execution
- Add to checkInputs if test dependencies missing
Debug Commands
# Show derivation details
nix show-derivation .#package
# Build with verbose output
nix build -L .#package
# Enter build environment
nix develop .#package
# Check what's in closure
nix path-info -r .#package
# Show why package is in closure
nix why-depends .#system .#package
Nixpkgs Contribution
Testing Changes
# Test build
nix-build -A package
# Test NixOS module
nixos-rebuild build --flake .#hostname
# Run package
nix run .#package
# Check for evaluation errors
nix-instantiate --eval '<nixpkgs>' -A package.meta
Pre-commit Checks
# Format Nix files
nixfmt **/*.nix
# or
alejandra **/*.nix
# Check evaluation
nix flake check
# Run nixpkgs-review (for nixpkgs PRs)
nixpkgs-review pr <PR-number>
Metadata Requirements
All packages MUST include:
meta = with lib; {
description = "Brief description (no package name)";
homepage = "https://...";
license = licenses.mit; # or appropriate license
maintainers = with maintainers; [ your-handle ];
# For executables:
mainProgram = "executable-name";
# Platform support:
platforms = platforms.unix; # or platforms.linux, platforms.all
# If package is known broken:
broken = false;
};
Common Patterns
makeWrapper for Scripts
{ lib, stdenv, makeWrapper, python3, ... }:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ makeWrapper ];
installPhase = ''
mkdir -p $out/bin
cp script.py $out/bin/script
wrapProgram $out/bin/script \
--prefix PATH : ${lib.makeBinPath [ python3 ]}
'';
}
Patches
{
patches = [
./patches/fix-build.patch
(fetchpatch {
url = "https://github.com/owner/repo/commit/abc123.patch";
hash = "sha256-...";
})
];
}
postPatch for File Modifications
{
postPatch = ''
# Fix hardcoded paths
substituteInPlace src/main.rs \
--replace '/usr/bin/env' '${coreutils}/bin/env'
# Update version in file
sed -i 's/version = "0.0.0"/version = "${version}"/' Cargo.toml
'';
}
Conditional Dependencies
buildInputs = [
common-dep
] ++ lib.optionals stdenv.isDarwin [
darwin.apple_sdk.frameworks.Security
] ++ lib.optionals stdenv.isLinux [
systemd
];
File Organization
Package File Structure
package-name/
βββ default.nix # Main derivation
βββ cargo.lock # If using cargoLock
βββ patches/ # Patches directory
βββ fix-thing.patch
Multi-Package Repository
repo/
βββ flake.nix
βββ flake.lock
βββ packages/
β βββ package1/
β β βββ default.nix
β βββ package2/
β βββ default.nix
βββ modules/
β βββ service.nix
βββ overlays/
βββ default.nix
Quick Reference
Essential commands:
- Build: nix-build -A <attr> or nix build .#<package>
- Develop: nix develop or nix-shell
- Run: nix run .#<package>
- Search: nix search nixpkgs <query>
- Format: nixfmt *.nix or alejandra .
Hash helpers:
- Use lib.fakeHash initially
- Cargo: update cargoHash when Cargo.lock changes
- NPM: update npmDepsHash when package-lock.json changes
- Source: update hash when version/source changes
Key principles:
- MUST declare all dependencies
- MUST NOT access network in build phase
- MUST use appropriate buildInputs classification
- SHOULD use latest package builder patterns
- SHOULD include comprehensive meta
- MUST test build before submitting to nixpkgs
Common mistakes:
- Wrong input classification (native vs build)
- Missing mainProgram in meta
- Hardcoded store paths instead of references
- Network access during build
- Missing propagated dependencies
- Outdated hashes after updates
Note: For project-specific Nix patterns, check .claude/CLAUDE.md in the project directory.
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.