很多人第一次想给一台没有外网的机器装 Codex CLI 时,都会在搜索框里打「codex 离线安装包」,然后发现:官方并没有像 .exe、.dmg、.deb 那样的一键离线安装包可下载。这不是文档没写清楚,而是 Codex CLI 走的是 npm 分发路线——它本质上是一个发布在 npm registry 上的 Node 包。理解了这一点,离线安装这件事就从「找一个不存在的安装包」变成了「用通用的 npm 机制把包和依赖搬进内网」,思路一下就顺了。
这篇就把这条路彻底讲透:从 npm 分发原理,到在联网机器上导出包与依赖,再到目标机安装、版本锁定、完整性校验,最后给出团队规模化的私有 registry 方案,以及一张内网部署最容易踩的报错排查表。
先给结论:Codex 离线安装的 TL;DR
如果你只想快速拿到可执行的步骤,先记住下面这几条,后面每一节再展开:
- 没有官方离线安装包。Codex CLI 通过 npm 发布,所谓「离线安装」=「把 npm 包和它的依赖树搬到无外网环境再装」。
- 三种打包思路,按场景选一种:
npm pack导出 tgz(最轻)、搬运 npm 缓存目录(中等)、offline mirror 整包镜像(最重、最稳)。 - 目标机用
npm install <tgz>或--offline/--prefer-offline走本地缓存安装,全程不碰外网。 - 版本必须锁:靠
package-lock.json+npm ci,而不是npm install,否则两台机器装出来的依赖版本可能不一致。 - 先对齐 Node 版本和平台(包括 Intel Mac 的 Rosetta、Windows 的 PATH),很多「离线装失败」其实是环境前置没对齐,不是包的问题。
- 精确的包名、当前版本号、最低 Node 版本,以官方发布页为准——本文围绕通用 npm 机制写,不臆造私有命令或地址。
下面进入正题。
离线安装到底卡在哪:先搞懂 npm 的分发机制
要把一件事可靠地离线化,得先知道联网时它在背后做了什么。直接 npm install -g 安装一个 CLI,npm 大致干了三件事:
- 向 registry(默认
https://registry.npmjs.org)查询这个包的元数据(有哪些版本、每个版本的依赖、每个版本 tarball 的下载地址和完整性哈希)。 - 按 semver 规则解析出一棵完整的依赖树,把树上每个包的 tarball(
.tgz)下载下来。 - 解压、链接、生成 bin 软链,让你能在命令行里直接调用。
离线安装真正卡住的从来不是第①步的「主包」,而是第②步那棵依赖树。一个看起来很小的 CLI,node_modules 里可能藏着几十上百个间接依赖。你手动下载主包的 tgz 拿到内网,一装就报一堆 ENOTFOUND registry.npmjs.org——因为它还要去网上拉那几十个依赖。
所以离线安装的核心命题只有一句话:把「主包 + 整棵依赖树」一次性、完整地搬到目标机,并让 npm 相信它不需要联网就能装齐。剩下的全是实现这句话的不同手段。
为什么不能只拷一个 tgz 就完事
npm pack <包名> 只会打包主包本身,不会递归打包依赖。这一点是新手最大的误区。主包的 tgz 里有 package.json,里面写着 dependencies,但依赖的实际代码并不在这个 tgz 内。所以单 tgz 方案要成立,必须满足一个前提:目标机的本地 npm 缓存里已经有那些依赖,或者你额外把依赖也一起搬过去。这就引出了后面三种打包方案的分野。
如果你对 Codex 这类自主 agent 在本地到底会拉多少东西、写多少盘有概念,可以顺带看下 Codex 磁盘占用异常: 失控写盘的根因与排查清理——它从另一个角度说明了「依赖和缓存到底有多重」这件事,对规划内网磁盘配额有参考价值。
准备阶段:在联网机器上导出包与依赖
离线安装永远是「两台机器」的故事:一台能上外网(准备机),一台不能(目标机)。所有联网动作都在准备机上做完,产出一个可搬运的产物(tgz、缓存目录或镜像目录),再用 U 盘 / 内网传输 / scp 搬到目标机。
强烈建议准备机和目标机的操作系统、CPU 架构、Node 大版本尽量一致。Node 的部分依赖含原生编译产物(platform-specific),跨平台搬运会出现 .node 二进制不匹配。如果准备机是 Intel Mac、目标机是 ARM 服务器,这类坑会特别多,务必对齐架构。
方案一:npm pack 导出 tgz(最轻量,适合依赖少的场景)
最简单的形态。在准备机上:
# 1. 新建一个干净的导出目录
mkdir codex-offline && cd codex-offline
# 2. 把 Codex CLI 的 npm 包打成 tgz(包名以官方发布为准)
# npm pack 会下载该包并在当前目录生成 <包名>-<版本>.tgz
npm pack <codex-cli 的 npm 包名>
# 3. 如果只 pack 主包不够(多数情况都不够),
# 用一个临时工程把完整依赖树也装下来,再整体打包
npm init -y
npm install <codex-cli 的 npm 包名>
tar -czf codex-with-deps.tgz node_modules package.json package-lock.json
注意第 3 步才是真正可用的形态:先在一个临时工程里 npm install 把整棵依赖树落到 node_modules,再连同 package.json / package-lock.json 一起打包。这样目标机解包后,依赖就是齐的。
方案二:搬运 npm 缓存目录(中等,复用 npm 自己的缓存格式)
npm 8+ 的缓存(content-addressable cache,默认在 ~/.npm/_cacache)天然适合离线搬运。思路是:在准备机上把要装的东西「下载一遍」,npm 会自动把每个 tarball 写进缓存,然后把整个缓存目录搬到目标机。
# 准备机:指定一个独立缓存目录,避免和本机已有缓存混在一起
npm config set cache /path/to/codex-cache --location=project
# 或者临时用环境变量
export npm_config_cache=/path/to/codex-cache
# 在临时工程里完整安装一次,把所有 tarball 灌进这个缓存
npm init -y
npm install <codex-cli 的 npm 包名>
# 把缓存目录打包带走
tar -czf codex-cache.tgz -C /path/to codex-cache
到了目标机,解包缓存目录,再把 npm 的缓存指过去,配合 --offline 安装(见下一节)。这个方案的好处是复用 npm 自己的缓存格式,完整性哈希都在缓存里,不用你手动管。
方案三:offline mirror 整包镜像(最重最稳,适合反复部署)
如果你要给很多台内网机器反复装,或者要把一整批包(不只 Codex CLI)都离线化,最稳的是做一个「离线镜像目录」:把所有 tarball 平铺存成文件,目标机直接从这个目录装。
# 准备机:把 tarball 落地到一个目录,而不是只进缓存
npm config set cache /path/to/mirror-cache
npm init -y
npm install <codex-cli 的 npm 包名>
# 用 lockfile 列出所有依赖的 tarball 地址,逐个 pack 下来
# (也可以借助 npm 缓存导出,或团队现成的镜像工具)
mkdir -p /path/to/mirror/tarballs
# 思路:遍历 package-lock.json 中的 resolved 地址逐个下载为 .tgz
这种方案通常配合下一节讲的私有 registry 一起用,把镜像目录喂给 Verdaccio 之类的私服,内网机器就像连公网一样 npm install,体验最顺。规模化团队基本都走这条路。
不管选哪种方案,导出前都先在准备机上验证一次「干净环境能装成功」:删掉 node_modules 重装一遍,确认 lockfile 解析无误、没有缺包。这一步省下的是目标机现场返工的时间——内网现场往往没有第二次联网机会。
内网/目标机安装步骤
产物搬到目标机后,安装分三步走:对齐前置环境 → 装包 → 验证可用。
第一步:校验 Node 与平台前置条件
这一步被跳过的次数最多,但「离线装不上」八成栽在这里。
# 确认 Node 和 npm 存在且版本达标(最低版本以官方要求为准)
node -v
npm -v
# 确认架构匹配(准备机和目标机要一致)
node -p "process.platform + ' ' + process.arch"
几个高频前置坑:
- Node 版本不够:Codex CLI 这类现代 Node 工具通常要求较新的 LTS。Node 本身也得离线装——内网机器如果连 Node 都没有,要先把 Node 的离线安装包(官方有平台版二进制压缩包)搬进去,这是 npm 包离线化的前置前置。
- Intel Mac 的 Rosetta:在 Apple Silicon 机器上跑 Intel 架构的 Node,或反过来,可能需要 Rosetta 转译层,否则原生依赖会架构不符。这类平台细节,Codex CLI Intel Mac 安装相关的版本、Node 与 Rosetta 问题 这类对比与排查贴里讨论得比较多,装之前值得扫一眼避坑。
- Windows 的 PATH 与执行策略:全局装的 CLI 要让
npm bin -g的目录进 PATH,PowerShell 还可能卡执行策略。Windows 平台的 Codex 周边工具生态可以参考 开发者推出 Windows 版 Codex 额度监测应用,了解 Windows 下的常见环境差异。
第二步:装包
根据准备阶段选的方案,目标机的安装命令不同。
如果用方案一(tgz):
# 解包带依赖的产物
tar -xzf codex-with-deps.tgz
# 进入工程目录,离线链接(node_modules 已经齐了)
npm install --offline
# 或者直接全局安装主包 tgz(前提:依赖在缓存里)
npm install -g ./<codex-cli 包名>-<版本>.tgz --offline
如果用方案二(缓存目录):
# 解包缓存目录并指给 npm
tar -xzf codex-cache.tgz -C /opt
npm config set cache /opt/codex-cache
# 强制只用本地缓存,绝不联网
npm install -g <codex-cli 的 npm 包名> --offline
这里 --offline 和 --prefer-offline 的区别要分清:
--prefer-offline:优先用缓存,缓存里没有的才去联网拉。适合「半离线」(弱网、想省流量但还能上网)。--offline:强制只用缓存,缓存缺任何一个包就直接报错失败,绝不联网。真·内网环境用这个,能在第一时间暴露「缓存不全」的问题,而不是悄悄去连一个连不上的 registry 卡半天。
真正的无外网内网,一律用 --offline,让它「缺就立刻报错」,这是离线部署该有的失败语义。
第三步:验证可用
装完别急着收工,跑一下基本命令确认 bin 链接正常、Node 能加载主模块:
# 确认全局 bin 生效(具体命令名以官方为准)
which codex || npm ls -g --depth=0
# 看版本,确认装的是你预期的那个版本
<codex 命令> --version
版本校验与锁定
离线部署最怕的不是「装不上」,而是「装上了,但和你测试过的版本不一样」。内网机器没法随时回滚重装,版本漂移的代价很高。锁版本靠两件事:lockfile 和 npm ci。
用 npm ci + lockfile 锁版本
npm install 会按 semver 范围重新解析依赖,可能拉到比 lockfile 更新的小版本;而 npm ci 严格按 package-lock.json 安装,一个字节都不偏,且要求 lockfile 与 package.json 一致,否则直接失败。离线场景请优先用 npm ci:
# 目标机:严格按 lockfile 离线安装,版本零漂移
npm ci --offline
这意味着准备机导出时,必须把 package-lock.json 一并带上。lockfile 是离线部署的「版本契约」,丢了它,离线安装的可复现性就没了。这套「先锁规格再实现」的思路,和工程上区分 vibe coding 与 spec coding 何时切换 是一个道理——能复现的部署,前提是先把版本规格钉死。
校验包完整性
从 U 盘、内网传输搬过来的 tgz,有没有损坏、有没有被中间环节改过?npm 缓存里的 tarball 自带 integrity 哈希(sha512),npm ci 安装时会自动核对。如果你想在搬运后、安装前先手动验一道:
# 对搬过来的 tgz 算哈希,和准备机记录的对比
shasum -a 512 codex-with-deps.tgz
# package-lock.json 里每个依赖的 integrity 字段就是校验基准
养成「准备机出包时记一份哈希清单、目标机装前比一遍」的习惯。内网部署一旦出问题,「文件是不是搬坏了」是要第一个排除的变量。
常见报错排查
把内网离线安装最高频的报错和处理方式列成一张表,照着对号入座:
| 报错现象 | 根因 | 处理 |
|---|---|---|
ENOTFOUND registry.npmjs.org / 卡在 fetch |
npm 还在尝试联网拉依赖 | 加 --offline;确认缓存目录已正确指向;确认依赖树搬全了 |
npm ERR! 404 Not Found 某个依赖 |
依赖树没搬全,缺包 | 回准备机用「临时工程 + lockfile」重导,确保整棵树都在 |
EBADENGINE / Unsupported engine |
目标机 Node 版本低于包要求 | 先离线升级 Node 到达标 LTS 版本 |
node-gyp 编译失败 / 缺 .node |
含原生依赖,跨平台/跨架构搬运不兼容 | 准备机与目标机对齐 OS + arch;必要时在同架构机器上重新导出 |
EACCES 权限错误 |
全局目录无写权限 | 用合适的 npm 全局前缀目录,或 npm config set prefix 指到有权限的路径 |
EINTEGRITY 校验失败 |
tarball 搬运损坏或被改动 | 重新搬运;用哈希清单核对;确认传输过程没被压缩工具二次处理 |
装完 command not found |
全局 bin 目录没进 PATH | 把 npm bin -g 输出的目录加入 PATH |
npm ci 报 lockfile 与 package.json 不符 |
导出时 lockfile 与 manifest 不一致 | 准备机重新生成 lockfile 后再导出 |
如果排查后发现是包本身在某些环境下表现异常、而不是你的离线流程有问题,可以横向参考社区里 对主流 AI 编程工具替代方案的讨论,先确认是不是版本/环境层面的已知问题,再决定要不要降级到更稳的版本离线部署。
私有 registry / 团队规模化方案
单机离线靠 tgz 和缓存就够。但只要机器数量上去、或者要持续更新,手搬 tgz 就变成灾难。团队规模化的正解是在内网搭一个私有 npm registry,让所有内网机器把它当 registry 用,体验和连公网几乎无差。
Verdaccio:轻量私服,团队首选
Verdaccio 是开源的轻量级私有 npm proxy registry,特别适合内网。典型用法:在一台能短暂访问外网(或一次性导入镜像)的中转机上跑 Verdaccio,它会把第一次请求过的包缓存到本地磁盘;之后内网机器全部指向它:
# 内网机器把 registry 指向内网 Verdaccio
npm config set registry http://内网IP:4873/
# 之后正常 install,包都从私服走,不碰公网
npm install -g <codex-cli 的 npm 包名>
把准备阶段方案三导出的镜像目录预先导入 Verdaccio,内网机器就能在完全隔离的环境里「像连公网一样」装 Codex CLI 及其所有依赖。
Nexus / Artifactory:企业级方案
如果公司已经有 Nexus Repository 或 JFrog Artifactory,它们都支持 npm 仓库类型(hosted + proxy + group)。把 Codex CLI 需要的包推到 hosted 仓库,内网开发机指向 group 仓库,统一走企业制品库治理。这套适合已经有制品库基建、需要审计和权限管控的团队。
配置统一化:别让每台机器各调各的
私服铺开后,新问题是「每台机器的 npm 配置(registry、cache、prefix)怎么保持一致」。这和管理 AI 编程工具配置碎片化是同一类问题。社区里已经有不少把工具配置模块化、集中管理的实践,比如 开源工具统一管理 Claude、Cursor 等 AI 编程工具配置 和 关于 Claude Code 配置模块化管理的讨论,思路可以平移到内网 npm 配置的统一下发上——把 .npmrc 当作可版本化的配置资产,而不是每台机器手敲。
至于把 Codex 真正用起来后的工程化配置(项目级上下文、规约文件),CLAUDE.md 怎么写:提升 agent 准确率的最小有效配置 虽然讲的是 Claude Code,但「用一个项目级配置文件给 agent 注入上下文」的方法论对 Codex 同样成立;如果你的内网代码库是历史包袱很重的老项目,为 Claude/Codex 注入业务上下文记忆的 Project Brain 也值得一看。
相关阅读
- Codex 磁盘占用异常: 失控写盘的根因与排查清理——规划内网磁盘配额前先了解 Codex 本地写盘行为。
- Claude Code vs Codex vs WorkBuddy vs Zcode: AI 编程 Agent 怎么选——内网选型时横向了解各 agent 的安装与运行差异。
- Codex CTF 模式配置与工作流实战——装好之后,看一个具体的 Codex 配置实战。
- 实测分享:Codex55 省 Token 配置方案——离线/内网环境对 Token 成本更敏感,配置优化值得参考。
- 开发者构建多智能体协作流:用 GPT Pro 指挥 Claude Code 与 Codex——多工具协同时,统一的安装与配置基线很关键。
FAQ
Q1:Codex CLI 到底有没有官方离线安装包?
没有传统意义上的离线安装包。它通过 npm 分发,「离线安装」指的是把 npm 包和依赖树搬进无外网环境。把它当成「一个 npm 包的离线部署」来处理,而不是去找一个不存在的 .exe / .dmg。
Q2:我只把主包的 tgz 拷到内网,为什么装不上?
因为 npm pack 只打包主包,不含依赖树。装的时候 npm 还要去网上拉几十个间接依赖,内网拉不到就报错。正解是用「临时工程 + npm install 落全 node_modules + 带上 package-lock.json」一起搬,或搬运整个 npm 缓存目录。
Q3:--offline 和 --prefer-offline 选哪个?
真·内网用 --offline(强制只用缓存,缺包立即失败,便于第一时间发现缓存不全);弱网或想省流量用 --prefer-offline(缓存优先,缺的才联网)。
Q4:怎么保证两台机器装出来的版本完全一致?
带上 package-lock.json,用 npm ci --offline 而不是 npm install。npm ci 严格按 lockfile 安装,版本零漂移,这是离线可复现部署的关键。
Q5:准备机和目标机系统不一样行不行?
纯 JS 依赖一般没问题,但含原生编译产物的依赖(.node)对 OS 和 CPU 架构敏感,跨平台/跨架构搬运容易报 node-gyp 或架构不符。强烈建议准备机与目标机对齐操作系统与架构。
结语
离线安装 Codex CLI 的难点从来不是「找安装包」,而是「把整棵依赖树完整、可复现地搬进内网」。把 npm 机制吃透,单机用 tgz 加缓存、团队用 Verdaccio 私服,配上 npm ci 锁版本和哈希校验,无外网环境一样能稳定部署。具体包名与版本,始终以官方发布为准。