feat: add n8n, beads, opencode packages

- Add pkgs/n8n/default.nix (v2.4.1)
- Add pkgs/beads/default.nix (v0.47.1, doCheck=false)
- Add pkgs/opencode/default.nix (v1.1.18)
- Include relax-bun-version-check.patch for opencode
- Register all packages in pkgs/default.nix
This commit is contained in:
m3tm3re
2026-01-13 20:26:30 +01:00
parent c67d663600
commit bc75505ca3
5 changed files with 429 additions and 0 deletions

62
pkgs/beads/default.nix Normal file
View File

@@ -0,0 +1,62 @@
{
lib,
stdenv,
buildGoModule,
fetchFromGitHub,
gitMinimal,
installShellFiles,
versionCheckHook,
writableTmpDirAsHomeHook,
}:
buildGoModule (finalAttrs: {
pname = "beads";
version = "0.47.1";
src = fetchFromGitHub {
owner = "steveyegge";
repo = "beads";
tag = "v${finalAttrs.version}";
hash = "sha256-DwIR/r1TJnpVd/CT1E2OTkAjU7k9/KHbcVwg5zziFVg=";
};
vendorHash = "sha256-pY5m5ODRgqghyELRwwxOr+xlW41gtJWLXaW53GlLaFw=";
subPackages = ["cmd/bd"];
ldflags = ["-s" "-w"];
nativeBuildInputs = [installShellFiles];
nativeCheckInputs = [gitMinimal writableTmpDirAsHomeHook];
# Skip security tests on Darwin - they check for /etc/passwd which isn't available in sandbox
checkFlags =
lib.optionals stdenv.hostPlatform.isDarwin
["-skip=TestCleanupMergeArtifacts_CommandInjectionPrevention"];
preCheck = ''
export PATH="$out/bin:$PATH"
'';
postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
installShellCompletion --cmd bd \
--bash <($out/bin/bd completion bash) \
--fish <($out/bin/bd completion fish) \
--zsh <($out/bin/bd completion zsh)
'';
nativeInstallCheckInputs = [versionCheckHook writableTmpDirAsHomeHook];
versionCheckProgramArg = "version";
doInstallCheck = true;
# Tests require git worktree operations that fail in Nix sandbox
doCheck = false;
meta = {
description = "Lightweight memory system for AI coding agents with graph-based issue tracking";
homepage = "https://github.com/steveyegge/beads";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [kedry];
mainProgram = "bd";
};
})

View File

@@ -1,11 +1,14 @@
{pkgs, ...}: {
# Custom packages registry
# Each package is defined in its own directory under pkgs/
beads = pkgs.callPackage ./beads {};
code2prompt = pkgs.callPackage ./code2prompt {};
hyprpaper-random = pkgs.callPackage ./hyprpaper-random {};
launch-webapp = pkgs.callPackage ./launch-webapp {};
mem0 = pkgs.callPackage ./mem0 {};
msty-studio = pkgs.callPackage ./msty-studio {};
n8n = pkgs.callPackage ./n8n {};
opencode = pkgs.callPackage ./opencode {};
pomodoro-timer = pkgs.callPackage ./pomodoro-timer {};
rofi-project-opener = pkgs.callPackage ./rofi-project-opener {};
stt-ptt = pkgs.callPackage ./stt-ptt {};

114
pkgs/n8n/default.nix Normal file
View File

@@ -0,0 +1,114 @@
{
stdenv,
lib,
nixosTests,
fetchFromGitHub,
nodejs,
pnpm_10,
fetchPnpmDeps,
pnpmConfigHook,
python3,
node-gyp,
cctools,
xcbuild,
libkrb5,
libmongocrypt,
libpq,
makeWrapper,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "n8n";
version = "2.4.1";
src = fetchFromGitHub {
owner = "n8n-io";
repo = "n8n";
tag = "n8n@${finalAttrs.version}";
hash = "sha256-EQP9ZI8kt30SUYE1+/UUpxQXpavzKqDu8qE24zsNifg=";
};
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs) pname version src;
pnpm = pnpm_10;
fetcherVersion = 3;
hash = "sha256-M/HXRii4FotDC/xIa6DVlY13rCHMq7oZNtPi7hvDXik=";
};
nativeBuildInputs =
[
pnpmConfigHook
pnpm_10
python3 # required to build sqlite3 bindings
node-gyp # required to build sqlite3 bindings
makeWrapper
]
++ lib.optional stdenv.hostPlatform.isDarwin [cctools xcbuild];
buildInputs = [nodejs libkrb5 libmongocrypt libpq];
buildPhase = ''
runHook preBuild
pushd node_modules/sqlite3
node-gyp rebuild
popd
# TODO: use deploy after resolved https://github.com/pnpm/pnpm/issues/5315
pnpm build --filter=n8n
runHook postBuild
'';
preInstall = ''
echo "Removing non-deterministic and unnecessary files"
find -type d -name .turbo -exec rm -rf {} +
rm node_modules/.modules.yaml
rm packages/nodes-base/dist/types/nodes.json
CI=true pnpm --ignore-scripts prune --prod
find -type f \( -name "*.ts" -o -name "*.map" \) -exec rm -rf {} +
rm -rf node_modules/.pnpm/{typescript*,prettier*}
shopt -s globstar
# https://github.com/pnpm/pnpm/issues/3645
find node_modules packages/**/node_modules -xtype l -delete
echo "Removed non-deterministic and unnecessary files"
'';
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,lib/n8n}
mv {packages,node_modules} $out/lib/n8n
makeWrapper $out/lib/n8n/packages/cli/bin/n8n $out/bin/n8n \
--set N8N_RELEASE_TYPE "stable"
runHook postInstall
'';
passthru = {
tests = nixosTests.n8n;
updateScript = ./update.sh;
};
# this package has ~80000 files, these take too long and seem to be unnecessary
dontStrip = true;
dontPatchELF = true;
dontRewriteSymlinks = true;
meta = {
description = "Free and source-available fair-code licensed workflow automation tool";
longDescription = ''
Free and source-available fair-code licensed workflow automation tool.
Easily automate tasks across different services.
'';
homepage = "https://n8n.io";
changelog = "https://github.com/n8n-io/n8n/releases/tag/n8n@${finalAttrs.version}";
maintainers = with lib.maintainers; [gepbird AdrienLemaire sweenu];
license = lib.licenses.sustainableUse;
mainProgram = "n8n";
platforms = lib.platforms.unix;
};
})

