modules/home/programs/cli-agents/shared/skills/coding/nix-package/SKILL.md
Creating and debugging Nix packages - fetchers, hash generation, overlays, AppImage wrapping, and common build patterns for NixOS dotfiles.
npx skillsauth add not-matthias/dotfiles-nix nix-packageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Guide for creating custom Nix packages, debugging build failures, and integrating packages into a NixOS overlay.
pkgs/Before writing a full package, test dependencies or binaries in a shell:
# Enter shell with specific packages
nix-shell -p openssl pkg-config gnumake
# Test a prebuilt binary's dynamic links
nix-shell -p ldd --run "ldd ./my-binary"
Use nix-init to automatically generate a package from a URL or repo:
nix-shell -p nix-init --run "nix-init https://github.com/user/repo"
It handles hash generation, fetchers, and standard build inputs automatically.
pkgs/<name>/default.nix (or pkgs/<name>.nix){lib, stdenv, fetchurl, ...}: let
pname = "my-app";
version = "1.2.3";
in stdenv.mkDerivation {
inherit pname version;
src = fetchurl {
url = "https://example.com/my-app-${version}.tar.gz";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
installPhase = ''
mkdir -p $out/bin
cp my-app $out/bin/
chmod +x $out/bin/my-app
'';
meta = {
description = "My application";
homepage = "https://example.com";
license = lib.licenses.mit;
platforms = lib.platforms.linux;
mainProgram = "my-app";
};
}
{lib, appimageTools, fetchurl}: let
pname = "my-app";
version = "1.2.3";
src = fetchurl {
url = "https://example.com/my-app-${version}.AppImage";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
in appimageTools.wrapType2 {
inherit pname version src;
meta = {
description = "My application";
homepage = "https://example.com";
license = lib.licenses.unfree;
platforms = ["x86_64-linux"];
mainProgram = pname;
};
}
{lib, stdenv, fetchFromGitHub, cmake, ...}: stdenv.mkDerivation rec {
pname = "my-tool";
version = "1.2.3";
src = fetchFromGitHub {
owner = "org";
repo = "repo";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
nativeBuildInputs = [cmake];
meta = {
description = "My tool";
homepage = "https://github.com/org/repo";
license = lib.licenses.mit;
platforms = lib.platforms.linux;
};
}
modules/overlays/pkgs.nix)(_self: super: {
my-app = super.callPackage ../../pkgs/my-app.nix {};
# For subdirectory packages:
my-app = super.callPackage ../../pkgs/my-app {};
})
home.packages = with pkgs; [my-app];
# or system-wide:
environment.systemPackages = with pkgs; [my-app];
Before editing a package for a new version, check what changed upstream:
# For electron apps — fetch package.json from the new tag to verify:
# - electron version (may need electron_NN bump in nix)
# - dropped dependencies (e.g. sass-embedded removed → delete preBuild hook)
curl -s "https://raw.githubusercontent.com/<owner>/<repo>/refs/tags/v<version>/package.json" | jq '{electron: .devDependencies.electron}'
Changes to watch for:
electron_NN inputnativeBuildInputs and build hookssubstituteInPlace paths still exist in the new sourceStart with a fake hash — Nix will tell you the real one:
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
Build fails with: hash mismatch ... got: sha256-<actual> — copy that value.
# Prefetch before writing the package
nix-prefetch-url --type sha256 <url>
# Convert hex → SRI: nix hash to-sri --type sha256 <hex>
# For GitHub
nix-prefetch-fetchFromGitHub --owner <org> --repo <repo> --rev <tag>
sudo nixos-rebuild build --flake .#framework --show-trace
# Cached failure? Force re-eval:
sudo nixos-rebuild build --flake .#framework --option eval-cache false
Common eval errors:
attribute 'X' missing → Check overlay registration or callPackage argsinfinite recursion → Use super not self in overlaycannot coerce X to string → Wrong type passed to a string context# Build single package in isolation
# NOTE: nix build -f pkgs/<name>.nix only works for argument-free packages.
# For callPackage-style packages (with lib, stdenv, etc.) use:
nix build --impure --expr 'let pkgs = import <nixpkgs> {}; in pkgs.callPackage ./pkgs/<name>.nix {}'
# Interactive build env
nix develop .#<derivation>
Common build errors:
buildInputsnativeBuildInputsnativeBuildInputs = [patchelf autoPatchelfHook];
buildInputs = [stdenv.cc.cc.lib zlib];
# In a module
{pkgs-unstable, ...}: {
home.packages = [pkgs-unstable.some-package];
}
nix build -f pkgs/<name>.nix succeedsmodules/overlays/pkgs.nixhome.packages or environment.systemPackagessudo nixos-rebuild build --flake .#framework succeedsmeta.mainProgram set for executableslib.licenses.unfree for proprietary)documentation
Save notes, journal entries, and research to the personal-notes Obsidian vault (personal-vault-v2). Use when the user asks to 'save note', 'save to notes', 'write to personal notes', 'save to daily notes', 'note this down', or wants to persist findings/analysis to their personal vault.
documentation
Use whenever the user asks to address, fix, resolve, review, or respond to pull-request comments or review feedback.
development
Apply Not Matthias's Rust-first personal coding style. Use whenever the user explicitly asks to apply or review their code style, make Rust match their preferences, perform a style pass, or simplify/refactor according to their conventions. Inspect only task-touched code, honor local project conventions first, and make only safe opt-out style edits.
development
Guide for writing ast-grep rules to perform structural code search and analysis. Use when users need to search codebases using Abstract Syntax Tree (AST) patterns, find specific code structures, or perform complex code queries that go beyond simple text search. This skill should be used when users ask to search for code patterns, find specific language constructs, or locate code with particular structural characteristics.