本地 Codex 认证信息管理 CLI。
codex-auth import-cpa ./cpa.json --name work --tag team-a
codex-auth import-cpa ./cpa.json
codex-auth import-cpa ~/.cli-proxy-api
codex-auth import-auth ~/Desktop/dis-auths/auth-loveydfforever@icloud.com.json --name loveyd --tag personal
codex-auth list
codex-auth usage
codex-auth tag work team-a
codex-auth use 1
codex-auth use work项目不依赖第三方包,Node.js 20+ 即可运行。
cd ~/fxWorkSpac/tool/codex-auth-switcher
npm link安装后可以直接使用 codex-auth 命令。也可以不安装,直接运行:
node ./bin/codex-auth.js list也可以初始化 zsh 全局命令和补全:
node ./bin/codex-auth.js init-zsh
source ~/.zshrc这个命令会创建两个全局入口:
codex-auth
coex-authcoex-auth 是同一个 CLI 的别名。补全脚本会安装到 ~/.zsh/completions/_codex-auth。
真实认证信息不会写入项目目录。默认运行时数据放在:
~/.codex-auth-switcher
├── profiles
├── inactive
└── state.json切换账号时会写入 Codex 当前认证文件:
~/.codex/auth.json如果切换前已经存在 ~/.codex/auth.json,旧文件会复制到:
~/.codex-auth-switcher/inactive导入单个 CPA JSON:
codex-auth import-cpa ./cpa.json --name work --tag team-a--name 可以省略。省略时默认从 CPA 文件中按顺序读取:
name -> email -> account_id -> chatgpt_account_id
例如 CPA 文件里只有 email: "person@example.com" 时,profile 名称会是 person@example.com。
--tag 可选,用于给导入的 profile 写入一个便于分组或识别的标签;不传时 tag 为空,后续 list 和 usage 会显示为 -。导入后也可以用 codex-auth tag <profile-or-index> <tag> 单独设置或覆盖 tag。
如果同名 profile 已存在,默认拒绝覆盖。确认要覆盖时使用:
codex-auth import-cpa ./cpa.json --name work --force也可以直接传目录,批量导入该目录直属的所有 .json 文件:
codex-auth import-cpa ~/.cli-proxy-api目录导入也可以传 --tag,该 tag 会应用到本次导入的所有 profile:
codex-auth import-cpa ~/.cli-proxy-api --tag team-a目录导入规则:
- 只识别目录下文件名以
.json结尾的直属文件 - 不递归子目录
- 不支持
--name,每个 profile 名称都从对应 CPA 文件里读取 - 导入前会先校验全部文件和 profile 名称;如果有重复名称或无效文件,不会写入部分结果
- 同名 profile 已存在时默认拒绝覆盖,确认覆盖时使用
--force
导入器按标准 CPA 扁平结构转换,目标 auth.json 格式与 Codex 当前认证文件兼容:
{
"auth_mode": "chatgpt",
"OPENAI_API_KEY": null,
"tokens": {
"id_token": "...",
"access_token": "...",
"refresh_token": "...",
"account_id": "..."
},
"last_refresh": "2026-05-24T00:00:00.000Z"
}字段映射规则:
auth_mode固定为"chatgpt"OPENAI_API_KEY固定为nulltokens.id_token来自 CPA 的id_tokentokens.access_token来自 CPA 的access_tokentokens.refresh_token来自 CPA 的refresh_tokentokens.account_id优先来自 CPA 的account_id,其次chatgpt_account_id;如果都获取不到,转换后的auth.json不写入这个字段last_refresh来自 CPA 的last_refresh,缺失时使用当前时间
当 CPA 的 refresh_token 是空字符串或 null 时,会生成:
{
"tokens": {
"refresh_token": "__missing_refresh_token__"
},
"axonhub_refresh_token_placeholder": true,
"axonhub_note": "refresh_token is a placeholder; access_token works only until it expires."
}同一场景下,tokens.id_token 会确保以 .synthetic 结尾;如果原始 id_token 已经以 . 结尾,则会补成 ...synthetic,避免出现 ..synthetic。
如果已经有一个可直接用于 Codex 的 auth.json 文件,使用官方认证导入模式:
codex-auth import-auth ~/Desktop/dis-auths/auth-loveydfforever@icloud.com.json --name loveyd --tag personal官方认证导入规则:
- 必须显式传
--name --tag可选- 只支持单文件导入
- 不做 CPA 字段转换
- 不补
refresh_token - 不修改
id_token - profile 内的
auth.json直接复制源文件内容 - 仍会做 Codex auth 的基础结构校验,避免把明显不是认证文件的 JSON 放进 profile
对已导入的 profile 单独设置或覆盖 tag:
codex-auth tag work team-a
codex-auth tag 1 personalprofile-or-index 支持 profile 名称,也支持 list 输出里的序号。该命令只更新 profile 元数据里的 tag,不会修改 profile 内的 auth.json,也不会修改当前 Codex 的 ~/.codex/auth.json。
codex-auth list输出包含序号列:
# ACTIVE NAME TAG IMPORTED_AT ORIGIN
1 dif.gpt@outlook.com team-a 2026-05-24T14:01:04.182Z cpa
2 loveyd personal 2026-05-24T14:01:04.214Z codex-auth
当前激活的 profile 会用 * 标记。TAG 显示 profile 元数据里的 tag,没有设置时显示 -。ORIGIN 直接显示 profile 元数据里的 source.format,例如 cpa 或 codex-auth。激活判断基于 profile 的 auth.json 和当前 ~/.codex/auth.json 内容哈希。
codex-auth usage
codex-auth usage --active
codex-auth usage --jsonusage 会对已导入 profile 发起 ChatGPT usage API 请求,并展示 tag、5 小时额度、周额度、套餐和状态:
# ACTIVE NAME TAG PLAN 5H WEEKLY STATUS
1 * work team-a Business 89% (18:15) 6% (26 May 18:15) ok
2 backup - - - - 401 token_invalidated
注意:
- 该命令会把对应 profile 的
tokens.access_token发送到https://chatgpt.com/backend-api/wham/usage。 - 请求 header 包含
Authorization: Bearer <access_token>和ChatGPT-Account-Id: <tokens.account_id>。 - 这是 ChatGPT 后端接口,不是 OpenAI public API。
- API 请求失败时只展示对应错误状态,例如
401 token_invalidated、403、TimedOut、RequestFailed或MissingAuth。 - 本项目不实现上游 fallback 时的 local-only rollout 扫描模式;不会读取
~/.codex/sessions/**/rollout-*.jsonl来兜底。 usage不修改 profile 的auth.json,也不写入 usage 缓存;输出只代表本次 API 查询结果。
--active 只查询当前激活 profile。--json 输出结构化 JSON,便于脚本消费。
codex-auth use work也可以用 list 里的序号切换:
codex-auth use 1这个命令会:
- 校验
workprofile 是否存在 - 校验 profile 内的
auth.json是否满足 Codex 基本结构 - 如果上一个 active profile 是正常 refresh token 认证,把当前
~/.codex/auth.json里的access_token/refresh_token回写到该 profile - 把当前
~/.codex/auth.json复制到 inactive 目录 - 用
workprofile 的认证文件替换~/.codex/auth.json
npm test
npm run check测试使用临时目录和环境变量,不会改动真实的 ~/.codex/auth.json。
用于测试或临时改路径:
CODEX_AUTH_SWITCHER_HOME=/tmp/codex-auth-switcher \
CODEX_AUTH_SWITCHER_CODEX_AUTH_PATH=/tmp/codex/auth.json \
node ./bin/codex-auth.js list