package-npm-nix
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese<objective>
Create Nix packages for npm-based CLI tools, covering both pre-built packages from npm registry and source builds with proper dependency management. This skill provides patterns for fetching, building, and packaging JavaScript/TypeScript/Bun tools in Nix environments.
</objective>
<quick_start>
<pre_built_from_npm>
For tools already built and published to npm (fastest approach):
nix
{
lib,
stdenv,
fetchzip,
nodejs,
}:
stdenv.mkDerivation rec {
pname = "tool-name";
version = "1.0.0";
src = fetchzip {
url = "https://registry.npmjs.org/${pname}/-/${pname}-${version}.tgz";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
nativeBuildInputs = [ nodejs ];
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp $src/dist/cli.js $out/bin/tool-name
chmod +x $out/bin/tool-name
# Fix shebang
substituteInPlace $out/bin/tool-name \
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
runHook postInstall
'';
meta = with lib; {
description = "Tool description";
homepage = "https://github.com/org/repo";
license = licenses.mit;
sourceProvenance = with lib.sourceTypes; [ binaryBytecode ];
maintainers = with maintainers; [ ];
mainProgram = "tool-name";
platforms = platforms.all;
};
}Get the hash:
bash
nix-prefetch-url --unpack https://registry.npmjs.org/tool-name/-/tool-name-1.0.0.tgz<objective>
为基于npm的CLI工具创建Nix包,涵盖来自npm注册表的预构建包以及具备完善依赖管理的源码构建。本技能提供了在Nix环境中获取、构建和打包JavaScript/TypeScript/Bun工具的实现模式。
</objective>
<quick_start>
<pre_built_from_npm>
针对已构建并发布到npm的工具(最快方式):
nix
{
lib,
stdenv,
fetchzip,
nodejs,
}:
stdenv.mkDerivation rec {
pname = "tool-name";
version = "1.0.0";
src = fetchzip {
url = "https://registry.npmjs.org/${pname}/-/${pname}-${version}.tgz";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
nativeBuildInputs = [ nodejs ];
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp $src/dist/cli.js $out/bin/tool-name
chmod +x $out/bin/tool-name
# Fix shebang
substituteInPlace $out/bin/tool-name \
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
runHook postInstall
'';
meta = with lib; {
description = "Tool description";
homepage = "https://github.com/org/repo";
license = licenses.mit;
sourceProvenance = with lib.sourceTypes; [ binaryBytecode ];
maintainers = with maintainers; [ ];
mainProgram = "tool-name";
platforms = platforms.all;
};
}获取哈希值:
bash
nix-prefetch-url --unpack https://registry.npmjs.org/tool-name/-/tool-name-1.0.0.tgzConvert to SRI format:
转换为SRI格式:
nix hash convert --to sri --hash-algo sha256 <hash-output>
</pre_built_from_npm>
<source_build_with_bun>
For tools that need to be built from source using Bun:
```nix
{
lib,
stdenv,
stdenvNoCC,
fetchFromGitHub,
bun,
makeBinaryWrapper,
nodejs,
autoPatchelfHook,
}:
let
fetchBunDeps =
{ src, hash, ... }@args:
stdenvNoCC.mkDerivation {
pname = args.pname or "${src.name or "source"}-bun-deps";
version = args.version or src.version or "unknown";
inherit src;
nativeBuildInputs = [ bun ];
buildPhase = ''
export HOME=$TMPDIR
export npm_config_ignore_scripts=true
bun install --no-progress --frozen-lockfile --ignore-scripts
'';
installPhase = ''
mkdir -p $out
cp -R ./node_modules $out
cp ./bun.lock $out/
'';
dontFixup = true;
outputHash = hash;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
};
version = "1.0.0";
src = fetchFromGitHub {
owner = "org";
repo = "repo";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
node_modules = fetchBunDeps {
pname = "tool-name-bun-deps";
inherit version src;
hash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
};
in
stdenv.mkDerivation rec {
pname = "tool-name";
inherit version src;
nativeBuildInputs = [
bun
nodejs
makeBinaryWrapper
autoPatchelfHook
];
buildInputs = [
stdenv.cc.cc.lib
];
buildPhase = ''
# Verify lockfile match
diff -q ./bun.lock ${node_modules}/bun.lock || exit 1
# Copy and patch node_modules
cp -R ${node_modules}/node_modules .
chmod -R u+w node_modules
patchShebangs node_modules
autoPatchelf node_modules
export HOME=$TMPDIR
export npm_config_ignore_scripts=true
bun run build
'';
installPhase = ''
mkdir -p $out/bin
cp dist/tool-name $out/bin/tool-name
chmod +x $out/bin/tool-name
'';
dontStrip = true;
meta = with lib; {
description = "Tool description";
homepage = "https://github.com/org/repo";
license = licenses.mit;
sourceProvenance = with lib.sourceTypes; [ fromSource ];
maintainers = with maintainers; [ ];
mainProgram = "tool-name";
platforms = [ "x86_64-linux" ];
};
}</source_build_with_bun>
</quick_start>
<workflow>
<step_1_identify_package_type>
**Determine build approach**:
Check the npm package:
bash
undefinednix hash convert --to sri --hash-algo sha256 <hash-output>
</pre_built_from_npm>
<source_build_with_bun>
针对需要使用Bun从源码构建的工具:
```nix
{
lib,
stdenv,
stdenvNoCC,
fetchFromGitHub,
bun,
makeBinaryWrapper,
nodejs,
autoPatchelfHook,
}:
let
fetchBunDeps =
{ src, hash, ... }@args:
stdenvNoCC.mkDerivation {
pname = args.pname or "${src.name or "source"}-bun-deps";
version = args.version or src.version or "unknown";
inherit src;
nativeBuildInputs = [ bun ];
buildPhase = ''
export HOME=$TMPDIR
export npm_config_ignore_scripts=true
bun install --no-progress --frozen-lockfile --ignore-scripts
'';
installPhase = ''
mkdir -p $out
cp -R ./node_modules $out
cp ./bun.lock $out/
'';
dontFixup = true;
outputHash = hash;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
};
version = "1.0.0";
src = fetchFromGitHub {
owner = "org";
repo = "repo";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
node_modules = fetchBunDeps {
pname = "tool-name-bun-deps";
inherit version src;
hash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
};
in
stdenv.mkDerivation rec {
pname = "tool-name";
inherit version src;
nativeBuildInputs = [
bun
nodejs
makeBinaryWrapper
autoPatchelfHook
];
buildInputs = [
stdenv.cc.cc.lib
];
buildPhase = ''
# Verify lockfile match
diff -q ./bun.lock ${node_modules}/bun.lock || exit 1
# Copy and patch node_modules
cp -R ${node_modules}/node_modules .
chmod -R u+w node_modules
patchShebangs node_modules
autoPatchelf node_modules
export HOME=$TMPDIR
export npm_config_ignore_scripts=true
bun run build
'';
installPhase = ''
mkdir -p $out/bin
cp dist/tool-name $out/bin/tool-name
chmod +x $out/bin/tool-name
'';
dontStrip = true;
meta = with lib; {
description = "Tool description";
homepage = "https://github.com/org/repo";
license = licenses.mit;
sourceProvenance = with lib.sourceTypes; [ fromSource ];
maintainers = with maintainers; [ ];
mainProgram = "tool-name";
platforms = [ "x86_64-linux" ];
};
}</source_build_with_bun>
</quick_start>
<workflow>
<step_1_identify_package_type>
**确定构建方式**:
检查npm包:
bash
undefinedDownload and inspect
下载并检查
nix-prefetch-url --unpack https://registry.npmjs.org/package/-/package-1.0.0.tgz
ls -la /nix/store/<hash>-package-1.0.0.tgz/
If `dist/` directory exists with built files:
→ Use pre-built approach (simpler, faster)
If only `src/` exists or package.json has build scripts:
→ Use source build approach
Check package.json for:
- `"bin"` field: Shows what executables are provided
- `"type": "module"`: ES modules (common in modern packages)
- `"scripts"`: Build commands (indicates source build needed)
- Runtime: Look for bun, node, or specific version requirements
</step_1_identify_package_type>
<step_2_fetch_hashes>
**Get source and dependency hashes**:
For pre-built packages:
```bashnix-prefetch-url --unpack https://registry.npmjs.org/package/-/package-1.0.0.tgz
ls -la /nix/store/<hash>-package-1.0.0.tgz/
如果存在包含构建后文件的`dist/`目录:
→ 使用预构建方式(更简单、快速)
如果仅存在`src/`目录或package.json包含构建脚本:
→ 使用源码构建方式
检查package.json中的以下字段:
- `"bin"`字段:显示工具提供的可执行文件
- `"type": "module"`:ES模块(现代包中常见)
- `"scripts"`:构建命令(表明需要源码构建)
- 运行时:查看是否依赖bun、node或特定版本要求
</step_1_identify_package_type>
<step_2_fetch_hashes>
**获取源码和依赖哈希值**:
针对预构建包:
```bashFetch npm tarball
获取npm压缩包
nix-prefetch-url --unpack https://registry.npmjs.org/pkg/-/pkg-1.0.0.tgz
nix-prefetch-url --unpack https://registry.npmjs.org/pkg/-/pkg-1.0.0.tgz
Output: 1abc... (base32 format)
输出:1abc...(base32格式)
Convert to SRI format
转换为SRI格式
nix hash convert --to sri --hash-algo sha256 1abc...
nix hash convert --to sri --hash-algo sha256 1abc...
Output: sha256-xyz...
输出:sha256-xyz...
For source builds:
```bash
针对源码构建:
```bashGet GitHub source hash
获取GitHub源码哈希
nix-prefetch-url --unpack https://github.com/org/repo/archive/v1.0.0.tar.gz
nix-prefetch-url --unpack https://github.com/org/repo/archive/v1.0.0.tar.gz
Get dependencies hash (requires iteration):
获取依赖哈希(需要迭代操作):
1. Use lib.fakeHash in fetchBunDeps
1. 在fetchBunDeps中使用lib.fakeHash
2. Try to build
2. 尝试构建
3. Nix will show expected hash in error
3. Nix会在错误信息中显示期望的哈希值
4. Update hash and rebuild
4. 更新哈希值并重新构建
</step_2_fetch_hashes>
<step_3_create_package_files>
**Create package structure**:
```bash
mkdir -p packages/tool-nameCreate with full derivation (see quick_start).
packages/tool-name/package.nixCreate :
packages/tool-name/default.nixnix
{ pkgs }: pkgs.callPackage ./package.nix { }This two-file pattern allows the package to be used standalone or integrated into a flake.
</step_3_create_package_files>
<step_4_handle_special_cases>
Common additional requirements:
WASM files or other assets:
nix
installPhase = ''
mkdir -p $out/bin
cp $src/dist/cli.js $out/bin/tool
cp $src/dist/*.wasm $out/bin/ # Copy WASM alongside
chmod +x $out/bin/tool
substituteInPlace $out/bin/tool \
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
'';Multiple executables:
nix
undefined</step_2_fetch_hashes>
<step_3_create_package_files>
**创建包结构**:
```bash
mkdir -p packages/tool-name创建文件并写入完整的派生包定义(参考快速开始部分)。
packages/tool-name/package.nix创建:
packages/tool-name/default.nixnix
{ pkgs }: pkgs.callPackage ./package.nix { }这种双文件模式允许包独立使用或集成到flake中。
</step_3_create_package_files>
<step_4_handle_special_cases>
常见额外需求:
WASM文件或其他资源:
nix
installPhase = ''
mkdir -p $out/bin
cp $src/dist/cli.js $out/bin/tool
cp $src/dist/*.wasm $out/bin/ # Copy WASM alongside
chmod +x $out/bin/tool
substituteInPlace $out/bin/tool \
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
'';多个可执行文件:
nix
undefinedpackage.json might have:
package.json中可能包含:
"bin": {
"bin": {
"tool": "dist/cli.js",
"tool": "dist/cli.js",
"tool-admin": "dist/admin.js"
"tool-admin": "dist/admin.js"
}
}
installPhase = ''
mkdir -p $out/bin
for exe in tool tool-admin; do
cp $src/dist/$exe.js $out/bin/$exe
chmod +x $out/bin/$exe
substituteInPlace $out/bin/$exe
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" done '';
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" done '';
meta.mainProgram = "tool"; # Primary command
**Platform-specific binaries**:
```nix
meta = {
platforms = [ "x86_64-linux" ]; # Bun-compiled binaries often Linux-only
# or
platforms = platforms.all; # Pure JS works everywhere
};</step_4_handle_special_cases>
<step_5_test_build>
Build and test:
bash
undefinedinstallPhase = ''
mkdir -p $out/bin
for exe in tool tool-admin; do
cp $src/dist/$exe.js $out/bin/$exe
chmod +x $out/bin/$exe
substituteInPlace $out/bin/$exe
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" done '';
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" done '';
meta.mainProgram = "tool"; # 主命令
**特定平台二进制文件**:
```nix
meta = {
platforms = [ "x86_64-linux" ]; # Bun编译的二进制文件通常仅支持Linux
# 或
platforms = platforms.all; # 纯JS包支持所有平台
};</step_4_handle_special_cases>
<step_5_test_build>
构建并测试:
bash
undefinedBuild
构建
nix build .#tool-name
nix build .#tool-name
Test the binary
测试二进制文件
./result/bin/tool-name --version
./result/bin/tool-name --help
./result/bin/tool-name --version
./result/bin/tool-name --help
Check dependencies (Linux)
检查依赖(Linux)
ldd ./result/bin/tool-name # Should show all deps resolved
ldd ./result/bin/tool-name # 应显示所有依赖已解析
Format
格式化
nix fmt
nix fmt
Run flake checks
运行flake检查
nix flake check
</step_5_test_build>
</workflow>
<metadata_requirements>
<essential_fields>
Every package must have complete metadata:
```nix
meta = with lib; {
description = "Clear, concise description";
homepage = "https://project-homepage.com";
changelog = "https://github.com/org/repo/releases"; # Optional but nice
license = licenses.mit; # or licenses.unfree for proprietary
sourceProvenance = with lib.sourceTypes; [
fromSource # Built from source
# or
binaryBytecode # Pre-built JS/TS (npm dist/)
# or
binaryNativeCode # Compiled binaries
];
maintainers = with maintainers; [ ]; # Empty OK for community packages
mainProgram = "binary-name";
platforms = platforms.all; # or specific: [ "x86_64-linux" ]
};</essential_fields>
<source_provenance_guide>
Choose based on what you're packaging:
- : Built from TypeScript/source during derivation
fromSource - : Pre-compiled JS from npm registry
binaryBytecode - : Native binaries (Rust, Go, Bun-compiled)
binaryNativeCode
This affects security auditing and reproducibility expectations.
</source_provenance_guide>
</metadata_requirements>
<common_patterns>
<shebang_replacement>
Always replace shebangs for reproducibility:
nix
undefinednix flake check
</step_5_test_build>
</workflow>
<metadata_requirements>
<essential_fields>
每个包必须包含完整的元数据:
```nix
meta = with lib; {
description = "Clear, concise description";
homepage = "https://project-homepage.com";
changelog = "https://github.com/org/repo/releases"; # 可选但推荐
license = licenses.mit; # 专有包使用licenses.unfree
sourceProvenance = with lib.sourceTypes; [
fromSource # 从源码构建
# 或
binaryBytecode # 预编译JS/TS(npm dist/目录)
# 或
binaryNativeCode # 编译后的原生二进制文件
];
maintainers = with maintainers; [ ]; # 社区包可留空
mainProgram = "binary-name";
platforms = platforms.all; # 或指定平台:[ "x86_64-linux" ]
};</essential_fields>
<source_provenance_guide>
根据打包内容选择:
- : 构建过程中从TypeScript/源码编译
fromSource - : 从npm注册表获取的预编译JS
binaryBytecode - : 原生二进制文件(Rust、Go、Bun编译)
binaryNativeCode
这会影响安全审计和可复现性要求。
</source_provenance_guide>
</metadata_requirements>
<common_patterns>
<shebang_replacement>
为了可复现性,务必替换shebang:
nix
undefinedSingle file
单个文件
substituteInPlace $out/bin/tool
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
substituteInPlace $out/bin/tool
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
Multiple files
多个文件
find $out/bin -type f -exec substituteInPlace {}
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" ;
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" ;
The `--replace-quiet` flag suppresses warnings if pattern not found.
</shebang_replacement>
<native_dependencies>
**Handle native modules** (like sqlite, sharp):
```nix
nativeBuildInputs = [
bun
nodejs
makeBinaryWrapper
autoPatchelfHook # Linux: patches ELF binaries
];
buildInputs = [
stdenv.cc.cc.lib # Provides libgcc_s.so.1, libstdc++.so.6
];
autoPatchelfIgnoreMissingDeps = [
"libc.musl-x86_64.so.1" # Ignore musl if not available
];autoPatchelf<bun_compiled_binaries>
Don't strip Bun-compiled executables:
nix
undefinedfind $out/bin -type f -exec substituteInPlace {}
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" ;
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node" ;
`--replace-quiet`参数会在未找到匹配模式时抑制警告。
</shebang_replacement>
<native_dependencies>
**处理原生模块**(如sqlite、sharp):
```nix
nativeBuildInputs = [
bun
nodejs
makeBinaryWrapper
autoPatchelfHook # Linux:修补ELF二进制文件
];
buildInputs = [
stdenv.cc.cc.lib # 提供libgcc_s.so.1、libstdc++.so.6
];
autoPatchelfIgnoreMissingDeps = [
"libc.musl-x86_64.so.1" # 忽略不可用的musl库
];autoPatchelf<bun_compiled_binaries>
不要剥离Bun编译的二进制文件:
nix
undefinedBun embeds JavaScript in the binary
Bun会将JavaScript嵌入到二进制文件中
dontStrip = true;
Stripping would remove the embedded JS, breaking the program.
</bun_compiled_binaries>
<checking_tarball_contents>
**Inspect npm package structure**:
```bashdontStrip = true;
剥离操作会移除嵌入的JS代码,导致程序无法运行。
</bun_compiled_binaries>
<checking_tarball_contents>
**检查npm包结构**:
```bashAfter nix-prefetch-url
在nix-prefetch-url之后
ls -la /nix/store/*-pkg-1.0.0.tgz/
ls -la /nix/store/*-pkg-1.0.0.tgz/
Common layouts:
常见布局:
dist/cli.js → Pre-built, use directly
dist/cli.js → 预构建包,可直接使用
dist/index.js → Main entry, check package.json "bin"
dist/index.js → 主入口,需检查package.json的"bin"字段
src/index.ts → Source only, need to build
src/index.ts → 仅源码,需要构建
lib/ → Built CommonJS
lib/ → 已构建的CommonJS模块
esm/ → Built ES modules
esm/ → 已构建的ES模块
Check package.json to find the correct entry point.
</checking_tarball_contents>
</common_patterns>
<anti_patterns>
<avoid_these>
**Don't do this**:
❌ Hardcode node paths:
```nix
查看package.json以找到正确的入口点。
</checking_tarball_contents>
</common_patterns>
<anti_patterns>
<avoid_these>
**请勿执行以下操作**:
❌ 硬编码node路径:
```nixBad
错误
"#!/usr/bin/node" # Won't work on NixOS
✅ Use substituteInPlace:
```nix"#!/usr/bin/node" # 在NixOS上无法工作
✅ 使用substituteInPlace:
```nixGood
正确
substituteInPlace $out/bin/tool
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
❌ Skip hash verification:
```nixsubstituteInPlace $out/bin/tool
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
--replace-quiet "#!/usr/bin/env node" "#!${nodejs}/bin/node"
❌ 跳过哈希验证:
```nixBad - insecure
错误 - 不安全
hash = lib.fakeHash;
✅ Get real hash:
```nixhash = lib.fakeHash;
✅ 使用真实哈希值:
```nixGood - reproducible and secure
正确 - 可复现且安全
hash = "sha256-actual-hash-here";
❌ Forget to make executable:
```nixhash = "sha256-actual-hash-here";
❌ 忘记设置可执行权限:
```nixBad - won't run
错误 - 无法运行
cp $src/dist/cli.js $out/bin/tool
✅ Set executable bit:
```nixcp $src/dist/cli.js $out/bin/tool
✅ 设置可执行位:
```nixGood
正确
cp $src/dist/cli.js $out/bin/tool
chmod +x $out/bin/tool
❌ Strip Bun binaries:
```nixcp $src/dist/cli.js $out/bin/tool
chmod +x $out/bin/tool
❌ 剥离Bun二进制文件:
```nixBad - breaks Bun-compiled executables
错误 - 破坏Bun编译的可执行文件
(default behavior strips binaries)
(默认行为会剥离二进制文件)
✅ Disable stripping:
```nix
✅ 禁用剥离:
```nixGood
正确
dontStrip = true;
</avoid_these>
</anti_patterns>
<troubleshooting>
<hash_mismatch>
**Error: "hash mismatch in fixed-output derivation"**
The hash you provided doesn't match what Nix fetched.
Solution:
1. Nix error shows "got: sha256-XYZ..."
2. Copy that hash into your derivation
3. Rebuild
For `fetchBunDeps`, this is expected the first time—use the error output to get the correct hash.
</hash_mismatch>
<missing_executable>
**Error: Binary not found after build**
Check:
```bashdontStrip = true;
</avoid_these>
</anti_patterns>
<troubleshooting>
<hash_mismatch>
**错误:"hash mismatch in fixed-output derivation"**
你提供的哈希值与Nix获取的内容不匹配。
解决方法:
1. Nix错误信息会显示"got: sha256-XYZ..."
2. 将该哈希值复制到你的派生包定义中
3. 重新构建
对于`fetchBunDeps`,首次构建时出现此错误是正常的——使用错误输出中的正确哈希值即可。
</hash_mismatch>
<missing_executable>
**错误:构建后未找到二进制文件**
检查以下内容:
```bashList what was actually built
列出实际构建的内容
ls -R result/
ls -R result/
Check package.json "bin" field
检查package.json的"bin"字段
cat /nix/store/*-source/package.json | jq .bin
cat /nix/store/*-source/package.json | jq .bin
Check build output location
检查构建输出目录
cat /nix/store/*-source/package.json | jq .scripts.build
The build might output to a different directory than expected.
</missing_executable>
<elf_interpreter_error>
**Error: "No such file or directory" when running binary (Linux)**
The binary needs ELF patching for native dependencies.
Solution:
```nix
nativeBuildInputs = [
autoPatchelfHook
];
buildInputs = [
stdenv.cc.cc.lib
];For node_modules with native addons:
nix
buildPhase = ''
cp -R ${node_modules}/node_modules .
chmod -R u+w node_modules
autoPatchelf node_modules # Patch .node files
'';</elf_interpreter_error>
<bun_lock_mismatch>
Error: "bun.lock mismatch"
The lockfile in your source doesn't match the cached dependencies.
This happens when:
- Source version updated but dependency hash not updated
- Source repo has uncommitted lockfile changes
Solution:
- Update source hash to match new version
- Set dependency hash to
lib.fakeHash - Build to get correct dependency hash
- Update dependency hash
- Rebuild </bun_lock_mismatch> </troubleshooting>
- succeeds
nix build .#package-name - works
./result/bin/tool --version - works
./result/bin/tool --help - passes
nix flake check - is clear and concise
meta.description - points to project site
meta.homepage - is correct
meta.license - matches what you packaged
meta.sourceProvenance - is set
meta.mainProgram - is appropriate for the tool
meta.platforms - All hashes are real (no )
lib.fakeHash - Shebangs use Nix store paths, not /usr/bin
- File is formatted with </build_checklist>
nix fmt
<testing_on_other_platforms>
If you only have Linux but package claims :
platforms.allConsider asking maintainers with macOS/ARM to test, or:
- Mark platforms conservatively based on what you can test
- Note in package that other platforms are untested
- Let CI or other contributors expand platform support </testing_on_other_platforms> </validation>
<success_criteria>
A well-packaged npm tool has:
- Clean build with no warnings or errors
- Working executable in
result/bin/ - Complete and accurate metadata
- Proper source provenance classification
- All dependencies resolved (no missing libraries)
- Reproducible builds (real hashes, no network access during build)
- Follows Nix packaging conventions (shebang patching, proper phases) </success_criteria>
cat /nix/store/*-source/package.json | jq .scripts.build
构建产物可能输出到了预期之外的目录。
</missing_executable>
<elf_interpreter_error>
**错误:运行二进制文件时提示"No such file or directory"(Linux)**
该二进制文件需要对原生依赖进行ELF修补。
解决方法:
```nix
nativeBuildInputs = [
autoPatchelfHook
];
buildInputs = [
stdenv.cc.cc.lib
];对于包含原生扩展的node_modules:
nix
buildPhase = ''
cp -R ${node_modules}/node_modules .
chmod -R u+w node_modules
autoPatchelf node_modules # 修补.node文件
'';</elf_interpreter_error>
<bun_lock_mismatch>
错误:"bun.lock mismatch"
源码中的锁文件与缓存的依赖不匹配。
出现此问题的场景:
- 源码版本更新但依赖哈希值未更新
- 源码仓库存在未提交的锁文件变更
解决方法:
- 更新源码哈希值以匹配新版本
- 将依赖哈希值设置为
lib.fakeHash - 构建以获取正确的依赖哈希值
- 更新依赖哈希值
- 重新构建 </bun_lock_mismatch> </troubleshooting>
- 执行成功
nix build .#package-name - 可正常运行
./result/bin/tool --version - 可正常运行
./result/bin/tool --help - 检查通过
nix flake check - 清晰简洁
meta.description - 指向项目官网
meta.homepage - 设置正确
meta.license - 与打包内容匹配
meta.sourceProvenance - 已设置
meta.mainProgram - 与工具支持的平台相符
meta.platforms - 所有哈希值均为真实值(无)
lib.fakeHash - Shebang使用Nix存储路径,而非/usr/bin
- 文件已使用格式化 </build_checklist>
nix fmt
<testing_on_other_platforms>
如果你仅使用Linux但包声明支持:
platforms.all可以联系使用macOS/ARM的维护者进行测试,或:
- 根据你能测试的内容保守标记平台
- 在包中注明其他平台未测试
- 让CI或其他贡献者扩展平台支持 </testing_on_other_platforms> </validation>
<success_criteria>
一个良好打包的npm工具应具备以下特性:
- 构建过程无警告或错误
- 目录下存在可正常工作的可执行文件
result/bin/ - 元数据完整且准确
- 正确分类源码来源
- 所有依赖已解析(无缺失库)
- 构建可复现(使用真实哈希值,构建过程无网络访问)
- 遵循Nix打包规范(Shebang修补、正确的构建阶段) </success_criteria>