Create Nix package derivations for this flake-parts repository. Use when packaging new software, wrapping AppImages, extracting .deb files, building from source, or creating language-specific packages (Python, Go, Rust, Node.js/npm/pnpm/yarn). Triggers on requests like "package X", "add Y to packages/", "create derivation for Z", "wrap this AppImage/binary", or "package this npm/node project".
Create Nix packages for this flake-parts-based repository. Packages go in packages/ and are exposed via flake-parts/packages.nix.
packages/<name>.nix using appropriate templateflake-parts/packages.nixjj file track packages/<name>.nix (flakes require VCS tracking)nix build .#<name> (use lib.fakeHash first, fix hashes iteratively)nix flake checkWhat do you have?
├─ AppImage (.AppImage file)
│ └─ Use: appimageTools.wrapType2 (see AppImage section below)
├─ .deb package
│ └─ Use: stdenv.mkDerivation + dpkg — see references/deb.md
├─ Prebuilt binary/tarball
│ └─ Use: stdenv.mkDerivation with autoPatchelfHook — see references/source-builds.md
├─ Source code
│ ├─ Node.js/JavaScript → see references/nodejs.md
│ ├─ Python → see references/source-builds.md
│ ├─ Go → see references/source-builds.md
│ ├─ Rust → see references/source-builds.md
│ └─ C/C++/other → see references/source-builds.md
└─ Override existing nixpkgs package
└─ Use overlay in overlays/default.nix
Before writing a derivation, read existing packages for battle-tested patterns:
| Package | Type | File | Notes |
|---|---|---|---|
| Helium | AppImage (multi-arch) | packages/helium.nix | srcs attrset keyed by pkgs.system |
| Quounter | AppImage (single-arch, Tauri) | packages/quounter.nix | Direct fetchurl, no AppRun fix needed |
| DevToys | Deb extraction | packages/devtoys.nix | dpkg-deb + makeWrapper + autoPatchelfHook |
| Agent Browser | pnpm complex build | packages/agent-browser.nix | pnpm.fetchDeps + pnpm.configHook |
| opencode-morph-fast-apply | npm build | packages/opencode-morph-fast-apply.nix | buildNpmPackage |
ALWAYS inspect AppImage contents before finalizing the derivation:
lib.fakeHash → build → get correct hash → updatels /nix/store/*-<pname>-<version>-extracted/
find /nix/store/*-<pname>-<version>-extracted/ -name "*.desktop"
find /nix/store/*-<pname>-<version>-extracted/ -name "*.png" -o -name "*.svg"
cat /nix/store/*-<pname>-<version>-extracted/*.desktop
Gotchas:
Quounter.desktop not quounter.desktop)Exec=appname (lowercase) — skip substituteInPlace for AppRun replacementusr/share/icons/ — prefer the usr/share/icons/ treeFor multi-arch releases, use an srcs attrset keyed by pkgs.system. For single-arch, simplify to a direct fetchurl:
{
pkgs,
lib,
}:
let
pname = "app-name";
version = "1.0.0";
# Multi-arch: use srcs attrset (see packages/helium.nix)
# srcs = {
# x86_64-linux = { url = "..."; sha256 = lib.fakeHash; };
# aarch64-linux = { url = "..."; sha256 = lib.fakeHash; };
# };
# srcInfo = srcs.${pkgs.system} or (throw "Unsupported system: ${pkgs.system}");
# src = pkgs.fetchurl { inherit (srcInfo) url sha256; };
# Single-arch: direct fetchurl (see packages/quounter.nix)
src = pkgs.fetchurl {
url = "https://example.com/App_${version}_amd64.AppImage";
sha256 = lib.fakeHash;
name = "${pname}-${version}.AppImage";
};
appimageContents = pkgs.appimageTools.extract { inherit pname version src; };
in
pkgs.appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ ];
extraInstallCommands = ''
# Desktop file name is often Capitalized — inspect extracted contents first!
install -Dm644 ${appimageContents}/AppName.desktop \
$out/share/applications/${pname}.desktop
# Only if desktop file has Exec=AppRun (NOT needed for Tauri apps):
# substituteInPlace $out/share/applications/${pname}.desktop \
# --replace-fail "Exec=AppRun" "Exec=${pname}"
cp -r ${appimageContents}/usr/share/icons $out/share/icons
'';
meta = {
description = "Short description";
homepage = "https://example.com";
license = lib.licenses.mit;
platforms = [ "x86_64-linux" ];
mainProgram = pname;
sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
};
}
AppName.desktop (capitalized, matches Tauri app name)Exec= is already set to lowercase binary name — no AppRun fix neededusr/share/icons/hicolor/ with all standard sizes.deb also available but AppImage is simpler to packageAdd to flake-parts/packages.nix:
packages = {
# Cross-platform
my-package = import ../packages/my-package.nix { inherit pkgs; lib = pkgs.lib; };
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
linux-pkg = import ../packages/linux-pkg.nix { inherit pkgs; lib = pkgs.lib; };
}
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
darwin-pkg = import ../packages/darwin-pkg.nix { inherit pkgs; lib = pkgs.lib; };
};
lib.fakeHash initially in all hash fieldsnix build .#package-name — Nix fails with the correct hashlib.fakeHash with the provided hash, rebuildfetchFromGitHub: nix-prefetch-github owner repo --rev v1.0.0npmDepsHashRepo requirement: Track new files before building:
jj file track packages/new-package.nix
nativeBuildInputs = [ pkgs.makeWrapper ];
postInstall = ''
wrapProgram $out/bin/app \
--prefix PATH : ${lib.makeBinPath [ pkgs.git pkgs.curl ]} \
--set ENV_VAR "value"
'';
nativeBuildInputs = [ pkgs.autoPatchelfHook ];
buildInputs = [ pkgs.stdenv.cc.cc.lib ];
postPatch = ''
substituteInPlace src/config.py \
--replace-fail "/usr/bin/git" "${pkgs.git}/bin/git"
'';
| Issue | Solution |
|---|---|
| Hash mismatch | Use lib.fakeHash, build, copy correct hash |
| Missing library | Add to buildInputs, use autoPatchelfHook |
| Can't find binary | Check mainProgram, verify install path |
| Desktop file not found | Inspect extracted contents — filename often Capitalized |
| Platform error | Check platforms in meta, use optionalAttrs |
| npm ENOENT / node-gyp | Missing native deps, add python3 to nativeBuildInputs |
| Electron download fails | Set env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1" |
| pnpm cache errors | Use pnpm.fetchDeps + pnpm.configHook |
| Nix can't find .nix file | jj file track <file> — flakes require VCS tracking |
| AppImage Exec=AppRun wrong | Check .desktop Exec= line — Tauri apps already use correct name |