CodeGraph ships a vendored Node runtime alongside the app. Because Node 22.5+
has a built-in real SQLite (node:sqlite, with WAL + FTS5), bundling Node means:
- No native build —
better-sqlite3is gone, so there are zero native addons to compile or rebuild. - No wasm fallback — and therefore no more
database is locked(issue #238). - No Node-version dependence — the app always runs on the bundled Node, whatever the user has (or doesn't have) installed.
Built by scripts/build-bundle.sh — one archive per
platform, identical recipe (only the Node download differs):
codegraph-<target>/
node | node.exe # official Node runtime for <target>
lib/
dist/ # compiled app (+ tree-sitter .wasm grammars, schema.sql)
node_modules/ # production deps only (pure JS / wasm — portable)
bin/
codegraph | codegraph.cmd # launcher → runs the bundled Node with the app
Targets: darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64,
win32-arm64. Unix targets produce .tar.gz (shell launcher); Windows produces
.zip (node.exe + a .cmd launcher).
scripts/build-bundle.sh linux-x64 # -> release/codegraph-linux-x64.tar.gz
scripts/build-bundle.sh win32-x64 # -> release/codegraph-win32-x64.zipBecause dropping better-sqlite3 left zero native addons, building a bundle is
pure file-packaging — any target builds on any OS (the whole matrix builds
on one Linux runner). Cross-compilation isn't a concern; only run-testing a
bundle needs the target platform (or emulation, e.g. docker run --platform linux/amd64).
curl | sh(install.sh) — no Node required; ideal for a fresh Linux VPS over SSH. Detects os/arch, pulls the archive from GitHub Releases, symlinkscodegraphonto PATH. Re-run to upgrade;--uninstallto remove.- npm (
scripts/npm-shim.js) — preservesnpm i -g @colbymchenry/codegraph. The main package is a tiny shim; the bundles ship as per-platformoptionalDependencies(@colbymchenry/codegraph-<target>withos/cpu), so npm installs only the matching one. The shim — run by the user's Node — execs the bundle, so the real work runs on the bundled Node 24. Works even on old Node. On Windows it invokes the bundlednode.exeagainst the app entry directly (not the.cmdlauncher) — modern Node throwsEINVALwhen asked to spawn a.cmd/.bat. - Windows (
install.ps1) —irm … | iex; same flow as install.sh (detect arch, pull the.zipfrom Releases, add to PATH). - Homebrew / Scoop — TODO (tap + cask pointing at the Release archives).
.github/workflows/release.yml — manually
triggered. Reads the version from package.json, builds every platform bundle on
one runner, creates the GitHub Release (notes from CHANGELOG.md), and publishes
the npm shim + per-platform packages. Requires the NPM_TOKEN repo secret.
Still TODO:
- Code signing — the main gap for "download & run": macOS Gatekeeper needs a Developer ID + notarization; Windows needs Authenticode. Homebrew softens the macOS case (handles quarantine).
- Retire the now-vestigial Node-version gate in
src/bin/codegraph.ts— the bundle always runs Node 24, and the npm shim does no tree-sitter work. - Re-wire
npm uninstallcleanup (the agent-configpreuninstall) through the shim — the generated main package doesn't carry it.