From 08b663fad862344d70a7dc0ed81348c99a78dabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Mulet?= Date: Fri, 22 May 2026 16:41:40 +0200 Subject: [PATCH 1/3] feat: add Nix flake for native Nix/NixOS installation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves #324 — the curl|sh install scripts don't work under Nix (FHS paths like ~/.local/bin aren't on $PATH). The flake provides: - packages.default: codegraph built with buildNpmPackage (Node.js 24) - devShells.default: development shell with Node.js 24 The wrapper injects --liftoff-only to prevent the V8 turboshaft WASM Zone OOM (issues #293/#298), matching the existing bundle launcher. Supports linux and darwin on both x86_64 and aarch64. --- .gitignore | 3 ++ flake.lock | 61 +++++++++++++++++++++++++++++++++++++++ flake.nix | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.gitignore b/.gitignore index f7aa9d68..3039d866 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ test-languages/ nul release/ + +# Nix +result diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..7a7f0470 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1779414690, + "narHash": "sha256-gOTcX/9MZVMUE0Xvb4IEcv+0TQJkZFNEnL757ljU360=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6dedf69f94d03cbe7bdde106f2d4c23ae2a853bf", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..af3ae7bf --- /dev/null +++ b/flake.nix @@ -0,0 +1,85 @@ +{ + description = "CodeGraph – semantic code intelligence for AI agents"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + nodejs = pkgs.nodejs_24; + + codegraph = pkgs.buildNpmPackage { + pname = "codegraph"; + version = + (builtins.fromJSON (builtins.readFile ./package.json)).version; + + src = ./.; + + npmDeps = pkgs.fetchNpmDeps { + src = ./.; + hash = "sha256-GJfqzykgrgD/KCtf8LupRw31S2cCmwGCF/0PMpzaCrk="; + }; + + inherit nodejs; + + npmBuildScript = "build"; + + # The build copies .wasm + schema.sql into dist/ via the + # `copy-assets` npm script (called from `build`). Nothing + # extra to do here. + + installPhase = '' + runHook preInstall + + # Application code + mkdir -p $out/lib/codegraph + cp -r dist $out/lib/codegraph/dist + cp package.json $out/lib/codegraph/ + + # Production node_modules (already populated by buildNpmPackage) + cp -r node_modules $out/lib/codegraph/node_modules + + # Launcher wrapper: injects --liftoff-only so tree-sitter's + # large WASM grammars stay on V8's Liftoff baseline compiler + # and never hit the turboshaft Zone OOM (issues #293/#298). + mkdir -p $out/bin + cat > $out/bin/codegraph <<'EOF' +#!/bin/sh +exec @node@ --liftoff-only @out@/lib/codegraph/dist/bin/codegraph.js "$@" +EOF + substituteInPlace $out/bin/codegraph \ + --replace-fail '@node@' '${nodejs}/bin/node' \ + --replace-fail '@out@' "$out" + chmod +x $out/bin/codegraph + + runHook postInstall + ''; + + # No native addons to build — pure JS + WASM. + dontNpmBuild = false; + + meta = with pkgs.lib; { + description = + "Semantic code intelligence for AI agents — local-first knowledge graph over tree-sitter"; + homepage = "https://github.com/colbymchenry/codegraph"; + license = licenses.mit; + mainProgram = "codegraph"; + platforms = platforms.unix; + }; + }; + in { + packages = { + default = codegraph; + inherit codegraph; + }; + + devShells.default = pkgs.mkShell { + buildInputs = [ nodejs ]; + }; + }); +} From 6deb1d08088d4645ab70931e976070e6766b3ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Mulet?= Date: Sun, 24 May 2026 18:50:54 +0200 Subject: [PATCH 2/3] fix: prune devDependencies from Nix output, remove redundant dontNpmBuild - Remove redundant `dontNpmBuild = false` (it's the default) - Add `npm prune --omit=dev` in installPhase to strip devDependencies (typescript, vitest, etc.) from the final Nix store output - Clean up empty scoped-package directories left by prune --- flake.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index af3ae7bf..004e3f77 100644 --- a/flake.nix +++ b/flake.nix @@ -41,7 +41,10 @@ cp -r dist $out/lib/codegraph/dist cp package.json $out/lib/codegraph/ - # Production node_modules (already populated by buildNpmPackage) + # Production node_modules — prune devDependencies that the + # build step pulled in so the closure stays lean. + npm prune --omit=dev + find node_modules -mindepth 1 -maxdepth 1 -type d -empty -delete cp -r node_modules $out/lib/codegraph/node_modules # Launcher wrapper: injects --liftoff-only so tree-sitter's @@ -60,9 +63,6 @@ EOF runHook postInstall ''; - # No native addons to build — pure JS + WASM. - dontNpmBuild = false; - meta = with pkgs.lib; { description = "Semantic code intelligence for AI agents — local-first knowledge graph over tree-sitter"; From b46fc464c680232806f9ef145bca5a5dcc719bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Mulet?= Date: Sun, 24 May 2026 18:59:59 +0200 Subject: [PATCH 3/3] refactor: drop flake-utils, improve flake documentation - Replace flake-utils with native genAttrs pattern, reducing locked inputs from 3 to 1 (just nixpkgs). flake-utils is discouraged for new projects; the native pattern adds minimal boilerplate. - Add inline instructions for updating npmDepsHash after package-lock.json changes. - Add rationale comment for the Node.js 24 pin (node:sqlite >=22.5, V8 turboshaft OOM blocks 25.x). - Add prefetch-npm-deps to devShell so contributors can easily recompute the hash. --- flake.lock | 40 ++------------- flake.nix | 140 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 82 insertions(+), 98 deletions(-) diff --git a/flake.lock b/flake.lock index 7a7f0470..8ba83bdf 100644 --- a/flake.lock +++ b/flake.lock @@ -1,30 +1,12 @@ { "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1779414690, - "narHash": "sha256-gOTcX/9MZVMUE0Xvb4IEcv+0TQJkZFNEnL757ljU360=", + "lastModified": 1779536132, + "narHash": "sha256-q+fF42iv/geEbHfgSzy3tS0FF/EyD6XTZ98E6yxiBO8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6dedf69f94d03cbe7bdde106f2d4c23ae2a853bf", + "rev": "3d8f0f3f72a6cd4d93d0ad13203f2ea1cb7e1456", "type": "github" }, "original": { @@ -36,24 +18,8 @@ }, "root": { "inputs": { - "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 004e3f77..8c26c31c 100644 --- a/flake.nix +++ b/flake.nix @@ -3,83 +3,101 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { self, nixpkgs, flake-utils }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = nixpkgs.legacyPackages.${system}; + outputs = { self, nixpkgs }: + let + supportedSystems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + nixpkgsFor = forAllSystems (system: nixpkgs.legacyPackages.${system}); + in + { + packages = forAllSystems (system: + let + pkgs = nixpkgsFor.${system}; + + # Node 24 — matches build-bundle.sh pin (v24.16.0). + # Requires node:sqlite (>=22.5), blocks 25.x (V8 turboshaft OOM). + nodejs = pkgs.nodejs_24; + + codegraph = pkgs.buildNpmPackage { + pname = "codegraph"; + version = + (builtins.fromJSON (builtins.readFile ./package.json)).version; - nodejs = pkgs.nodejs_24; - - codegraph = pkgs.buildNpmPackage { - pname = "codegraph"; - version = - (builtins.fromJSON (builtins.readFile ./package.json)).version; - - src = ./.; - - npmDeps = pkgs.fetchNpmDeps { src = ./.; - hash = "sha256-GJfqzykgrgD/KCtf8LupRw31S2cCmwGCF/0PMpzaCrk="; - }; - inherit nodejs; + npmDeps = pkgs.fetchNpmDeps { + src = ./.; + # Update after package-lock.json changes: + # nix run nixpkgs#prefetch-npm-deps -- package-lock.json + hash = "sha256-GJfqzykgrgD/KCtf8LupRw31S2cCmwGCF/0PMpzaCrk="; + }; + + inherit nodejs; - npmBuildScript = "build"; + npmBuildScript = "build"; - # The build copies .wasm + schema.sql into dist/ via the - # `copy-assets` npm script (called from `build`). Nothing - # extra to do here. + # The build copies .wasm + schema.sql into dist/ via the + # `copy-assets` npm script (called from `build`). Nothing + # extra to do here. - installPhase = '' - runHook preInstall + installPhase = '' + runHook preInstall - # Application code - mkdir -p $out/lib/codegraph - cp -r dist $out/lib/codegraph/dist - cp package.json $out/lib/codegraph/ + # Application code + mkdir -p $out/lib/codegraph + cp -r dist $out/lib/codegraph/dist + cp package.json $out/lib/codegraph/ - # Production node_modules — prune devDependencies that the - # build step pulled in so the closure stays lean. - npm prune --omit=dev - find node_modules -mindepth 1 -maxdepth 1 -type d -empty -delete - cp -r node_modules $out/lib/codegraph/node_modules + # Production node_modules — prune devDependencies that the + # build step pulled in so the closure stays lean. + npm prune --omit=dev + find node_modules -mindepth 1 -maxdepth 1 -type d -empty -delete + cp -r node_modules $out/lib/codegraph/node_modules - # Launcher wrapper: injects --liftoff-only so tree-sitter's - # large WASM grammars stay on V8's Liftoff baseline compiler - # and never hit the turboshaft Zone OOM (issues #293/#298). - mkdir -p $out/bin - cat > $out/bin/codegraph <<'EOF' + # Launcher wrapper: injects --liftoff-only so tree-sitter's + # large WASM grammars stay on V8's Liftoff baseline compiler + # and never hit the turboshaft Zone OOM (issues #293/#298). + mkdir -p $out/bin + cat > $out/bin/codegraph <<'EOF' #!/bin/sh exec @node@ --liftoff-only @out@/lib/codegraph/dist/bin/codegraph.js "$@" EOF - substituteInPlace $out/bin/codegraph \ - --replace-fail '@node@' '${nodejs}/bin/node' \ - --replace-fail '@out@' "$out" - chmod +x $out/bin/codegraph - - runHook postInstall - ''; - - meta = with pkgs.lib; { - description = - "Semantic code intelligence for AI agents — local-first knowledge graph over tree-sitter"; - homepage = "https://github.com/colbymchenry/codegraph"; - license = licenses.mit; - mainProgram = "codegraph"; - platforms = platforms.unix; + substituteInPlace $out/bin/codegraph \ + --replace-fail '@node@' '${nodejs}/bin/node' \ + --replace-fail '@out@' "$out" + chmod +x $out/bin/codegraph + + runHook postInstall + ''; + + meta = with pkgs.lib; { + description = + "Semantic code intelligence for AI agents — local-first knowledge graph over tree-sitter"; + homepage = "https://github.com/colbymchenry/codegraph"; + license = licenses.mit; + mainProgram = "codegraph"; + platforms = platforms.unix; + }; }; - }; - in { - packages = { + in + { default = codegraph; inherit codegraph; - }; + }); - devShells.default = pkgs.mkShell { - buildInputs = [ nodejs ]; - }; - }); + devShells = forAllSystems (system: + let pkgs = nixpkgsFor.${system}; + in { + default = pkgs.mkShell { + buildInputs = [ pkgs.nodejs_24 pkgs.prefetch-npm-deps ]; + }; + }); + }; }