1. 一句话总结
- Node shim 不是 Agent 核心。
- Codex 核心是 Rust binary。
- opencode 核心是 Bun compiled binary。
- Node 只是 npm 入口层的转发壳。
- 它解决的是“怎么装、怎么启动”,不是“Agent 怎么跑”。
- npm 负责包、版本、命令名和安装路径。
- native binary 负责 TUI、Agent Loop、工具调用和权限逻辑。
- 关键链路只有一条。
npm bin -> Node shim -> 找 binary -> spawn -> 透传终端生命周期。
- 这层不要和 Agent Loop 混在一起看。
- shim 只管启动。
- Agent 能力在真正的 CLI 主程序里。
2. 一图甚千言

3. 一眼看懂:Node shim 是什么
text
你敲: codex / opencode
│
▼
package.json#bin
│
▼
Node shim
├─ ① 判断当前机器: mac / linux / windows, x64 / arm64
├─ ② 找对应的 native binary
├─ ③ spawn(binary, args)
├─ ④ stdin / stdout / stderr 直接继承
├─ ⑤ Ctrl-C 等 signal 转给子进程
└─ ⑥ 子进程怎么退出,父进程就怎么退出
│
▼
真正的 CLI 主程序- 类比前端 / Node 项目:
package.json#bin像入口声明。- Node shim 像一个很薄的
bootstrap。 - native binary 才是
main()。
记住这句就够了:Node shim 是 npm 世界和 native binary 世界之间的胶水。
4. Codex 和 opencode 怎么对应
| 维度 | Codex | opencode |
|---|---|---|
| npm 命令 | codex | opencode |
| bin 入口 | codex/codex-cli/bin/codex.js | opencode/packages/opencode/bin/opencode |
| package.json | codex/codex-cli/package.json | opencode/packages/opencode/package.json |
| shim 语言 | Node.js ESM | Node.js CommonJS |
| 真正执行体 | Rust binary | Bun compiled binary |
| 平台判断 | platform + arch -> target triple | platform + arch + AVX2 + libc |
| 启动方式 | child_process.spawn() | child_process.spawn() |
| 额外重点 | 注入安装上下文 | 选择更细的平台包 |
- Codex 的重点:
- 找
vendor/<target>/bin/codex。 - 设置
CODEX_MANAGED_BY_NPM/CODEX_MANAGED_BY_BUN。 - 设置
CODEX_MANAGED_PACKAGE_ROOT。 - Rust 侧在
codex/codex-rs/install-context/src/lib.rs读取这些信息。
- 找
- opencode 的重点:
- 区分 macOS / Linux / Windows。
- 区分 x64 / arm64 / arm。
- x64 还看 AVX2。
- Linux 还看 musl / glibc。
postinstall.mjs会提前准备最匹配的 binary。
5. 为什么不直接让 npm bin 指向 native binary
- 理论上可以。
- npm 的
bin不要求一定是 JS。
- npm 的
- 现实问题是跨平台。
- macOS Intel 和 Apple Silicon 不同。
- Linux x64 / arm64 不同。
- Windows 还要
.exe。 - Linux 还可能区分 glibc / musl。
- 所以更省心的做法是:
- 用户只装一个包。
- 用户只记一个命令。
- shim 自动选择当前机器能跑的 binary。
text
不用 shim:
用户或安装脚本要直接面对一堆平台包
用 shim:
npm 负责装包
Node shim 负责选 binary
native binary 负责跑产品6. 真正值得学的边界
- 不要把 Node shim 看成“CLI 架构主体”。
- 它只是入口层。
- 它应该很薄。
- 不要把 npm 渠道和产品运行时混在一起。
- npm 是分发渠道。
- Node shim 是渠道适配。
- native binary 是产品内核。
- 不要把 Agent Loop 写进 shim。
- shim 做平台选择和进程转发。
- Agent Loop 放在真正的主程序里。
7. 可以复用的 shim 骨架
text
npm package
└── bin/agent.js
├── 判断平台
├── 找 native binary
├── 注入 env
├── spawn binary
├── 转发 signal
└── 镜像 exit code- 最终结论:
Node shim = 胶水。native binary = main program。Agent Loop不应该长在 loader 里。