只有一个 Codex 项目时,一个模型、一把 Key、一个目录就够了。项目一多,问题就来了:为了 A 项目改了全局配置,B 项目跟着变;两个 Codex 任务在同一个目录里同时改代码;所有项目共用一把 Key,出了问题不知道是谁在调用;最后又把 Codex 接进 GitHub Actions。
这篇按四层来拆:配置用 Profile 分开,Key 按项目分开,文件用 Git worktree 分开,CI 用 Secret 注入 Key 并收紧权限。配置写法都在 Codex CLI 0.162.1 上接 AI Code With 实际跑过。
本文参数说明都附了 OpenAI 官方文档出处,主要来自 Codex Advanced Configuration 和 Codex Configuration Reference。
1. 四层隔离:配置、Key、文件、权限
| 隔离层 | 解决什么问题 | 用什么 |
|---|---|---|
| 配置层 | 不同项目用不同模型或参数 | Codex Profile(--profile) |
| Key 层 | 知道是哪个项目在调用,出问题只停一把 | 每个项目一个 provider、一把 Key |
| 文件层 | 并行任务互不覆盖 | Git worktree |
| 权限层 | 自动化只拿到必要的能力 | GitHub Secret + 最小 permissions |
这四层不能互相替代:Profile 能切模型,但挡不住两个任务同时改同一批文件;worktree 能隔离文件,却不会帮你分开 Key。
2. 先写好全局 config.toml
第一步,在控制台为每个项目各创建一把 Key,名字能看出用途,例如 codex-site-dev、codex-admin-dev:
第二步,打开 ~/.codex/config.toml(Windows 是 %USERPROFILE%\.codex\config.toml),写入完整的基础配置。默认用 aicodewith 这个 provider:
model_provider = "aicodewith"
model = "gpt-6.1-sol"
[model_providers.aicodewith]
name = "aicodewith"
base_url = "https://api.aicodewith.ai/chatgpt/v1"
wire_api = "responses"
experimental_bearer_token = "sk-你的Key"
用本站不需要设 API Key 环境变量,Key 直接写在 experimental_bearer_token 里。各字段的含义见《Codex config.toml 配置指南》,环境变量和这个文件冲突时谁生效见《Codex 环境变量怎么配》。
官方文档原文:model_provider 是「Provider id from model_providers」;experimental_bearer_token 是「Direct bearer token for the provider」。出处:Configuration Reference。
3. 第一层:用 Profile 给每个项目切模型
Profile 是 config.toml 旁边的一个单独文件
现在的 Codex 里,Profile 不是写在 config.toml 里的 [profiles.xxx] 小节,而是 ~/.codex 下一个名为「项目名.config.toml」的文件,里面只写和基础配置不同的那几项。
官方文档原文:「When you pass --profile profile-name, Codex loads ~/.codex/config.toml, then overlays ~/.codex/profile-name.config.toml. Profile names can contain letters, numbers, hyphens, and underscores.」出处:Advanced Configuration · Profiles。
比如官网项目用 gpt-6.1-sol,后台项目用 gpt-5.6-terra,就建两个文件。第一个是 ~/.codex/site.config.toml:
model = "gpt-6.1-sol"
第二个是 ~/.codex/admin.config.toml:
model = "gpt-5.6-terra"
在各自项目目录里用 --profile 启动,交互模式和 codex exec 都可以:
codex --profile site
codex exec --profile admin "检查这次改动"
实测:两个 profile 各跑一次 codex exec,启动信息里分别显示 model: gpt-6.1-sol 和 model: gpt-5.6-terra,都正常回复,用时分别为 2.7 秒和 9.6 秒。
旧写法 [profiles.xxx] 会直接报错
很多旧教程还在 config.toml 里写 [profiles.xxx]。官方说明 0.134.0 起已经不再读取:
官方文档原文:「In Codex 0.134.0 and later, --profile no longer reads [profiles.profile-name] from config.toml, and the top-level profile = "profile-name" selector is no longer supported.」出处:Advanced Configuration · Profiles。
实测在 config.toml 里留着 [profiles.legacy],再运行 codex exec --profile legacy,Codex 不启动,直接报错(路径换成了 ~ 写法):
Error loading config.toml: --profile `legacy` cannot be used while ~/.codex/config.toml contains legacy `profile = "legacy"` or `[profiles.legacy]` config; move those settings into ~/.codex/legacy.config.toml and remove the legacy profile selector/table.
按提示把内容搬到 ~/.codex/legacy.config.toml,再删掉 config.toml 里的 [profiles.legacy] 即可。
profile 名写错不会报错
这是最容易踩的坑。实测运行 codex exec --profile proj-x,而 ~/.codex 下并没有 proj-x.config.toml:Codex 没有任何报错或提示,直接按基础配置跑完了。所以每次启动后看一眼开头的 model: 和 provider: 两行,确认是不是你要的那个项目。
4. 第二层:每个项目用自己的 Key
一个项目一个 provider,Profile 负责选
不同项目用不同 Key,做法是在 config.toml 里给每把 Key 配一段 provider,再由 profile 文件里的 model_provider 选择。在第 2 节的基础配置后面追加一段:
[model_providers.aicodewith_admin]
name = "aicodewith"
base_url = "https://api.aicodewith.ai/chatgpt/v1"
wire_api = "responses"
experimental_bearer_token = "sk-后台项目的Key"
然后把 ~/.codex/admin.config.toml 改成同时指定 provider 和模型:
model_provider = "aicodewith_admin"
model = "gpt-5.6-terra"
这样运行 codex --profile admin 时用的就是后台项目那把 Key;不带 --profile 时仍然用默认的 aicodewith。
实测:给一个 profile 指向一段故意填错 Key 的 provider,启动信息显示 provider: aicodewith_b,请求返回 401;同一台机器上指向正确 Key 的 profile 正常回复。说明 profile 确实切换了 Key。
profile 文件里也能直接覆盖 Key
profile 文件是叠在 config.toml 上面的一层,所以也可以在里面直接改写同一个 provider 的 Key:
[model_providers.aicodewith]
experimental_bearer_token = "sk-另一把Key"
实测这样写同样生效(用错误 Key 测试时返回 401)。不过两种写法里,「一个项目一段 provider」更清楚:打开 config.toml 就能看到一共有几把 Key,profile 文件里不放 Key,复制给同事也不会带出去。
Key 命名和日常核对
Key 的名字至少要能回答:哪个工具、哪个项目、哪个环境,例如 codex-site-dev、codex-admin-dev、codex-ci-review。每周看一次各 Key 的调用记录:调用的模型对不对、最近还有没有在用,没人用的 Key 及时停用。项目不多时按项目拆;项目很多时可以按风险合并,生产独立,临时实验共用一把测试 Key。
5. 第三层:并行任务不要共用同一个工作目录
配置和 Key 分开以后,还有文件。两个 Codex 任务在同一个目录同时改代码,危险的不只是最后合并冲突,而是其中一个任务一直建立在另一个任务改到一半的状态上。Git worktree 让每个任务有自己的目录和分支,又共享同一个仓库的 Git 数据。
给每个任务一个 worktree
git worktree add ../project-task-a -b codex/task-a main
git worktree add ../project-task-b -b codex/task-b main
git worktree list
然后让每个 Codex 任务只在自己的目录里工作。目录名对应任务,不要叫 tmp1、tmp2。给 Codex 的任务说明里写清楚允许改的路径、验收命令和不能碰的共享配置。
worktree 只隔离文件
两个 worktree 仍可能抢同一个 3000 端口、同一个开发数据库、同一个测试账号。并行前列一张共享资源表:哪些能分配不同端口或测试数据,哪些只能有一个任务写入。lockfile、数据库迁移和代码生成结果最容易冲突,可以指定一个任务为唯一写入者。
合并前先让每个任务成为可验证的提交
git -C ../project-task-a status
git -C ../project-task-a diff --check
在 worktree 里看完 diff、跑完项目自己的测试再提交,回主分支审查后再 merge 或 cherry-pick。两个任务有依赖时,先合基础改动,再让后面的分支 rebase 并重新跑测试。
用完清理
git worktree remove ../project-task-a
git worktree prune
确认提交已经进了目标分支、目录里没有要保留的改动再清理。直接删文件夹的话,Git 里还会留着 worktree 记录。
6. 第四层:在 GitHub Actions 里用 Codex
最小写法:用 Secret 生成 config.toml
在仓库的 Settings → Secrets and variables → Actions 里新建一个 Secret,名字叫 AICODEWITH_API_KEY,值是专门给 CI 建的那把 Key。然后在 workflow 里先装 Codex,再用一个步骤从 Secret 生成 config.toml:
name: codex-review
on: pull_request
permissions:
contents: read
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- run: npm install -g @openai/codex
- name: Configure Codex
env:
AICODEWITH_API_KEY: ${{ secrets.AICODEWITH_API_KEY }}
run: |
mkdir -p ~/.codex
cat > ~/.codex/config.toml <<EOF
model_provider = "aicodewith"
model = "gpt-6.1-sol"
[model_providers.aicodewith]
name = "aicodewith"
base_url = "https://api.aicodewith.ai/chatgpt/v1"
wire_api = "responses"
experimental_bearer_token = "${AICODEWITH_API_KEY}"
EOF
- name: Run Codex
run: codex exec "只检查本次改动的错误处理,列出发现和证据,不修改文件。"
实测:把 Configure Codex 这一步的脚本放在一个干净的 HOME 下运行,Key 由环境变量传入,生成的 config.toml 接着跑 codex exec,2.9 秒返回正常回复。
几个要点:
- Key 只出现在 Secret 和运行时生成的文件里,不写进仓库,也不要 echo 到日志。
- permissions 从 contents: read 开始。GitHub 的 permissions 管 workflow 的 token 能对仓库做什么,Codex 自己的沙箱管它运行的命令能碰哪些文件,两层都要收紧。
- 来自 fork 的 pull request 默认拿不到仓库 Secret,不要为了让它能跑就改成更宽的触发方式。
GitHub permissions 字段的说明见 GitHub Docs:Authenticate with GITHUB_TOKEN。
写权限跟着任务一起加
只读审查只需要读。要让 Codex 改文件、提交补丁或发评论时,再加对应的权限,而且只加这次任务需要的那一项。更稳的流程是:Codex 先产出报告或补丁,人或独立步骤检查 diff 和测试,再由受控流程提交。
Prompt 写成验收标准
在 CI 里写「优化一下代码」几乎没法验收。写清楚目标范围、不能改的区域、必须跑的检查和输出格式。规则很长时放进仓库里的文件,这个文件本身也要经过 Review。
7. 完整例子:三个项目加一个 CI
| 场景 | 启动方式 | Key(provider) | 文件隔离 |
|---|---|---|---|
| 官网开发 | codex --profile site | codex-site-dev(aicodewith) | 独立 worktree |
| 后台开发 | codex --profile admin | codex-admin-dev(aicodewith_admin) | 独立 worktree |
| SEO 脚本 | codex --profile seo | codex-seo-ops(aicodewith_seo) | 独立分支 |
| PR 审查 | GitHub Actions | codex-ci-review(Secret 注入) | CI 的 checkout |
配置差异靠 Profile,调用归属靠 Key,并行改代码靠 worktree,CI 用独立 Secret 和只读权限,最后交付仍然以 diff、测试和 Review 为准。
8. 常见报错
401:请在请求中提供有效的 API Key
profile 指向的 provider 里 Key 填错或已失效时,实测输出:
ERROR: unexpected status 401 Unauthorized: {"error":"请在请求中提供有效的 API Key。"}, url: https://api.aicodewith.ai/chatgpt/v1/responses
先看启动信息里的 provider: 是哪一段,再去 config.toml 里核对那一段的 experimental_bearer_token。更多情况见《Codex 401 Unauthorized 怎么解决》。
模型不存在或未上线
profile 里写了本站没有的模型名时,实测输出:
ERROR: {"error":"模型 gpt-5.5 不存在或未上线,请前往 https://aicodewith.com/zh/dashboard/pricing 查看可用模型列表 (request_id: ...)"}
把 profile 文件里的 model 改成控制台模型列表里有的名字,例如 gpt-6.1-sol。
--profile 报 legacy 配置错误
config.toml 里还留着 [profiles.xxx] 时会报这个错,原文和处理方法见第 3 节。
常见问题
Profile 能不能单独换 Key?
能。推荐给每把 Key 配一段 provider,在 profile 文件里用 model_provider 选;也可以在 profile 文件里直接覆盖同一个 provider 的 experimental_bearer_token。两种实测都生效。
为什么我写的 [profiles.work] 不生效?
0.134.0 起 Codex 不再读 config.toml 里的 [profiles.xxx]。把内容挪到 ~/.codex/work.config.toml,并删掉原来的小节。
--profile 名字打错了会怎样?
实测不会报错,Codex 直接按基础配置运行。启动后看开头的 model: 和 provider: 两行确认。
多个项目要设 API Key 环境变量吗?
不用。Key 写在 config.toml 各 provider 的 experimental_bearer_token 里,profile 负责选择。只有 CI 里是先用 Secret 注入环境变量,再生成 config.toml。
只有一把 Key,Profile 还有用吗?
有。可以只用 Profile 切模型,比如日常用 gpt-6.1-sol,简单任务换一个更快的模型。
其他工具(OpenCode、WorkBuddy)也要分项目吗?
思路一样。具体配置见《Codex、OpenCode、WorkBuddy 模型怎么配》。
免费注册 AI Code With,给 Codex 配一个专用 Key →
相关阅读
- 《Codex config.toml 配置指南》
- 《Codex 环境变量怎么配》
- 《Codex API Key 怎么配置》
- 《Codex、OpenCode、WorkBuddy 模型怎么配》
- 《Codex 401 Unauthorized 怎么解决》