modules/home/programs/cli-agents/shared/skills/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)development
Emulates not-matthias's technical blog writing style. Use when writing blog posts, technical articles, README content, or any long-form technical prose. Produces investigation-driven, first-person narratives with dry humor, practical code examples, and concrete takeaways.
development
Create and manage Git worktrees for parallel feature development. Use when user wants to work on multiple features simultaneously or needs isolated development environments.
development
Systematic technical research and brainstorming. Given a question, recursively explores attached specifications, source code, documentation, GitHub repositories, and authoritative online sources to build comprehensive, accurate answers. Surfaces edge cases, caveats, and implementation details that matter.
development
Converts a research paper (PDF path, uploaded PDF, or URL) into a reusable skill that stores distilled knowledge for future sessions. Use when a user asks to "turn this paper into a skill", "make this PDF reusable", "encode this research", or wants project-specific decisions backed by a specific paper without re-uploading it.