GitHub - fancyfx/codex-auth-switcher · GitHub
Skip to content

fancyfx/codex-auth-switcher

Folders and files

Repository files navigation

codex-auth-switcher

本地 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-auth

coex-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

导入单个 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 为空,后续 listusage 会显示为 -。导入后也可以用 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 固定为 null
  • tokens.id_token 来自 CPA 的 id_token
  • tokens.access_token 来自 CPA 的 access_token
  • tokens.refresh_token 来自 CPA 的 refresh_token
  • tokens.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

如果已经有一个可直接用于 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

对已导入的 profile 单独设置或覆盖 tag:

codex-auth tag work team-a
codex-auth tag 1 personal

profile-or-index 支持 profile 名称,也支持 list 输出里的序号。该命令只更新 profile 元数据里的 tag,不会修改 profile 内的 auth.json,也不会修改当前 Codex 的 ~/.codex/auth.json

查看 profiles

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,例如 cpacodex-auth。激活判断基于 profile 的 auth.json 和当前 ~/.codex/auth.json 内容哈希。

查询 usage 额度

codex-auth usage
codex-auth usage --active
codex-auth usage --json

usage 会对已导入 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_invalidated403TimedOutRequestFailedMissingAuth
  • 本项目不实现上游 fallback 时的 local-only rollout 扫描模式;不会读取 ~/.codex/sessions/**/rollout-*.jsonl 来兜底。
  • usage 不修改 profile 的 auth.json,也不写入 usage 缓存;输出只代表本次 API 查询结果。

--active 只查询当前激活 profile。--json 输出结构化 JSON,便于脚本消费。

切换 profile

codex-auth use work

也可以用 list 里的序号切换:

codex-auth use 1

这个命令会:

  1. 校验 work profile 是否存在
  2. 校验 profile 内的 auth.json 是否满足 Codex 基本结构
  3. 如果上一个 active profile 是正常 refresh token 认证,把当前 ~/.codex/auth.json 里的 access_token / refresh_token 回写到该 profile
  4. 把当前 ~/.codex/auth.json 复制到 inactive 目录
  5. work profile 的认证文件替换 ~/.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

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors