Add Pi Package
Package a pi coding agent extension (npm package) into the NUR repository's piPackages set.
When to Use
- User provides a
pi.dev/packages/<name>ornpmjs.org/package/<name>URL - User asks to "add", "package", or "打包" a pi package/extension
- User mentions a pi extension name to add to the NUR repo
Prerequisites
- Working directory: NUR repository root (contains
pkgs/pi-packages/) - Nix with flakes enabled
- npm (for generating lock files when needed)
Procedure
Step 1: Get Package Info
Query npm registry to determine package metadata and dependency type:
curl -s "https://registry.npmjs.org/<scope>/<name>/latest" | jq '{name, version, dependencies, peerDependencies}'
Decision point:
- No
dependencies(onlypeerDependenciesor none) → Use simple extraction (npmDepsHash = "") - Has
dependencies→ UsebuildNpmPackagewith propernpmDepsHash
Step 2: Get Tarball Hash
HASH=$(nix-prefetch-url --unpack "https://registry.npmjs.org/<scope>/<name>/-/<name>-<version>.tgz" 2>/dev/null)
nix hash to-sri --type sha256 "$HASH"
Note: The hash from nix-prefetch-url may differ from what nix expects during build. Be prepared to correct it if build fails with hash mismatch (use the got: value from the error).
Step 3: Handle Dependencies (if any)
If the package has dependencies:
Download and extract tarball:
mkdir -p /tmp/pi-packages-test/<name> cd /tmp/pi-packages-test/<name> curl -sL "https://registry.npmjs.org/<scope>/<name>/-/<name>-<version>.tgz" | tar xz --strip-components=1Generate lock file:
npm install --package-lock-onlyClean lock file — remove
@earendil-works/*peer deps (they're private and unavailable on npm):cat package-lock.json | jq ' .packages |= with_entries( select(.key == "" or (.key | test("node_modules/@earendil-works") | not)) ) ' > package-lock-cleaned.jsonCopy lock file to locks directory:
cp package-lock-cleaned.json <repo>/pkgs/pi-packages/locks/-<scope>-<name>-<version>.jsonGet npmDepsHash — build with a placeholder to discover the real hash:
cd <repo> nix build --impure --expr ' let pkgs = import <nixpkgs> {}; lib = pkgs.lib; mkNodePackage = import ./pkgs/pi-packages/mkNodePackage.nix { inherit pkgs lib; }; locksDir = ./pkgs/pi-packages/locks; mkScopedPackage = scope: name: args: mkNodePackage (args // { inherit scope name; packageLockJson = locksDir + "/${lib.replaceStrings [ "@" "/" ] [ "-" "-" ] "${scope}/${name}"}-${args.version}.json"; }); in mkScopedPackage "<scope>" "<name>" { version = "<version>"; hash = "<tarball-hash>"; npmDepsHash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="; description = "test"; homepage = "test"; } ' 2>&1 | grep "got:"
Step 4: Add Package to default.nix
Edit pkgs/pi-packages/default.nix and add the package definition. Place it in the appropriate section (or create a new section if the package category doesn't exist):
"<scope>/<name>" = mkScopedPackage "<scope>" "<name>" {
version = "<version>";
hash = "<tarball-hash>";
npmDepsHash = "<deps-hash or empty string>";
description = "<description from npm/GitHub>";
homepage = "<GitHub repo URL>";
};
For unscoped packages, use mkPackage instead of mkScopedPackage.
Step 5: Test Build
cd <repo>
nix build .#piPackages."<scope>/<name>" 2>&1
If hash mismatch error occurs, update the hash with the got: value and rebuild.
Verify the output:
ls result/ # Check files are present
ls result/node_modules/ # If has dependencies, verify they're installed
Step 6: Add to check-updates.sh
Edit scripts/check-updates.sh and add an entry to the PACKAGE_SOURCES associative array:
["<scope>/<name>"]="<github-owner>/<github-repo>"
Step 7: Commit
git add pkgs/pi-packages/default.nix \
pkgs/pi-packages/locks/-<scope>-<name>-<version>.json \
scripts/check-updates.sh
git commit -m "feat(pi-packages): add <scope>/<name> v<version>
- <short description>
- <dependency info: 'No dependencies' or 'Dependencies: X, Y'>
- Added to check-updates.sh"
Pitfalls
- Hash mismatch:
nix-prefetch-urlhash may differ from build hash. Always use thegot:value from the error message. - @earendil-works/ in lock files*: These are pi internal packages, not on npm. Remove them from lock files or
prefetch-npm-depswill fail with "non-git dependencies should have associated integrity". - fakeHash value:
lib.fakeHashequalssha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=. ThemkNodePackagefunction treats this as "no dependencies" and uses simple extraction. Do NOT use this for packages with real dependencies. - Lock file not tracked by git: Nix flakes require git-tracked files. Run
git addon lock files before building.
Verification
After commit, verify:
nix build .#piPackages."<scope>/<name>"succeedsbash scripts/check-updates.shshows the new packagegit log -1shows the commit with correct message
Source: wenjinnn/.dotfiles — distributed by TomeVault.