Codex CLI 全局安装失败常见两种脸孔:npm install -g @openai/codex报 EACCES,或 sudo 装完zsh: command not found: codex。本地修好后模型通道还可能配不通,TaoToken就管后半段:打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content= 拿 Key,把 Codex CLI 的 Base URL 指到 https://taotoken.net/api。前面那截 npm 权限和 PATH 还得在本地自己修,两者别混成一件事。
很多人的排查顺序是反的:命令都找不到就先怀疑模型服务,结果在配置里来回改,越改越乱。更省事的切法是先把本地这条链路走通——which codex有输出、codex --version有版本号,再看它请求发去了哪里。下面按报错现场、npm 全局目录、nvm 切换、config.toml 接入、验证、对照排障走一遍,每一步都能单独停下来检查。
1. npm install -g @openai/codex 报 EACCES 的现场
1.1 三条报错其实指向三件不同的事
终端里最常看到的第一条是Error: EACCES: permission denied, access '/usr/local/lib/node_modules',这是 npm 想往系统目录写文件但当前用户没权限。第二条是sudo npm install -g @openai/codex明明显示安装成功,敲codex却是zsh: command not found: codex,这是 PATH 里没有 npm 全局 bin 目录,或者 sudo 把包装到了 root 的路径下。第三条是 nvm 用户切了 Node 版本之后命令凭空消失,因为每个 Node 版本的全局包是各存各的。
分清这三类之后再动手,能省掉一半试错。EACCES 改的是 npm prefix,command not found 改的是 shell 的 PATH,nvm 丢包则是版本隔离的正常行为,不是装坏了。原文统计里权限不足约占 40%、PATH 缺失约占 25%、nvm 切换丢失约占 15%,这三项加起来就是绝大多数场景。
# 先确认现状,三条命令分别看安装位置、bin 目录、当前 Node which codex npm config get prefix node -v && npm -v1.2 为什么全局安装总要碰 /usr/local
npm 默认把全局包装进/usr/local/lib/node_modules,可执行文件软链到/usr/local/bin,这两个目录在 macOS 和多数 Linux 发行版上都归 root。用 Homebrew 装的 Node 会换成/opt/homebrew,那套目录权限宽松,所以有人换 Node 来源之后问题自动消失。本质不是 Codex 特殊,而是任何-g安装都会走同一条路。
知道这一点,方案选择就清楚了:要么把 npm 的全局目录从系统目录搬到你自己的家目录,要么让 Node 本身跑在用户目录里(nvm、fnm、volta 都属于这类),要么用 npx 干脆不装。sudo 之所以不推荐,是因为它把文件所有者变成 root,下次更新、卸载可能还要 sudo,权限状态会越来越乱。
# 能不用 sudo 就不用,先看看当前 prefix 落在哪 npm config get prefix # 输出 /usr/local 说明是系统目录,后面会改成用户目录2. 把 npm 全局目录搬到用户目录
2.1 mkdir ~/.npm-global 与 npm config set prefix
这是通用性最好的做法,改动只影响当前用户,不碰系统目录,之后所有npm install -g都不需要 sudo。四步:建目录、改 prefix、写 PATH、重装。注意顺序,先改 prefix 再装,否则旧包装在系统目录里,which codex还是会指向老地方。
# 1. 建一个属于当前用户的全局目录 mkdir -p ~/.npm-global # 2. 让 npm 把全局包装到这里 npm config set prefix "$HOME/.npm-global" # 3. 让 shell 能找到这个目录下的可执行文件 echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc source ~/.zshrc # 4. 重新安装 Codex CLI npm install -g @openai/codex # 5. 验证 which codex codex --version2.2 把 bin 目录写进 zshrc 并验证 which codex
第 3 步最容易漏。改了 prefix 却不改 PATH,装是装上了,命令照样找不到。写进~/.zshrc之后必须source一次,或者新开一个终端窗口,否则当前会话的 PATH 还是旧的。判断有没有生效,用echo $PATH看有没有~/.npm-global/bin这一段,用npm bin -g(部分 npm 版本已废弃该命令,可直接用npm config get prefix拼/bin)核对目录是否一致。
如果之前用 sudo 装过,先把旧的那份卸掉,避免两个 codex 打架:
sudo npm uninstall -g @openai/codex npm cache clean --force npm install -g @openai/codex@latest which -a codex # 列出所有同名命令,确认只剩一个which -a这个参数值得记住。它能一次性列出 PATH 中所有匹配项,比which只显示第一个有用得多——当系统目录里还留着一个旧版本时,你看到的版本号可能来自那份残留。
3. nvm 环境下重装 Codex 与切换版本
3.1 nvm 的全局包为什么切版本就消失
nvm 给每个 Node 版本单独准备了一套 lib 和 bin,全局包装在~/.nvm/versions/node/v22.x.x/lib/node_modules/下。nvm use 20之后,PATH 指向的是 v20 的 bin 目录,v22 里装的 codex 自然就找不到了。这不是 bug,是设计使然,所以 nvm 用户的正确习惯是:每个要用的 Node 版本各装一次。
nvm install 22 nvm use 22 nvm alias default 22 npm install -g @openai/codex codex --versionnvm 装的 Node,全局目录天然在用户家目录里,所以完全不需要 sudo,这点比系统 Node 省心。nvm alias default 22是让新开的终端默认用 22,否则每次重启都要手动nvm use。
3.2 每个 Node 版本重装一次的正确姿势
如果你确实需要在多个 Node 版本间来回切,可以写个小函数放进~/.zshrc,省得每次记不住装没装:
codex_ensure() { if ! command -v codex >/dev/null 2>&1; then echo "当前 Node $(node -v) 没装 codex,正在安装..." npm install -g @openai/codex@latest fi codex --version }另外两个备选路径也值得知道。不想装全局的,用npx @openai/codex@latest直接跑,代价是每次要检查下载。想更彻底的,用 fnm 或 volta 替代 nvm,volta 会把全局工具绑定到项目或用户级别,切 Node 时工具跟着走,不会丢。哪个顺手用哪个,核心诉求只有一个:让codex这个命令在任何目录下都能被找到。
# 临时用一次的写法,不装全局 npx @openai/codex@latest --version # 想长期偷懒,可以加个别名 echo 'alias codex="npx @openai/codex@latest"' >> ~/.zshrc source ~/.zshrc4. codex 能跑了但模型通道配不通
4.1 先拿 Key:去 TaoToken 控制台创建
到这一步,codex --version应该能正常输出版本号了。接下来如果发请求报鉴权失败、连不通、找不到模型,问题就不在 npm 侧,而在 Codex CLI 的模型通道配置。Codex 默认指向的地址需要换成你自己的通道,Key 也要换成你自己的。
打开 TaoToken 注册并登录,在控制台创建一把 API Key,复制出来先放好。注意区分两个地址:给人点的页面是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content= ,填进 Codex 配置文件的 Base URL 是https://taotoken.net/api,末尾不要加/v1。这两者不能互换,配置里加了/v1通常会得到 404。
模型 ID 不要凭记忆写。打开模型广场看当前可用的列表,把你要用的那个 ID 原样复制,避免因为名字差一个后缀而报模型不存在。
4.2 config.toml 里写 model_provider 与 base_url
Codex CLI 的配置文件在~/.codex/config.toml,没有就新建。要点是自定义一个 provider,把base_url指向 TaoToken 的接口地址,用env_key声明从哪个环境变量读 Key。
# ~/.codex/config.toml model = "YOUR_MODEL_ID" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY" wire_api = "chat"Key 不建议直接写在配置文件里,用环境变量更干净:
echo 'export TAOTOKEN_API_KEY=YOUR_API_KEY' >> ~/.zshrc source ~/.zshrc这里的YOUR_MODEL_ID换成你在模型广场看到的实际 ID,YOUR_API_KEY换成刚才创建的那把。注意别把 Claude Code 那套ANTHROPIC_*变量套到 Codex 上,两者读的配置项完全不同,混用只会得到莫名其妙的报错。
4.3 环境变量方式与 profile 切换
如果你需要频繁在多个通道之间切换,用 profile 比来回改主配置方便:
# ~/.codex/config.toml 追加 [profiles.taotoken] model = "YOUR_MODEL_ID" model_provider = "taotoken"之后用codex --profile taotoken启动,默认配置不动。适合同时保留几个不同用途的通道的场景,也方便你把测试配置和生产配置分开。改完配置后记得新开一个终端,或在当前会话里重新 source 一次,让环境变量生效。
5. 验证请求真的发出去了
5.1 从 codex --version 到一次最小对话
验证分两层。第一层是命令层,确认二进制没问题:
which codex codex --version codex --help第二层是请求层,随便提一个简单问题,看它能不能拿到回复。如果这一步卡住或报错,把完整报错信息留下来,对照下一节的状态码来定位。请求层通了,才说明 Key、Base URL、模型 ID 三样都对上了。
5.2 回控制台核对这次调用
请求发出后,去看一眼调用记录,确认这次请求确实记在了你的账号上。这一步能帮你区分"请求根本没发出去"和"发出去了但被拒"。如果记录里什么都没有,问题多半在本地配置没被读取;如果有记录但报错,那就要看返回的具体信息。
回到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content= 的控制台,在用量或日志页面核对刚才那次调用的模型和时间。确认无误之后,Codex CLI 的整条链路就算通了。
6. 排障对照:401、404、多了 /v1、模型 ID 不存在
6.1 状态码与配置的对应关系
| 现象 | 常见原因 | 处理方向 |
|---|---|---|
| 401 / 鉴权失败 | Key 没读到或写错 | 检查环境变量名与env_key是否一致,echo $TAOTOKEN_API_KEY是否有值 |
| 404 | Base URL 多了/v1或路径拼错 | 改回https://taotoken.net/api,末尾不加斜杠和版本段 |
| 模型不存在 | 模型 ID 写错或已下架 | 以模型广场当前列表为准,原样复制 |
| 超时 / 连不上 | 网络环境或代理设置干扰 | 检查本地代理变量,确认请求确实发向配置的地址 |
| 改了配置没生效 | 终端没重新加载 | 新开窗口或重新 source,确认读的是同一份 config.toml |
404 这一条最常见,也最好修。很多人习惯性在 Base URL 后面补/v1,但这里的接口地址本身已经包含了正确的路径结构,多写一段反而会被当成不存在的路由。
6.2 缓存与旧配置的坑
还有两个不明显的情况值得单独说。一是 npm 缓存导致装的是旧版 Codex,codex --version显示的版本比预期低,这时npm cache clean --force再重装@latest通常能解决。二是配置文件有多个来源,比如同时存在旧的 profile 和新的 provider 定义,实际生效的未必是你刚改的那段,删掉冗余段再试更省事。
# 确认到底加载了哪个版本的 codex which -a codex npm list -g @openai/codex # 确认配置文件内容 cat ~/.codex/config.toml7. 把 Codex 的模型通道固定下来
排障做完,建议把有效的那套配置固定住,别再靠临时命令。三个习惯:把TAOTOKEN_API_KEY写进 shell 的启动文件而不是每次手敲;把~/.codex/config.toml里的 provider 段保留成模板,换模型时只改model一行;Node 版本用 nvm 的default固定,避免某天新开终端突然发现 codex 又不见了。
以后再遇到 Codex 报错,先按顺序问自己四个问题:which codex有输出吗;codex --version正常吗;echo $TAOTOKEN_API_KEY有值吗;Base URL 是不是https://taotoken.net/api且没带/v1。这四个问题覆盖了绝大多数情况,能省掉反复卸载重装的时间。
配好之后想确认套餐是否够用,可以去 Coding Plan 看看;想再建一把备用 Key,在 控制台 API Keys 里操作;想先用同一把 Key 快速试一句话,直接开 模型对话 发条消息,比在终端里猜哪一步没生效快得多。