222
pkgs/opencode/default.nix Normal file
View File

@@ -0,0 +1,222 @@
{
lib,
stdenvNoCC,
bun,
fetchFromGitHub,
fzf,
makeBinaryWrapper,
models-dev,
nix-update-script,
ripgrep,
testers,
installShellFiles,
writableTmpDirAsHomeHook,
}: let
pname = "opencode";
version = "1.1.18";
src = fetchFromGitHub {
owner = "anomalyco";
repo = "opencode";
tag = "v${version}";
hash = "sha256-3A4s0FpjZuGB0HGMQVBXfWq+0yHmeIvnEQTSX3amV4I=";
};
node_modules = stdenvNoCC.mkDerivation {
pname = "${pname}-node_modules";
inherit version src;
impureEnvVars =
lib.fetchers.proxyImpureEnvVars
++ ["GIT_PROXY_COMMAND" "SOCKS_SERVER"];
nativeBuildInputs = [bun writableTmpDirAsHomeHook];
dontConfigure = true;
buildPhase = ''
runHook preBuild
export BUN_INSTALL_CACHE_DIR=$(mktemp -d)
bun install \
--cpu="*" \
--filter=./packages/opencode \
--force \
--frozen-lockfile \
--ignore-scripts \
--no-progress \
--os="*" \
--production
bun run ./nix/scripts/canonicalize-node-modules.ts
bun run ./nix/scripts/normalize-bun-binaries.ts
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out
find . -type d -name node_modules -exec cp -R --parents {} $out \;
runHook postInstall
'';
# NOTE: Required else we get errors that our fixed-output derivation references store paths
dontFixup = true;
outputHash = "sha256-zSco4ORQQOqV3vMPuP+M/q/hBa+MJGnTKIlxgngMA3g=";
outputHashAlgo = "sha256";
outputHashMode = "recursive";
};
in
stdenvNoCC.mkDerivation (finalAttrs: {
inherit pname version src node_modules;
nativeBuildInputs = [
bun
installShellFiles
makeBinaryWrapper
models-dev
writableTmpDirAsHomeHook
];
patches = [
# NOTE: Relax Bun version check to be a warning instead of an error
./relax-bun-version-check.patch
];
dontConfigure = true;
env.MODELS_DEV_API_JSON = "${models-dev}/dist/_api.json";
env.OPENCODE_VERSION = finalAttrs.version;
env.OPENCODE_CHANNEL = "stable";
buildPhase = ''
runHook preBuild
# Copy all node_modules including the .bun directory with actual packages
cp -r ${finalAttrs.node_modules}/node_modules .
cp -r ${finalAttrs.node_modules}/packages .
(
cd packages/opencode
# Fix symlinks to workspace packages
chmod -R u+w ./node_modules
mkdir -p ./node_modules/@opencode-ai
rm -f ./node_modules/@opencode-ai/{script,sdk,plugin}
ln -s $(pwd)/../../packages/script ./node_modules/@opencode-ai/script
ln -s $(pwd)/../../packages/sdk/js ./node_modules/@opencode-ai/sdk
ln -s $(pwd)/../../packages/plugin ./node_modules/@opencode-ai/plugin
# Use upstream bundle.ts for Nix-compatible bundling
cp ../../nix/bundle.ts ./bundle.ts
chmod +x ./bundle.ts
bun run ./bundle.ts
)
runHook postBuild
'';
installPhase = ''
runHook preInstall
cd packages/opencode
if [ ! -d dist ]; then
echo "ERROR: dist directory missing after bundle step"
exit 1
fi
mkdir -p $out/lib/opencode
cp -r dist $out/lib/opencode/
chmod -R u+w $out/lib/opencode/dist
# Select bundled worker assets deterministically (sorted find output)
worker_file=$(find "$out/lib/opencode/dist" -type f \( -path '*/tui/worker.*' -o -name 'worker.*' \) | sort | head -n1)
parser_worker_file=$(find "$out/lib/opencode/dist" -type f -name 'parser.worker.*' | sort | head -n1)
if [ -z "$worker_file" ]; then
echo "ERROR: bundled worker not found"
exit 1
fi
main_wasm=$(printf '%s\n' "$out"/lib/opencode/dist/tree-sitter-*.wasm | sort | head -n1)
wasm_list=$(find "$out/lib/opencode/dist" -maxdepth 1 -name 'tree-sitter-*.wasm' -print)
for patch_file in "$worker_file" "$parser_worker_file"; do
[ -z "$patch_file" ] && continue
[ ! -f "$patch_file" ] && continue
if [ -n "$wasm_list" ] && grep -q 'tree-sitter' "$patch_file"; then
# Rewrite wasm references to absolute store paths to avoid runtime resolve failures.
bun --bun ../../nix/scripts/patch-wasm.ts "$patch_file" "$main_wasm" $wasm_list
fi
done
mkdir -p $out/lib/opencode/node_modules
cp -r ../../node_modules/.bun $out/lib/opencode/node_modules/
mkdir -p $out/lib/opencode/node_modules/@opentui
# Generate and install JSON schema
mkdir -p $out/share/opencode
HOME=$TMPDIR bun --bun script/schema.ts $out/share/opencode/schema.json
mkdir -p $out/bin
makeWrapper ${lib.getExe bun} $out/bin/opencode \
--add-flags "run" \
--add-flags "$out/lib/opencode/dist/src/index.js" \
--prefix PATH : ${lib.makeBinPath [fzf ripgrep]} \
--argv0 opencode
runHook postInstall
'';
postInstall = ''
# Add symlinks for platform-specific native modules
pkgs=(
$out/lib/opencode/node_modules/.bun/@opentui+core-*
$out/lib/opencode/node_modules/.bun/@opentui+solid-*
$out/lib/opencode/node_modules/.bun/@opentui+core@*
$out/lib/opencode/node_modules/.bun/@opentui+solid@*
)
for pkg in "''${pkgs[@]}"; do
if [ -d "$pkg" ]; then
pkgName=$(basename "$pkg" | sed 's/@opentui+\([^@]*\)@.*/\1/')
ln -sf ../.bun/$(basename "$pkg")/node_modules/@opentui/$pkgName \
$out/lib/opencode/node_modules/@opentui/$pkgName
fi
done
${lib.optionalString
((stdenvNoCC.buildPlatform.canExecute stdenvNoCC.hostPlatform)
&& (stdenvNoCC.hostPlatform.system != "x86_64-darwin")) ''
installShellCompletion --cmd opencode \
--bash <($out/bin/opencode completion)
''}
'';
passthru = {
jsonschema = "${placeholder "out"}/share/opencode/schema.json";
tests.version = testers.testVersion {
package = finalAttrs.finalPackage;
command = "HOME=$(mktemp -d) opencode --version";
inherit (finalAttrs) version;
};
updateScript =
nix-update-script {extraArgs = ["--subpackage" "node_modules"];};
};
meta = {
description = "AI coding agent built for the terminal";
longDescription = ''
OpenCode is a terminal-based agent that can build anything.
It combines a TypeScript/JavaScript core with a Go-based TUI
to provide an interactive AI coding experience.
'';
homepage = "https://github.com/anomalyco/opencode";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [delafthi];
sourceProvenance = with lib.sourceTypes; [fromSource];
platforms = ["aarch64-linux" "x86_64-linux" "aarch64-darwin" "x86_64-darwin"];
mainProgram = "opencode";
};
})

View File

@@ -0,0 +1,28 @@
From 0e07ea8225f5667e39c6aa59eea726266f0afab0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
Date: Thu, 13 Nov 2025 10:16:31 +0100
Subject: [PATCH] Change Bun version check from error to warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
---
packages/script/src/index.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/script/src/index.ts b/packages/script/src/index.ts
index 141d2b75..de06d0dc 100644
--- a/packages/script/src/index.ts
+++ b/packages/script/src/index.ts
@@ -10,7 +10,7 @@ if (!expectedBunVersion) {
}
if (process.versions.bun !== expectedBunVersion) {
- throw new Error(`This script requires bun@${expectedBunVersion}, but you are using bun@${process.versions.bun}`)
+ console.warn(`Warning: This script expects bun@${expectedBunVersion}, but you are using bun@${process.versions.bun}`)
}
const CHANNEL = process.env["OPENCODE_CHANNEL"] ?? (await $`git branch --show-current`.text().then((x) => x.trim()))
--
2.51.0