如果你最近在刷技术社区或者跟开发朋友聊天,大概率会频繁看到Codex这个名字——它不是什么新出的IDE插件,而是OpenAI在2026年力推的终端AI编程助手。简单说,装上之后你在终端里敲一句自然语言,它就能帮你分析代码、改文件、跑测试、看日志,甚至自己起一个调试命令试错,整个过程不离开命令行。这种体验确实让人上瘾,但拦在很多人面前的第一道坎却很基础:API Key登录。很多人的Codex装到一半就卡住了,运行命令直接抛unexpected status 401 unauthorized: incorrect api key provided,然后就在各种群里喊救命。
这篇文章我打算按照2026年9月这个时间点的稳定版本,把Codex的安装、API Key的获取与配置、以及最常见的401报错解决思路一次讲透。内容定位是“能照着抄作业”的实操教程,也包含我自己的排查经验和踩坑记录,适合刚接触Codex的新人,同样适合在自动化环境里想用API Key方式跑Codex的老手。先说声丑话:配置过程中90%的401都出在钥匙没配对这件事上,剩下10%是各种隐藏的细节,下面我会一个一个拆开说。
1. 安装前的思路拆解:为什么Codex绕不开认证问题
1.1 先搞清楚Codex的运作方式
Codex看起来是个终端工具,但它跟传统意义上“装完就能跑”的命令行工具不太一样。它的核心能力全部来自云端模型接口,你在终端里输入的每一条指令、它为你生成的每一行代码,最终都是通过HTTPS请求发送到OpenAI的API服务端,然后等模型结果返回。这个过程本质上跟你用curl调接口一模一样,只是Codex把这些都包装成了交互式体验。
这意味着什么?只要Codex在你机器上运行,它就必须在请求里带上一个“能证明你身份”的凭证。Codex支持的凭证类型主要有两种:一种是ChatGPT账号的OAuth授权,登录成功后会在本地生成一个auth文件;另一种就是API Key,以sk-开头的密钥字符串,也是我们这篇文章的主角。HTTP协议里对凭证的校验结果就是状态码,凭证缺失或错误时,服务端返回401 Unauthorized,翻译成人话就是“我知道你在问我要资源,但我不知道你是谁,所以不给”。
理解了这一点,你就不会觉得401是什么玄学问题了。它就是一次普通的认证失败,我们要做的就是把钥匙换成对的。
1.2 为什么2026年还在坚持用API Key登录
可能有读者会说,codex login打开浏览器扫个码多方便,为什么非要折腾API Key?
我自己的体会是,扫码登录适合个人电脑上的临时体验,但一旦你想在CI流程里跑Codex、在云服务器上自动化改代码、或者团队里多人共享一套账号体系,OAuth那套交互式授权流程就很麻烦了。API Key本质上就是一个静态字符串,你可以把它写进环境变量里,在无人值守的脚本中反复使用,也方便做权限控制——给它配哪个项目、哪种模型权限,你都能在平台上单独管理。
还有一个很现实的理由:API Key可以精确控制预算。OpenAI平台里可以给不同项目创建独立的Key,哪个项目烧了多少钱一目了然。对于负责基础设施的同学来说,这是最省心的方案。所以这篇文章的配置环节,我会重点讲API Key方式,OAuth登录只在安装部分简单带过。
1.3 安装前必须完成的三个检查项
在敲安装命令之前,我建议你先花两分钟确认三件事,否则后面出了问题你根本不知道是Codex的问题还是环境的问题。
第一,Node.js版本要够。Codex的安装包通过npm分发,底层依赖较新的Node运行时,低于18的版本大概率会报错。执行node -v看一眼,如果数字是16开头,建议先升级到20 LTS或更高,别在旧版本上浪费时间。
第二,npm全局目录要可用。所谓“全局目录”,你可以粗暴理解为系统里一个专门放全局命令行工具的文件夹。如果之前从没装过全局包,运行npm install -g的时候可能会遇到权限报错,这个我们放到第2章细说。
第三,确认本机到API服务域名的网络连通性是正常的。Codex在工作时要把请求发到OpenAI的API端点,如果本机网络不通,你会看到各种连接超时、请求失败之类的报错。虽然这类问题和401是两回事,但很多人会混在一起看,所以我建议你先用最简单的命令验证网络,比如ping api.openai.com或者直接访问一下官方文档页面。这个验证不涉及任何特殊手段,就是确认你的机器能正常访问到目标域名。
2. 安装实操:从环境准备到跑通第一条指令
2.1 检查并准备Node.js运行环境
首先打开终端,先执行node -v看看Node版本。如果已经装了但版本太老,建议用官方安装包覆盖安装一次,或者用nvm这类Node版本管理器切换到最新LTS版。这里我不展开讲每个系统的安装细节,只提醒一句:macOS上如果你用Homebrew,brew install node就能直接搞定;Windows上官方安装包一路Next就行;Linux发行版大多数都能用包管理器装到较新版本。
装完Node之后顺手看一下npm -v,确保npm也正常。npm是Node的包管理器,我们后面要用它来安装Codex本体。如果提示npm命令找不到,多半是Node没装成功,或者安装后没有重开终端让环境变量生效。
2.2 安装Codex本体
环境没问题之后,安装命令非常简单:
npm install -g @openai/codex这里-g参数表示全局安装。为什么必须是全局?因为Codex是一个命令行工具,你希望在任何目录下输入codex都能直接唤起它,而不需要每次都跑到某个项目目录下执行。全局安装的本质,就是把可执行文件放到系统PATH包含的目录里。
如果你在Linux或macOS下遇到权限报错,提示类似EACCES: permission denied,别急着用sudo硬怼。我先说结论:用sudo装全局npm包是能跑,但你会发现后续每次更新都要sudo,而且可能污染系统目录,不优雅。更推荐的做法是通过nvm安装Node,这样npm的全局目录就在当前用户目录下,不需要额外权限。如果你实在不想折腾nvm,也可以配置npm的全局目录指向你用户目录下的某个文件夹,具体配置方法可以查npm文档,这里不展开。
安装完成后,验证一下:
codex --version如果能看到版本号,说明本体装好了。如果提示command not found,先别慌,多半是npm全局bin目录不在PATH里。你可以在终端里执行npm prefix -g查看全局目录,然后把bin子目录加进PATH。这一步很基础,但能拦下一堆人。
2.3 首次运行前的登录方式选择
装好之后,执行codex,它会进入交互式对话界面。首次运行时会引导你登录。如果你直接回车,它会尝试打开浏览器走OAuth流程,也就是用ChatGPT账号授权登录。走完这个流程后,授权信息会保存在~/.codex/auth.json文件里,后面运行就不需要再登录了。
但我们这篇文章的目标是用API Key。我一直强调的配置方式是:先给系统设置好OPENAI_API_KEY环境变量,然后再进入Codex。Codex在启动时检测到环境变量里的API Key,会优先使用它,而不需要走浏览器授权。如果环境变量和config配置文件里都有Key,则以环境变量为准——这是一个很关键的优先级知识,后面排查401的时候你会感谢我。
如果你只看局部但没配好Key就先进了交互界面,也不用担心。退出之后,按第3章的步骤配置好Key,重新启动Codex就会生效。
3. API Key的获取与配置:环境变量和config.toml两种姿势
3.1 拿到一把干净API Key的完整流程
这一步看似简单,但出问题最多的人往往就在这一步。我讲一下正确的操作路径:
登录OpenAI平台后,进入左侧的API Keys页面,点击Create new secret key,弹出窗口里会让你填名称和指定项目。名称随意,项目一定要选对——尤其是你如果同时维护多个项目,选错项目会导致后面模型权限对不上。创建成功后,窗口会显示一个以sk-开头的完整密钥,这个字符串只有这一次展示机会,一定要当场复制保存下来。如果关掉窗口再回来,你只能看到密钥的前几位,想看完整内容是不可能的,只能Revoke之后重新创建。
这里有几个细节值得注意。第一,复制的时候别用鼠标划拉,容易漏掉中间几位,建议直接点旁边的复制按钮。第二,粘贴的时候要注意不能带多余空格或换行,这两种情况都可能导致后面401。第三,如果你把Key保存在备忘录里,注意别被截图同步到云上,自己心里有点数。
3.2 推荐姿势:环境变量注入
拿到Key之后,第一种配置方式就是把它写入环境变量。临时生效的写法是:
export OPENAI_API_KEY="sk-你复制出来的完整key" export OPENAI_BASE_URL="https://api.openai.com/v1"这只是当前终端窗口有效。你关掉这个终端,再开一个新窗口,这个变量就没了。所以要想一劳永逸,还得写进shell的配置文件。我以macOS/Linux上最常见的bash和zsh为例:
# 编辑 ~/.zshrc 或 ~/.bashrc echo 'export OPENAI_API_KEY="sk-xxx"' >> ~/.zshrc echo 'export OPENAI_BASE_URL="https://api.openai.com/v1"' >> ~/.zshrc source ~/.zshrc手动编辑也行,关键是不要忘了source。很多人写完配置文件之后直接开新窗口,发现Codex还是不认Key,就是因为没意识到新窗口其实已经加载了新配置,但如果你是在同一个窗口里测试的,那需要你手动执行source才生效。Windows用户则可以在PowerShell里设置用户级环境变量:
setx OPENAI_API_KEY "sk-xxx" setx OPENAI_BASE_URL "https://api.openai.com/v1"setx写完后要重开一个终端窗口才会读取到。
配置完成后,验证是否生效:
echo $OPENAI_API_KEY如果输出的字符串以sk-开头且和你保存的一致,说明环境变量没问题。
3.3 优雅姿势:config.toml配置文件
除了环境变量,Codex还支持通过配置文件管理配置项。配置文件默认位于~/.codex/config.toml,如果你之前没有这个文件,第一次运行Codex之后它通常会帮你创建,也可能需要你手动新建。编辑它,输入以下内容:
# 这里放你账号有权限访问的模型ID # 不确定可以先留空,Codex会用内置默认模型 model = "你的模型ID" [model_provider] name = "openai" base_url = "https://api.openai.com/v1" api_key = "sk-xxx"注意,在config.toml里写api_key是可行的,但我个人更推荐不要写在配置文件里。原因很现实——配置文件很容易被你无意间提交到Git仓库里,或者分享给同事的时候一起发出去,一不留神Key就泄露了。环境变量在系统层管理,至少目录权限是受控的,被误提交的概率更低。当然,如果你就是为了在某个服务器上快速让Codex跑起来,临时写在config.toml里也无妨,但请务必确保这个文件不会离开这台机器。
config.toml还有一个重要用途:配置OpenAI兼容的服务地址。有些企业内部会搭建自己的API网关,提供和OpenAI一致的接口协议。这种情况下你不需要改Codex本身,只需要把base_url指向网关地址,把api_key换成网关分发的Key,模型ID换成网关支持的模型。这个能力很实用,但一定记住:base_url和api_key必须匹配。在官方地址填一个第三方Key,或者在企业网关地址填一个官方Key,都会直接401。
3.4 多环境多账号的切换玩法
如果你要在多个环境里使用不同的Key,比如工作电脑用公司账号的Key,家里电脑用自己的Key,我建议用direnv这类工具按目录自动加载环境变量。你可以在项目根目录放一个.envrc文件,里面写export OPENAI_API_KEY="sk-worker-key",进入这个目录时自动加载,离开目录时自动卸载。这种方式比改全局文件干净得多,也避免了两套Key互相污染。
这里还有一个我很想强调的点:不要为了图省事把Key直接写死在shell配置文件的公共部分,特别是公司配发的开发机上。因为那台机器可能还有其他同事在用,或者你哪天把.zshrc发给别人看,Key就暴露了。最稳妥的做法是单独建一个~/.codex_env文件,然后在.zshrc里source它,这样至少权限控制和可追溯性都会好一点。
4. 401报错全解:从原理到一行一行排查
4.1 401 Unauthorized到底在说什么
你执行codex,等了几秒,终端里蹦出一行熟悉的报错:
unexpected status 401 unauthorized: incorrect api key provided: sk-svcac****我们来拆这行字。401 unauthorized是HTTP状态码,这个没什么可说的。关键是后面那句incorrect api key provided: sk-svcac****,这是服务端把认证失败的原因直接返回给了客户端,而且非常贴心地把你传过去的那把Key的前几位回显了出来。sk-svcac****显然不是完整的Key,服务端展示的是脱敏前缀,但它已经足够帮你定位问题:
如果你配置的Key根本不是sk-svcac开头的,说明请求里携带的Key不是你以为的那一把。这种情况下,大概率是环境中还存在一个旧的Key,通过config.toml或另一处环境变量悄悄覆盖了你新设置的值。反过来,如果你配置的Key确实以sk-svcac开头,但服务端还是说incorrect,那问题就不在“传错了Key”,而在“这把Key本身不被服务端认可”。
我见过有些人看到这个报错就慌,在平台里反复创建新Key,但每次都还是401。其实第一步应该是搞清楚请求里到底带的哪把Key,否则你创建一百把Key也是白搭。
4.2 最常见的七个401场景
第一,复制后带了空格或换行。这可能是最高发的低级错误。Key是普通文本,粘贴到环境变量或配置文件里后,如果末尾多了一个\n,字符串就等于变了,服务端一验必挂。解决办法是配置完以后用echo "$OPENAI_API_KEY"看看输出结尾有没有明显的空行,或者直接用python3 -c "import os; print(repr(os.environ['OPENAI_API_KEY']))"查看字符串的原始形态。
第二,Key被吊销或重建过。你之前保存的Key可能已经在平台上被Revoke了,或者你在另一个项目里复制了旧的Key。只要那把Key在服务端已经失效,无论你怎么配置都会401。这时候回到平台API Keys页面,检查该Key是否存在、状态是否正常。
第三,环境变量没生效。可能是写进了.bashrc但当前终端用的是zsh,或者你忘了source,或者新开的终端确实没有加载对应配置文件。这种问题最迷惑人,因为你看.zshrc里明明有,但当前进程里就是没有。验一下echo $OPENAI_API_KEY就知道。
第四,配置文件里还有一把旧Key。Codex读取API Key的顺序通常是优先环境变量,再读config.toml。如果你在config.toml里写了一个失效的Key,而环境变量里是新的,多数情况下环境变量会覆盖它;但反过来如果你只配置了config.toml,同时里面是错的值,那就会一直401。排查的时候建议把config.toml里的api_key临时清空,再测试一次。
第五,base_url和Key不匹配。这个前面已经提过。你的Key是给官方OpenAI地址用的,结果base_url被改成了某个兼容地址,服务端收到的不是它能识别的Key,直接401。反过来也一样。如果你用了OpenAI兼容网关,务必确认Key、地址、模型三者来自同一个系统。
第六,账号没有该模型的访问权限。有些时候服务端返回401而不是403,这取决于网关具体实现。你创建Key时绑定的项目可能没有开通某模型,或者试用额度到期,导致请求被拒。这种情况建议登录平台看项目的模型权限和余额,别跟Key死磕。
第七,系统时间严重偏差。这算一个比较冷门但真实存在的坑。部分API网关在认证时会校验请求时间戳,如果你的本机时间比真实时间偏了好几分钟,握手阶段就可能出现问题,最终被包装成401/403。解决办法是校准系统时间,macOS和Windows都能直接开自动同步。
4.3 三步定位法:马上就找到病根
遇到401,我强烈建议你按下面三步走,别跳步。
第一步,用echo $OPENAI_API_KEY确认当前环境变量里到底是什么。如果输出为空,说明环境变量没设或者设了没加载。
第二步,打印config.toml里跟api_key、base_url相关的行。cat ~/.codex/config.toml看一眼,确认没有残留的旧Key和错误地址。
第三步,用codex --debug启动调试模式。这个模式下Codex会打印更多请求细节,包括实际请求的endpoint、请求头里的认证信息等。你没看错,调试信息会帮你确认请求真正发到了哪个地址、带的是哪把Key。到了这一步,问题要么是Key值错误,要么是地址错误,不会再有第三种模糊空间。
4.4 一个真实的排查案例
我举个例子。有个同事发来报错,说配置了API Key但还是401,报错里的前缀是sk-proj-***。我让他先echo $OPENAI_API_KEY,发现环境变量输出的值确实以sk-proj-开头。然后我让他cat ~/.codex/config.toml,结果发现里面还有一行api_key = "sk-svcac***"——那是他一周前创建的另一把Key。Codex在某些版本里环境变量和配置文件的优先级并没有完全按文档走,配置文件里的值把环境变量覆盖了。把config.toml里那行注释掉之后,问题立刻解决。
这个案例说明什么呢?401报错回显的key前缀,是最直接的诊断线索。看到sk-proj-和sk-svcac-这两个不同前缀同时出现过,你就该知道一定存在另一个来源的Key“截胡”了。
5. 实操过程中我踩过的坑:几条救命经验
5.1 把API Key写进代码库然后提交了
这事听起来蠢,但真的很多人干过。有一回我图省事,在Python脚本里直接硬编码了Key做联调,然后整个文件夹被git commit推到了远程仓库。当天晚上就收到告警说异常调用,幸好平台支持Key级撤销和用量监控,我第一时间去API Keys页面点了Revoke,那把Key立刻失效,才没造成更大损失。
这件事之后我给自己立了个规矩:任何代码仓库里出现sk-开头的字符串,一律视为事故。现在我都用环境变量或系统密钥管理器保存Key,代码里只写os.environ["OPENAI_API_KEY"]。如果你也想检查仓库里有没有历史遗留的Key,可以用git历史扫描工具扫一遍,发现之后立刻撤销对应Key。别心疼,撤销重建的成本远小于对外泄露的成本。
5.2 终端重启后Key凭空消失
有一个很常见的迷惑现场:下午配置好了Key,用着没问题,第二天早上打开电脑,新建终端跑codex,又报401。查了半天发现echo $OPENAI_API_KEY是空的。
原因基本只有一个:你昨天只在终端里执行了export OPENAI_API_KEY="...",并没有把它写进shell profile。这种临时变量只对当前终端进程有效,终端一关就没了。解决办法前面说过,写进.zshrc或.bashrc,或者用direnv按目录管理。
这里我想多提醒一句:如果你用图形界面SSH工具连服务器,每次新开会话都会重新加载shell配置文件,所以新建的会话反而生效;但如果你在一个已经打开的会话里用tmux分屏,新分屏继承的是旧环境变量。这种细节会迷惑人,排查的时候心里有数。
5.3 多个配置文件“打架”
Codex的配置层级比很多人想象的要复杂一点。用户级配置在~/.codex/config.toml,项目级配置可能出现在项目目录下。如果你在用户级配置里设了Key,又在项目里放了另一个config,那么某些情况下项目级配置会把用户级的值覆盖掉。这意味着你在~/.codex/config.toml里改了半天,项目目录下的配置却一直在捣乱。
我的建议是:如果只是个人使用,只在用户级配置里管理内容,项目目录下完全不建.codex目录;如果确实需要多项目配置,那就明确记住“优先级从高到低:环境变量 > 项目级config > 用户级config”这样的顺序。验证配置到底用哪份,依然可以用codex --debug看日志。
5.4 善用不保存Key的临时方案
有时候我只是想在别人的机器上快速试一下Codex,不想留下任何持久化痕迹。这时候我一般走一条“临时环境变量”路线:
OPENAI_API_KEY="sk-别人的key" codex --debug把环境变量直接放在命令前,只在执行这一条命令的进程里生效,不写入任何shell配置,也不写进config.toml。用完即走,干净利落。这个技巧在排查“是不是我的shell配置里有脏Key”时也特别有用——用绕过所有配置的方式启动Codex,如果它不再401,说明问题一定出在既有配置里。
6. 常见问题速查表
| 问题现象 | 常见原因 | 解决动作 |
|---|---|---|
codex: command not found | npm全局bin目录不在PATH | 执行npm prefix -g,将对应bin目录加入PATH,重开终端 |
输入codex后弹出浏览器引导授权 | 未检测到API Key | 按第3章设置OPENAI_API_KEY环境变量后重启终端 |
报错unexpected status 401 unauthorized: incorrect api key provided: sk-xxx**** | 请求携带的Key与服务端不匹配 | 看前缀定位Key来源,检查环境变量和config.toml里是否存在多个Key |
报错unexpected status 401 unauthorized: authentication fails, your api key: **** | 常见于兼容网关认证失败 | 核对base_url地址与Key是否为同一系统签发 |
报错connect ECONNREFUSED或timeout | 本机与API服务域名网络连通性异常 | 检查本机网络状态,确认可以正常访问API域名,然后重试 |
codex能跑但提示模型不存在 | model填了未开通的模型ID | 登录平台查看项目可用模型列表,换成有权限的模型ID |
| 登录状态一直残留,切不了账号 | OAuth登录态未清除 | 执行codex logout,或删除~/.codex/auth.json |
| 改了环境变量但Codex还是旧Key | 当前shell环境未重新加载 | 执行source ~/.zshrc或重开终端,再用echo $OPENAI_API_KEY验证 |
最后分享一个我个人的小习惯:每次配置完Key之后,我不会直接启动Codex,而是先echo $OPENAI_API_KEY看一眼,再codex --debug跑一条最简单的指令。确认请求地址和Key前缀都符合预期之后,才开始干正事。这个步骤只需要十几秒,但能把401报错的排查时间从半小时压缩到一分钟。你在2026年9月这个时间点照着这篇教程操作,如果一切顺利,Codex应该已经能稳稳跑起来了。如果还有问题,回到上面的速查表,按图索骥,不会比这更复杂了。