CodeGraph 分发策略:打包 vendored Node 运行时,构建零原生编译的自包含跨平台 Bundle CodeGraph 分发策略打包 vendored Node 运行时构建零原生编译的自包含跨平台 Bundle【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraphCodeGraph 的BUNDLING.md定义了项目“下载即运行”的分发方案随应用捆绑一份官方 Node 运行时彻底绕开原生依赖与用户环境差异。本文基于该文档并结合 scripts/build-bundle.sh、install.sh、scripts/npm-shim.js 与 .github/workflows/release.yml 的实际实现完整拆解 Bundle 的目录结构、构建流程、四个安装渠道以及发布流水线读完后你可以理解一个“无 native 编译、无 wasm 回退、无 Node 版本依赖”的 Node 应用是如何做到在单一 Linux Runner 上交叉产出全部平台产物的。一、为什么选择自包含 Bundlevendored Node 运行时的三个收益CodeGraph 的核心存储层是 SQLite知识图谱数据库 WAL FTS5 全文索引解析层是 tree-sitter 的 WASM 语法文件。早期方案依赖better-sqlite3这类原生模块而BUNDLING.md记录了架构切换后的收益——Node 22.5 内置了真正的 SQLitenode:sqlite支持 WAL 与 FTS5因此随应用捆绑 Node 运行时后无原生编译better-sqlite3被移除整个分发包中不存在任何需要编译或重建的 native addon无 wasm 回退存储层不再在原生 SQLite 与 wasm 之间降级历史上因此产生的database is locked问题issue #238不复存在无 Node 版本依赖无论用户装没装 Node、装的是什么版本CodeGraph 永远运行在捆绑的 Node 上当前构建固定为 Node v24.16.0。存储层的实现印证了这一点。src/db/sqlite-adapter.ts 的头注释明确写道“CodeGraph 捆绑了 Node 运行时因此node:sqlite真 SQLite支持 WAL FTS5始终可用——没有原生构建步骤也没有 wasm 回退”。适配器本身只是把node:sqlite的DatabaseSync包装成原 better-sqlite3 形状的接口补上.pragma()、.transaction()和open三个便捷方法使其余代码对存储后端保持无感src/db/sqlite-adapter.ts。这个决策是整个分发策略的地基正因为产物里只剩纯 JS 与 wasm打包才退化成纯粹的“文件搬运”从而获得跨平台构建的自由度。二、Bundle 的目录结构与构建配方BUNDLING.md指出每个平台由 scripts/build-bundle.sh 产出一个归档所有平台使用同一套配方唯一的差异是下载哪个官方 Node 发行版codegraph-target/ node | node.exe # target 平台的官方 Node 运行时 lib/ dist/ # 编译后的应用含 tree-sitter .wasm 语法与 schema.sql node_modules/ # 仅生产依赖纯 JS / wasm跨平台可移植 bin/ codegraph | codegraph.cmd # 启动器 → 用捆绑的 Node 运行应用目标平台共六个darwin-arm64、darwin-x64、linux-x64、linux-arm64、win32-x64、win32-arm64。Unix 目标产出.tar.gzshell 启动器Windows 产出.zipnode.exe.cmd启动器。scripts/build-bundle.sh linux-x64 # - release/codegraph-linux-x64.tar.gz scripts/build-bundle.sh win32-x64 # - release/codegraph-win32-x64.zip2.1 构建脚本的五步流程对照 scripts/build-bundle.sh 源码BUNDLING.md中“同一套配方”具体是下载目标平台的官方 Node 运行时脚本接受target与可选的[node-version]两个参数Node 版本默认固定为v24.16.0以保证构建可复现scripts/build-bundle.sh#L23-L24。win32 目标下载官方 zip无unzip时退回bsdtarUnix 目标下载 tar.gz。构建应用本体执行npm run build即tsc编译加资源拷贝——copy-assets会把 src/db/schema.sql 拷入dist/db/并把src/extraction/wasm/下全部.wasm语法文件拷入dist/extraction/wasm/见 package.json 的copy-assets脚本。暂存应用 仅生产依赖dist、package.json拷入lib/后用npm ci --omitdev --ignore-scripts安装生产依赖。由于依赖树中已无原生模块这一步在任何系统上产出相同的node_modules。可选的原生抽取内核如果release/kernel/target/codegraph-kernel.node或本地codegraph-kernel/prebuilds/target/存在预编译的 Rust 内核scripts/build-bundle.sh#L71-L89则将其拷入lib/kernel/缺失时 Bundle 自动退回 wasm 抽取路径——内核是“每语言的提速项而非必需项”设计背景见 docs/design/rust-kernel-migration-plan.md。写启动器 归档Unix 端生成一个 shell 启动器脚本Windows 端生成一行.cmd批处理然后分别用tar --no-xattrs避免 macOS xattrs 让 GNU tar 告警或zip打包。由于是纯文件打包任何目标都可以在任何操作系统上构建——整个六平台矩阵可以在单个 Linux Runner 上完成发布流水线正是这么做的。交叉编译不是问题只有“运行验证”某个 Bundle 才需要目标平台或仿真例如docker run --platform linux/amd64。2.2 启动器里藏着的三个关键细节Unix 启动器scripts/build-bundle.sh#L108-L130比“exec node app.js”多了三处刻意设计符号链接解析install.sh 会创建~/.local/bin/codegraph这样的符号链接启动器先循环readlink解析到真实 Bundle 目录再定位捆绑 Node保证从任意链接位置调用都能找到node与lib/。CODEGRAPH_HOST_PPID透传把启动者的父进程 PIDMCP 宿主传给服务端的孤儿进程看门狗issue #1185若外层启动器如 npm shim已设置则不覆盖。V8 运行标志--liftoff-only把 tree-sitter 的大型 WASM 语法固定在 V8 的 Liftoff 基线编译器上避免其进入 turboshaft 优化层——后者在 Node ≥ 22 上会因每次编译的 Zone 内存池耗尽而让整个进程崩溃Fatal process out of memory: Zone即使系统还有几十 GB 空闲内存issues #293/#298。该标志必须由 V8 在引擎初始化时读取所以只能出现在 node 命令行上解析 worker 进程会继承它。完整背景与“哪些替代手段无效”的实测记录见 src/extraction/wasm-runtime-flags.ts。另一个标志--disable-warningExperimentalWarning则用于屏蔽node:sqlite的“实验特性”警告——该警告按线程打印一次主进程加每个解析 worker 会在索引期间反复刷屏、撕碎进度 UI。对非 Bundle 启动路径直接从源码运行distCLI 会通过 relaunchWithWasmRuntimeFlagsIfNeeded 自检并带标志重新 exec 自身一次两条路径行为一致。Windows 启动器则是一行.cmd%~dp0..\node.exe --liftoff-only --disable-warningExperimentalWarning %~dp0..\lib\dist\bin\codegraph.js %*。三、安装渠道四种方式投递同一个 BundleBUNDLING.md列出四个安装渠道它们最终交付的都是上面同一种 Bundle。3.1curl | shinstall.sh面向“全新 Linux VPS 通过 SSH 接入、机器上什么都没有”的场景——不需要 Node、不需要构建工具、不需要 npm平台探测uname -s/uname -m映射到darwin|linux与arm64|x64拼出与发布归档一致的 target 三元组版本解析默认取 latest。这里有个实战细节——latest 是通过releases/latest的web 重定向解析的而不是 GitHub API未认证的 API 限速 60 次/小时/IP在共享主机与 CI 上很容易触发 403issue #325而 web 重定向无此限制重定向不可读时才退回 APIinstall.sh#L46-L62下载与安装归档解压到~/.codegraph/versions/v/每个版本一个独立目录约 50 MB含 vendored Node再建两个符号链接~/.local/bin/codegraph → versions/v/bin/codegraph和~/.codegraph/current → versions/v。重复运行同一命令即升级--uninstall删除安装目录与链接旧版本清理升级会留下旧版本目录脚本只保留刚装上的目录、删除其余install.sh#L96-L111。这在 POSIX 上是安全的——若旧 Bundle 仍有 daemon 在跑inode 会存活到进程退出PATH 体检安装后脚本遍历一次 PATH既提示“安装目录不在 PATH 上”也检测“PATH 上更靠前的另一个codegraph会遮蔽本安装”——最常见来源是陈旧的npm i -g全局包issue #1071此时codegraph --version会与实际安装不符。可调环境变量CODEGRAPH_VERSION钉住版本、CODEGRAPH_INSTALL_DIR默认~/.codegraph、CODEGRAPH_BIN_DIR默认~/.local/bin。3.2 npmscripts/npm-shim.jsesbuild 模式npm i -g colbymchenry/codegraph这条命令被完整保留实现方式是“薄安装器 每平台包”的经典拆分esbuild 模式主包是一个极小的 shim真正的 Bundle 以colbymchenry/codegraph-target的形式作为optionalDependencies发布各带os/cpu字段npm 只会安装与宿主匹配的那一个。打包逻辑见 scripts/pack-npm.sh它把每个 Bundle 归档展开成独立的平台包再生成主包——bin指向 npm-shim.jsmain指向 npm-sdk.js程序化嵌入入口re-export 平台包里的编译产物types则只发布.d.ts树运行时 JS 不重复打包。关键行为来自 shim 源码scripts/npm-shim.js用户的 Node 只是启动器shim 由用户自己的 Node 执行哪怕是老版本定位平台包后spawnSync其启动器真正干活的是捆绑的 Node 24Windows 的特殊处理现代 Node 对直接 spawn.cmd/.bat会抛EINVALCVE-2024-27980 加固所以 Windows 路径不经过.cmd启动器而是直接调用捆绑的node.exe运行应用入口并自行补上--liftoff-only等标志scripts/npm-shim.js#L65-L79自修复下载issue #303npmmirror/cnpm 等镜像与部分企业代理并不可靠地同步每平台的optionalDependencies而 npm 把“optional 依赖拉取失败”视为成功静默跳过——结果 Bundle 缺失、每条命令都失败。shim 发现安装包里解析不到 Bundle 时会退回到“从 GitHub Releases 下载与 install.sh 相同的那个归档”缓存在~/.codegraph/bundles/target-version/并做 SHA256 校验发布物附带SHA256SUMS缺失则跳过校验而不是阻断安装。相关开关CODEGRAPH_NO_DOWNLOAD1禁用联网回退但已缓存的 Bundle 仍可用、CODEGRAPH_INSTALL_DIR缓存位置、CODEGRAPH_DOWNLOAD_BASE镜像/离线环境换源。缓存同样带旧版本清理逻辑避免每版本约 50 MB 的 Bundle 无限堆积。3.3 Windowsinstall.ps1PowerShell 版irm … | iex安装流程与 install.sh 对应探测架构Arm64/x64→ 解析版本 → 从 Releases 下载.zip→ 解压到%LOCALAPPDATA%\codegraph\current单目录原地覆盖升级→ 把current\bin加入用户 PATH。它同样实现了“PATH 遮蔽”检查且同时检查机器级用户级持久化 PATH 与当前会话 PATH能发现 conda/npm 等 shell profile 注入目录里的旧codegraphinstall.ps1#L60-L89。3.4 Homebrew / ScoopTODOBUNDLING.md标注这两条渠道仍是待办tap cask 指向 Release 归档但文档同时指出 Homebrew 会软化 macOS 的代码签名问题——它处理 quarantine 标记。四、发布流水线单个 Runner 产出全平台 双通道发布发布流水线定义在 .github/workflows/release.yml手动触发workflow_dispatch。BUNDLING.md描述的主线是从package.json读取版本 → 在单个 Runner 上构建全部平台 Bundle → 用 CHANGELOG.md 生成 Release notes 创建 GitHub Release → 发布 npm shim 与每平台包。对照当前 workflow 源码实际步骤更完整内核预编译矩阵前置 jobkerneljob 在 macOS/Ubuntu/Windows 四台 Runner 上交叉编译 Rust 抽取内核aarch64-apple-darwin到aarch64-pc-windows-msvc共 6 个 target。自 1.5.0 起内核是发布的“头条功能”而非可选项因此该矩阵是硬依赖——内核构建失败会直接阻塞发布而不是静默发出 wasm-only 的 Bundle。CHANGELOG 自动晋升prepare-release.mjs把## [Unreleased]内容提升为## [version]并自动 commit/push 回 main保证发布说明不会因为维护者忘了预写版本块而空缺。单 Runner 构建六平台 Bundlefor t in darwin-arm64 darwin-x64 linux-x64 linux-arm64 win32-x64 win32-arm64; do bash scripts/build-bundle.sh $t; donerelease.yml#L197-L202随后生成SHA256SUMS并对所有 Bundle 做构建来源证明build provenance attestation——SHA256SUMS 只证明完整性attestation 才证明“由本仓库本 workflow 构建”的出处。创建 GitHub Release幂等——首次创建vversionrelease 并上传全部归档重跑则只刷新资产。发布 npmpack-npm.sh装配出release/npm/下的每平台包与主包后逐一npm publish --provenance跳过已发布的版本发布后再带重试地向 registry 复核“真的上架了”。一处与文档现状的差异值得说明BUNDLING.md写明流水线“需要NPM_TOKEN仓库密钥”但当前 workflow 已迁移到OIDC trusted publishing——每个发布的包主 shim 六个平台包都在 npm 侧配置了“本仓库 release.yml”作为可信发布者workflow 只需id-token: write权限不再持有NPM_TOKENrelease.yml#L18-L22、release.yml#L249-L254。此外流水线末尾还有一次 best-effort 的 npmmirror 同步因为该镜像经常不主动拉取每平台的 optionalDependenciesissue #303主动 nudge 一次可让镜像用户不用等待镜像抖动不会让发布失败兜底靠 shim 的自修复下载。五、文档明确留下的 TODO 与适用前提BUNDLING.md末尾列出了三项未完成事项阅读时应对应到源码现状代码签名是“下载即运行”的主要缺口macOS Gatekeeper 需要 Developer ID 公证Windows 需要 Authenticode在落地前Homebrew 渠道能在 macOS 侧缓解隔离属性问题退役src/bin/codegraph.ts中已成遗迹的 Node 版本门禁Bundle 恒定运行 Node 24npm shim 也不做任何 tree-sitter 工作该检查在 Bundle 路径上已无实际意义重接npm uninstall的清理逻辑主包的preuninstall钩子package.json 中的node dist/bin/uninstall.js负责清理 agent 配置但发布用的主包是在 pack-npm.sh 中现场生成的不带这个钩子需要经由 shim 重新接线。适用前提与限制自包含 Bundle 方案依赖 Node 22.5 的内置node:sqliteBundle 内固定 v24.16.0满足该前提若从源码直接运行npm run build node dist/...则要求本机 Node ≥ 22.5且 wasm-runtime-flags.ts 的自检重启动作会保证--liftoff-only生效原生 Rust 内核只是可选加速件其缺失不会让 Bundle 不可用。小结CodeGraph 的分发策略可以概括为一条因果链存储层换到内置node:sqlite→ 依赖树中不再有原生模块 → 打包退化为纯文件操作 → 单一 Linux Runner 交叉产出全部六个平台 → 四种安装渠道投递同一 Bundle。BUNDLING.md 给出了策略主干而 scripts/build-bundle.sh构建与启动器、install.sh / install.ps1 / scripts/npm-shim.js三个安装渠道及其自修复、版本清理、PATH 体检细节与 .github/workflows/release.yml内核矩阵、来源证明、OIDC 发布则构成了可直接对照验证的实现细节——这套方案对“CLI 工具如何摆脱环境依赖、做到下载即运行”是一个完整的参考样本。【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考