@ytechai/codex-forge
v0.1.45
Published
Local all-model BYOK configuration forge for Codex Desktop and CLI. Single install supports both server mode and CLI tool mode.
Maintainers
Readme
codex-forge
Local BYOK model gateway for Codex Desktop & CLI
把任意 OpenAI / Anthropic 兼容模型接入 Codex 原生选择器,而无需重建 Codex。
codex-forge is a local Node.js gateway that speaks the OpenAI Responses API Codex expects, then routes each request to the right upstream: OpenAI Chat Completions, Anthropic Messages, generic OpenAI-style chat endpoints, or the ChatGPT/Codex backend when a valid token is available.
这套方案的目标很明确:保持 Codex 原生的编辑器/代理体验,同时把模型路由、BYOK 配置和订阅透传放到本地可控的层级里。它适合这样一类用户:
- 想在 Codex 原生选择器里使用自有或 BYOK 模型;
- 想保留函数调用、工具输出、流式响应和图像能力;
- 想在本地控制 provider、routing 和 prompt 处理;
- 想把
codex-forge作为本地网关或远程服务端部署。
这个项目的实现很轻:纯 Node.js、零运行时依赖,跨平台支持 macOS、Windows、Linux、WSL 和 Git Bash。macOS 上唯一的专属能力是可选的 Desktop 选择器 ASAR 补丁,仅在 Codex 隐藏自定义条目时才需要。
已在 Codex Desktop 0.133.0-alpha.1(macOS arm64)上测试通过。
它能给你带来什么
Codex Desktop 只显示其服务端配置允许的模型。如果你有想作为一等公民出现在选择 器里的 OpenAI / Anthropic / Z.ai / DeepSeek / Gemini / OpenRouter / 本地代理 模型,本项目可以在本地把它们接入。
实际收益是:Codex 保持原生体验,而模型路由下沉到本地:
- BYOK 模型出现在正常的 Codex 选择器里。 不需要重建 Codex,也不需要请求重 放工作流。
- 原生 Codex agent 循环保持完整。 函数调用、工具输出、推理块、支持图像的 模型、shell 命令元数据和流式 SSE 都被翻译,而不是被压平成纯文本。
- ChatGPT/Codex 透传。 如果
~/.codex/auth.json里有有效的 Codex 访问令 牌,forge 可以把 Codex 原生的/v1/responses流量以当前 Codex 构建使用的gpt-5.5slug 路由到 ChatGPT 的 Codex 后端。 - Auto Router(可选)。 增加一个
Auto (smart routing)选择器条目,用一 个便宜的分类器模型把每个任务路由到能胜任的最便宜模型 —— 简单轮次保持低成 本,困难轮次自动升级。见docs/AUTO_ROUTER.md。 - 提示词捕获/代理友好架构。 在 forge 前面放一个本地代理,可以去重模板文 本、注入稳定指令、修复伪工具文本,或在请求到达上游前按策略路由提示词。
- 维护者在真实编码 agent 任务上的收益。 在维护者的内部 Codex 任务中, ChatGPT 透传加上 forge 前面的提示词捕获代理,带来了计费输入 token 的数倍下 降和相对基线路径明显更快的墙钟时间。仓库尚未附带可复现的基准脚本,请把这 当作轶事数据 —— 下面的基准章节说明了如何在引用数字前用明确的对照组测量 你自己的配置。
环境要求
- Node.js 22+。
- 已安装并完成认证的 Codex CLI/Desktop。
- server 主机满足以下之一:
~/.codex-forge/server/models.toml中配置了 BYOK/上游模型;- server 通过
--settings传入另一份models.toml; - server 主机
~/.codex/auth.json中包含tokens.access_token(仅用于 ChatGPT/Codex 透传)。
- forge 只使用 Node.js 标准库与一个 TOML 解析器(
smol-toml);如从源码运行, 请先执行pnpm install安装依赖。 - Windows:PowerShell/cmd 可通过
node src/run.mjs ...运行;WSL 或 Git Bash 仅在需要可选的bin/shell 包装脚本时才需要。 - 仅 macOS:如果需要可选的 Desktop 选择器补丁,需要
npx和codesign。
安装
这是一个 Multi-binary package(@ytechai/codex-forge),安装后提供两个独立命令:
| 命令 | 职责 | 运行位置 |
|---|---|---|
| codex-forge-cli | 工具端:Codex 配置管理、模型切换、诊断 | 安装 Codex 的电脑 |
| codex-forge-server | 服务端:模型代理、API 端点、daemon 管理 | 本机或局域网任意主机 |
两个命令来自同一个 npm 包,但运行时只通过 HTTP 协作。跨主机是默认架构约束;
同机只是 server 地址恰好为 loopback 的特例。 codex-forge-cli 与 codex app
同主机时可以共享本地 ~/.codex/config.toml,但 codex-forge-server 不读取、
不写入这份文件,也不控制 Codex Desktop。
方式一:npm 全局安装(推荐)
npm install -g @ytechai/codex-forge安装后即可使用 codex-forge-cli 和 codex-forge-server 两个命令。
方式二:软链(开发/本地安装)
克隆仓库并把 bin/ 软链到 PATH 中,可直接使用最新代码:
git clone https://github.com/veryben/codex-forge ~/codex-forge
cd ~/codex-forge
pnpm install # 安装 TOML 解析器依赖(smol-toml)
mkdir -p ~/.local/bin
ln -sf "$PWD/bin/codex-forge-cli" ~/.local/bin/codex-forge-cli
ln -sf "$PWD/bin/codex-forge-server" ~/.local/bin/codex-forge-serverbin/ 脚本是薄壳,优先加载 dist/,回退 src/。开发时可以设置
CODEX_FORGE_DEV=1 直接使用 src/,无需每次 npm run build:
export CODEX_FORGE_DEV=1 # 加入 ~/.zshrc 即可永久生效移动仓库位置后需重建软链。在原生 Windows PowerShell/cmd 上直接运行:
git clone https://github.com/veryben/codex-forge $HOME\codex-forge
cd $HOME\codex-forge
pnpm install # 或 npm install
node src/run.mjs show如果找不到命令,确认 ~/.local/bin 在 PATH 中:
export PATH="$HOME/.local/bin:$PATH"
# 永久生效:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # macOS 默认 zsh运行模式与命令
codex-forge 采用服务端 + 工具端分离架构,单一安装支持两种运行模式:
┌─────────────────────────────────────────────────────────────────┐
│ 工具端 (codex-forge-cli) │
│ 运行位置: 安装 Codex 的电脑 │
│ 职责: Codex 配置、本地 catalog、模型切换、启动 Codex │
│ 依赖: 必须连接运行中的服务端 │
└─────────────────────────────────────────────────────────────────┘
│ ▲
│ 调用 API │ 获取数据
▼ │
┌─────────────────────────────────────────────────────────────────┐
│ 服务端 (codex-forge-server) │
│ 运行位置: 本机或其它电脑 │
│ 职责: 模型配置、凭据、路由、翻译、daemon 生命周期 │
└─────────────────────────────────────────────────────────────────┘服务端命令(服务运行)
运行位置:可以是本机或其它电脑,只需
~/.codex-forge/server/models.toml
codex-forge-server start # 后台启动守护进程
codex-forge-server stop # 停止服务
codex-forge-server restart # 重启服务
codex-forge-server status # 查看服务状态
codex-forge-server logs # 查看 server 日志
codex-forge-server console # 前台运行(阻塞控制台)前台运行时可指定参数:
codex-forge-server console --settings ~/.codex-forge/server/models.toml --port 58767
CODEX_FORGE_TOKEN=... codex-forge-server console --host 0.0.0.0 --port 58767server 默认绑定 127.0.0.1。绑定 0.0.0.0 或其它局域网地址属于显式开启远程
访问,建议同时设置 CODEX_FORGE_TOKEN、防火墙规则,或在 TLS 反向代理后面部署。
服务端 API
| 端点 | 方法 | 用途 |
|------|------|------|
| /health | GET | 健康检查 |
| /api/models | GET | 返回模型列表(简化版) |
| /api/models/full | GET | 返回 CLI 生成 catalog 所需的模型 DTO |
| /api/refresh | POST | 校验并刷新 server 配置,不写任何文件 |
| /v1/models | GET | OpenAI 格式模型列表 |
| /v1/chat/completions | POST | OpenAI chat 请求代理 |
| /v1/messages | POST | Anthropic messages 请求代理 |
| /v1/responses | POST | OpenAI responses 请求代理 |
| /api/switch | POST | 已迁移到 CLI,返回 410 Gone |
工具端命令(工具操作)
运行位置:必须在安装 Codex 的电脑上,需要修改
~/.codex/config.toml
通用选项
codex-forge-cli -v # 显示版本
codex-forge-cli --version # 显示版本
codex-forge-cli -h # 显示帮助
codex-forge-cli --help # 显示帮助服务端同样支持版本与帮助:
codex-forge-server -v # 显示版本
codex-forge-server --help # 显示帮助配置管理
codex-forge-cli config show # 查看当前服务器连接配置
codex-forge-cli config set host <ip> # 设置远程服务器地址
codex-forge-cli config set port <port> # 设置服务器端口运行时状态按归属角色存放在 ~/.codex-forge/server/(仅 server 主机)与
~/.codex-forge/cli/(仅 client 主机)两个子目录,没有扁平的旧布局需要迁移。
配置存储在 ~/.codex-forge/cli/cli.json,也可用命令行参数临时覆盖:
codex-forge-cli --host 192.168.1.100 --port 58767 list当 Codex 已启用 forge 配置时,config set 会立即同步 ~/.codex/config.toml
里的 base_url(服务器在线则完整重建配置,离线则就地更新 base_url),无需
重新运行 enable。
模型操作
codex-forge-cli list # 查看可用模型列表
codex-forge-cli model list # 同上
codex-forge-cli model current # 查看当前使用的模型
codex-forge-cli model use <slug> # 切换默认模型Codex 配置
codex-forge-cli generate # 生成配置目录(需要服务运行)
codex-forge-cli enable # 启用 forge provider(修改 ~/.codex/config.toml,需要服务运行)
codex-forge-cli disable # 禁用 forge provider(恢复原配置)
codex-forge-cli doctor # 诊断配置问题启动 Codex
codex-forge-cli codex -- "prompt" # 使用 Codex CLI 执行任务
codex-forge-cli app . # 启动 Codex Desktop
codex-forge-cli app -m <slug> . # 启动 Codex Desktop 并指定模型配置文件说明
运行时状态按归属角色拆成两个子目录;codex-forge 默认跨主机部署,所以一台只 运行单一角色的机器只会出现对应角色的子目录:
~/.codex-forge/server/:只存在于 server 主机 —— provider 配置、daemon 状态、日志、调试转储、迁移备份。~/.codex-forge/cli/:只存在于 client 主机 —— CLI 连接配置、Codex 模型 目录、备份。
每个路径只有一个归属位置,没有旧布局的等价副本,也没有回退解析。
| 文件 | 用途 | 读取者 | 写入者 |
|------|------|--------|--------|
| ~/.codex-forge/server/models.toml | 定义可用模型和上游 API(推荐,仅 server 主机) | 服务端 | 用户 |
| ~/.codex-forge/cli/cli.json | 工具端连接 server 的 host / port / token(仅 client 主机) | 工具端 | 工具端(自动生成) |
| ~/.codex-forge/cli/model_catalog.custom.json | Codex 模型目录(仅 client 主机) | Codex | 工具端生成 |
| ~/.codex/config.toml | Codex provider 配置 | Codex | 工具端生成 |
| ~/.codex-forge/cli/backups/config.toml.before-codex-forge | 首次 enable 前的 ~/.codex/config.toml 原样快照 | 工具端 | 工具端(仅首次) |
| ~/.codex-forge/server/server.pid | daemon PID(仅 server 主机) | server | server |
| ~/.codex-forge/server/server.log | daemon stdout / stderr(仅 server 主机) | server | server |
托管块的写入安全
enable / disable 只增删自己的托管块(# >>> codex-forge managed >>> …
# <<< codex-forge managed <<<),并且:
- 首次
enable会把当时的~/.codex/config.toml原样存成~/.codex-forge/cli/backups/config.toml.before-codex-forge。只在配置里还没有 托管块时写一次;后续enable不会用「已被 forge 改过」的内容覆盖它,disable也不会删除它,留作随时可回退的原稿。 - 如果发现别人的配置落在托管块标记内部(Codex Desktop 追加的
[desktop]、[marketplaces.*]、[plugins.*]等曾出现过这种情况),这些内容会被移出 托管块并重新输出,而不是被一起删掉;命令会在 stderr 打印被保留的内容。 enable是幂等的:重复执行不会重复追加,也不会产生 diff。
这条角色边界还有静态保证:tests-node/architecture.test.mjs 会检查 server 代码
不得引用 cli/ 路径,client 代码不得引用 server 运行时产物(pid / log / debug)。
Windows 支持
可以,forge 在 Windows 上可用。核心 forge 是 Node.js,绑定 127.0.0.1,写入与
macOS/Linux 相同的 Codex provider 配置。可选以下任一方式:
| 环境 | 状态 | 说明 |
|---|---|---|
| 原生 Windows PowerShell/cmd | 支持 | 在仓库目录运行 node src/run.mjs ...。 |
| WSL | 支持 | 与 Linux 相同。当 Codex CLI/Desktop 也在 WSL 中驱动时最合适。 |
| Git Bash | 支持 | Node/Codex 在 PATH 上时可配合 POSIX bin/ 包装脚本使用。 |
| PowerShell/cmd 中的 bin/ 脚本 | 非原生 | bash 脚本不可用;脚本会检测到非 bash 环境并给出明确提示,请改用 Git Bash 或 node src/run.mjs ...。 |
| patch-app / restore-app | 仅 macOS | 它们针对 /Applications/Codex.app 与 macOS 上的 Electron ASAR 签名。 |
原生 Windows 快速检查:
node src/run-server.mjs --port 58767
node src/run.mjs show
node src/run.mjs list路径行为刻意保持常规:
- 在原生 Windows 中,
~/.codex-forge/server/models.toml指%USERPROFILE%\.codex-forge\server\models.toml,Codex 配置 位于%USERPROFILE%\.codex\config.toml。 - 在 WSL 中,
~/.codex-forge/server/models.toml和~/.codex/config.toml位于 Linux home 目录内,除非你显式用--settings指向/mnt/c/...下的 Windows 路径。 - 不要把 WSL 生成的
~/.codex/config.toml与原生 Windows Codex 混用并指望两 者自动共享文件。如果 Codex 是原生 Windows,请走原生 Windows 安装路径,或手 动保持 Windows 配置同步。 - 本地 provider URL 仍然是
http://127.0.0.1:58767/v1。
运行 forge 服务器并不需要可选的 macOS 选择器补丁。在 Windows 上,只要 Codex 能 读取生成的目录/provider 配置,请求就会像其他平台一样通过同一个本地端点路由。
Windows Store/MSIX 版 Codex Desktop 比 CLI 更严格。它可能把自定义本地/BYOK
slug 视为不可用、把 model = "<custom-slug>" 改回 gpt-5.5,并在启动时添加
[tui.model_availability_nux] 条目。这是 Desktop 的允许列表行为,不是 forge 路
由行为:codex exec、TUI 和 forge 端点仍然使用配置的模型 slug。macOS 的
patch-app 助手不适用于 C:\\Program Files\\WindowsApps 下的 MSIX 包。
如果 Windows 有 Clash/V2Ray 之类的系统代理,请确保回环地址绕过它:
setx NO_PROXY "127.0.0.1,localhost,::1"
setx no_proxy "127.0.0.1,localhost,::1"codex-forge-cli codex -- ... 和 codex-forge-cli app ... 会自动把这些回环条目加入
被启动进程的环境;如果你直接运行 codex.exe,也请全局设置它们。
快速开始
1. 生成目录并启动 forge
codex-forge-server start # 后台启动守护进程
codex-forge-cli list # 查看可用模型
codex-forge-cli show # 查看状态运行时文件按归属角色分开存放:server 主机的产物在 ~/.codex-forge/server/,
client 主机的产物在 ~/.codex-forge/cli/:
~/.codex-forge/cli/model_catalog.custom.json # model picker catalog for Codex(client 主机)
~/.codex-forge/cli/backups/ # pre-forge config snapshot、session 迁移备份(client 主机)
~/.codex/config.toml # Codex provider config (CLI writes,client 主机)
~/.codex-forge/server/server.pid # daemon pid(仅服务端读写,server 主机)
~/.codex-forge/server/server.log # stdout/stderr + request summaries(server 主机)服务器默认绑定 0.0.0.0,接受来自所有网络接口的连接。在不可信网络中,建议
配合 CODEX_FORGE_TOKEN 或防火墙使用。
2. 把 Codex Desktop 指向它
codex-forge-cli app . # launch Codex Desktop with the forge wired inapp 会生成目录、按需启动本地守护进程,并在 ~/.codex/config.toml 写入一个
小的托管块,使 Codex Desktop 使用本地 provider。原配置会作为原样快照存到
~/.codex-forge/cli/backups/config.toml.before-codex-forge(仅首次写入,disable
时保留),托管块可用以下命令移除:
codex-forge-cli disable此后,Codex Desktop 能看到 ~/.codex-forge/server/models.toml
中的每个条目,外加 GPT-5.5 ChatGPT 透传 slug(当且仅当 ~/.codex/auth.json
持有有效的 tokens.access_token)。
如果你的 Codex Desktop 模型选择器只显示 default 且拒绝渲染目录条目,请使用
下面的 macOS 选择器补丁。
3. 切换 Desktop 的激活模型
codex-forge-cli model list
codex-forge-cli model use <slug> # 切换到指定模型
codex-forge-cli app . # 重新启动 Codex Desktopcodex-forge-cli model use <slug> 改写 ~/.codex/config.toml 中 forge 托管的块。
4. 不改配置使用 Codex CLI
一次性 CLI 运行使用内联 -c 覆盖,而不是修改 ~/.codex/config.toml:
codex-forge-cli codex -- "inspect this repo and summarize the architecture"自定义配置文件
server 默认读取其主机上的 ~/.codex-forge/server/models.toml(仅支持这一种格式,
JSON 配置已移除)。文件缺失时 server 仍会启动,只是没有 BYOK 模型可服务;此时若
server 主机 ~/.codex/auth.json 包含有效的 tokens.access_token,仍会返回 ChatGPT
透传模型。你也可以用 --settings 指向另一份 TOML:
codex-forge-server start --settings /path/to/my-models.tomlmodels.toml 结构(推荐)
一个网关一块:[providers.<id>] 写这个网关的凭据,[[providers.<id>.models]]
写该网关下的模型 —— 不用再写 provider = "…" 引用,也就不可能出现引用不存在的
网关:
[providers.deepseek]
protocol = "openai" # openai | anthropic | ollama | generic-chat-completion-api
base_url = "https://api.deepseek.com"
api_key = "sk-…" # 字面量,或 "${DEEPSEEK_API_KEY}" 在加载时展开
# api_key_env = "DEEPSEEK_API_KEY" # 可选:环境变量名,优先于 api_key
# extra_headers = { x-foo = "bar" } # 可选:网关级附加请求头
[[providers.deepseek.models]]
display_name = "my-deepseek-flash" # 展示名 & slug 来源
model = "deepseek-flash" # 上游真实模型 ID
max_context_limit = 819000
[providers.mimo-sk]
protocol = "anthropic"
base_url = "https://api.xiaomimimo.com/anthropic"
api_key = "sk-…"
[[providers.mimo-sk.models]]
display_name = "my-mimo-v2.5-sk"
model = "mimo-v2.5"
max_context_limit = 819000完整示例见 examples/models-example.toml。
顺序即优先级:provider 块在文件中的顺序 × 块内模型顺序 = Codex 看到的模型 顺序(catalog priority、选择器顺序、以及"第一个可用模型"这个默认对话模型)。 想显式指定 Codex 辅助请求的落点,用
provider_default = true(见下节)。旧写法(顶层
[[models]]+provider = "…",以及[[models.<provider>]])会被 明确拒绝并给出正确写法,不会再静默读出 0 个模型。
设计要点:
- provider 名即 ID(如
mimo-tp),允许同协议多网关、同网关多账号。 - key 解析顺序:
api_key_env→${ENV}展开 → 字面值;模型级api_key可覆盖 provider 的 key。 extra_headers合并:provider 级与模型级按 key 合并,模型级优先。- 校验:模型嵌在 provider 块内,引用不存在的网关在结构上已不可能;缺
protocol/base_url的 provider 其模型会被静默跳过。顶层出现[[models]]等旧写法会直接报错并给出正确写法。 - 同名 model 跨网关由现有 slug 去重逻辑处理。
支持的 protocol 取值:
| protocol | 上游 API |
|---|---|
| openai | OpenAI /v1/chat/completions |
| generic-chat-completion-api | OpenAI 形态的 chat completions |
| anthropic | Anthropic /v1/messages |
| ollama | 归一化为 generic-chat-completion-api |
forge 还在同一端口接受 Anthropic Messages 请求(/v1/messages)。对
于 openai 和 generic-chat-completion-api 模型,它把 Messages 请求翻译为
OpenAI 形态的 chat completions,并把响应转换回 Anthropic 形状。对于
anthropic 模型,它把请求带上配置的模型名直接透传到上游 /messages 端点。
该桥接支持文本、图像输入、基本函数工具/工具结果和流式 SSE。诸如提示词缓存、
extended thinking 签名、文件和 token 计数等 provider 特性仍取决于上游。
常用模型字段:
| 字段 | 行为 |
|---|---|
| display_name | 人类可读的选择器标签。 |
| slug | 覆盖自动派生的 slug。 |
| index | 排序值。 |
| max_context_limit | 目录上下文窗口与压缩上限。 |
| max_output_tokens | 翻译为 Anthropic 时的默认最大输出。 |
| no_image_support | 为 true 时,目录声明仅文本输入。 |
| supports_search_tool | 为 false 时目录关闭 web_search 工具。 |
| provider_default | 指定 Codex 的 provider default(见下节);不写时取第一个模型。 |
| extra_headers | 合并进请求的可选上游头(模型级优先)。 |
| api_key / api_key_env | 罕见:覆盖 provider 的凭据(同网关分模型计费)。 |
Codex provider default(provider_default)
Codex 会把 catalog 条目按 priority 升序排序:数字最小的条目排在模型列表
第一位,并被当作 provider default —— 当 Codex 请求一个本网关没有的模型时,
它会回退到这个条目。Codex Desktop 自己的辅助请求就依赖这条回退路径:会话标题、
会话描述、turn 摘要、commit message / PR 文案、语音会话标题,都会先请求它内部的
模型 id(当前版本是 gpt-5.6-luna),BYOK 网关无法提供,于是落到 provider
default 上。
因此:
- 不写
provider_default时,models.toml的第一个模型是 provider default(与codex-forge-cli enable选默认对话模型的规则一致); - 想让这些辅助请求固定落到某个便宜模型(例如本机 Ollama 小模型),就在那一行
写
provider_default = true; - 该标记只影响 Codex 的辅助请求与模型列表排序,不会改变
~/.codex/config.toml里的对话模型;同一份文件里只有一个模型会生效 (重复标记时取第一个)。
codex-forge-cli list 会在对应行标注 (codex default)。
历史行为:
priority曾经按降序生成(1000 - index),使models.toml最后一行成为 provider default,辅助请求会被静默发到那个模型。如果因此 在日志里看到意外的模型(例如本机小模型)收到标题/摘要请求,请确认版本已包含 此修复,或用provider_default显式指定落点。
Codex 辅助请求的落点([aux])
先分清两个概念:
- 模型别名(
display_name/slug):同一个上游模型因为订阅计划、计费口径、 服务商不同而起的多个条目,例如yj-mimo-v2.5-pro-tp与yj-mimo-v2.5-pro-sk都指向mimo-v2.5-pro; - helper id(本节):Codex Desktop 自己发起辅助请求时使用的内部模型 id
(当前版本
gpt-5.6-luna,随桌面端版本变化),与你的模型别名无关。
会话标题、会话描述、turn 摘要、commit / PR 文案、语音会话标题都由 Codex Desktop 在临时 thread 里生成,它们总是请求上面那个内部 id。Codex 请求一个网关上不存在的 模型时会在客户端回退到 provider default(见上一节),服务端因此看不到这次请求, 也无法跟随你正在使用/切换的模型。
[aux] 段让 codex-forge 接管这类请求:
| 键 | 默认 | 行为 |
|---|---|---|
| enabled | true | 为 helper id 生成隐藏 catalog 条目(不出现在模型选择器)并按其路由;false 则交给 Codex 默认回退 |
| helper_ids | ["gpt-5.6-luna"] | 覆盖内置的 helper id 列表 |
| model | 不设置 | 设置时固定落到该 slug;不设置时跟随「该 Codex 安装最近一次实际使用的模型」(含会话内切换模型),没有记录时回退到 provider default |
[aux]
enabled = true
helper_ids = ["gpt-5.6-luna"]
# model = "yj-deepseek-flash" # 可选:固定落点(便宜模型 / 固定计费口径)跟随模式按 slug 记录,所以你在 -tp 计划与 -sk 计划之间切换时,辅助请求会跟着
切换,不会把两个计费口径混在一起;想固定到某个口径就直接 model = "yj-…-tp"。
codex-forge-cli list 会打印当前策略:
aux: gpt-5.6-luna -> follows the model this install used last, else m-two注意:
- 「最近使用的模型」按 Codex 安装(
x-codex-turn-metadata.installation_id)在内存里 记录,重启 server 后第一次辅助请求会先回退到 provider default; - 标题类辅助 thread 与你的会话没有父子关联,所以同时开着多个不同模型的会话时, 取的是最近一次使用过的那个;
helper_ids由桌面端版本决定,未覆盖到的 id 仍然走 provider default(不会失效);- 隐藏条目的上下文窗口等元数据借用「它平时会落到的模型」,标题类请求很短,无实际影响。
- 策略是确定性的:固定 → 最近使用 → provider default 三级;不做成本、阈值或" 自动挑便宜模型"之类的判断。
[router] / [[router.candidates]] 段与旧版 JSON 的 router 等价,只是换成
TOML 语法,详见 Auto Router。
Ollama / 本地 OpenAI 兼容 chat 端点
Codex 发送 Responses API。Ollama 和许多本地服务器暴露的是 OpenAI 形态的
/v1/chat/completions。保持 Codex 以 wire_api = "responses" 指向 forge;把
Ollama 配置为 generic-chat-completion-api,forge 就会做 Responses ⇄ chat
completions 翻译:
[providers.ollama]
protocol = "ollama" # normalized to generic-chat-completion-api
base_url = "http://127.0.0.1:11434/v1"
api_key = "ollama"
[[providers.ollama.models]]
display_name = "Ollama Llama 3.2"
model = "llama3.2"protocol = "ollama" 在加载时会被归一化为 generic-chat-completion-api(provider
必须提供 base_url;缺失的 provider 会被跳过)。
重复运行 codex-forge-cli enable、codex-forge-cli app 和 codex-forge-cli model use ...
是幂等的:写入新托管块之前会先移除 forge 托管的顶层键和
[model_providers.codex_forge] 块,因此不会累积重复的 profile/provider 键。
Codex 可能会为其自身产品行为对 OpenAI 模型 slug(如 gpt-5.4-mini)发起小型
后台调用。这些不是 Ollama 路由故障;可用 forge 请求日志确认该 agent 轮次实际选
中的模型。
macOS 上 Codex Desktop 的选择器补丁
Codex Desktop 有一个 Statsig 服务端允许列表(use_hidden_models: true),会隐
藏所有 slug 不在硬编码列表里的模型。自定义目录条目落入隐藏桶,永远不会在选择
器中渲染。
一个单布尔值的 ASAR 补丁可以把允许列表分支关掉,让选择器只检查本地 hidden
标志(本目录从不设置该标志)。在较新的 Codex Desktop 构建中,补丁还会把本地最
近会话加载器从 modelProviders: null 改为 modelProviders: [],使 Desktop 经
由 codex_forge provider 路由时侧边栏仍能显示已有的原生 openai 会话。
组合补丁已在 macOS arm64 上的 Codex Desktop 26.519.41501 /
codex-cli 0.133.0-alpha.1 测试通过。
打补丁前请备份
app.asar和Info.plist。
APP=/Applications/Codex.app
sudo cp -R "$APP" "$APP.unpatched-$(date +%Y%m%d-%H%M%S)"
# 1. Extract the ASAR
cd /tmp && rm -rf codex-asar-patch && mkdir codex-asar-patch && cd codex-asar-patch
npx --yes @electron/asar extract "$APP/Contents/Resources/app.asar" extracted
# 2. Patch the picker filter (single occurrence in tested builds)
PATCH_FILE=$(grep -RIl 'useHiddenModels' extracted/webview/assets/model-queries-*.js | head -n1)
sed -i.bak -E 's/let u=c\.useHiddenModels&&o!==`amazonBedrock`,d;/let u=!1,d;/' "$PATCH_FILE"
diff "$PATCH_FILE.bak" "$PATCH_FILE" || true
rm "$PATCH_FILE.bak"
# 3. Patch the sidebar recent-thread provider filter (single occurrence)
SIDEBAR_FILE=$(grep -RIl 'listRecentThreads' extracted/webview/assets/app-server-manager-signals-*.js | head -n1)
node - "$SIDEBAR_FILE" <<'JS'
const fs = require("node:fs");
const path = process.argv[1];
const text = fs.readFileSync(path, "utf-8");
const old = "listRecentThreads({cursor:e,limit:t}){return this.params.requestClient.sendRequest(`thread/list`,{limit:t,cursor:e,sortKey:this.recentConversationSortKey,modelProviders:null,archived:!1,sourceKinds:ke})}";
const next = "listRecentThreads({cursor:e,limit:t}){return this.params.requestClient.sendRequest(`thread/list`,{limit:t,cursor:e,sortKey:this.recentConversationSortKey,modelProviders:[],archived:!1,sourceKinds:ke})}";
if (text.split(old).length - 1 !== 1) throw new Error("expected one sidebar provider filter occurrence");
fs.writeFileSync(path, text.replace(old, next));
JS
# 4. Repack
npx --yes @electron/asar pack extracted app.asar.new
sudo cp app.asar.new "$APP/Contents/Resources/app.asar"仅做到这一步会让 Codex 下次启动时以 EXC_BREAKPOINT 崩溃。Electron 在
Info.plist 中的 ElectronAsarIntegrity 字段是 ASAR 归档 JSON 头(而非整
个文件)的 SHA-256。重新计算并重新签名:
# 5. Compute new header hash
HEADER_HASH=$(node - "$APP/Contents/Resources/app.asar" <<'JS'
const fs = require("node:fs");
const crypto = require("node:crypto");
const fd = fs.openSync(process.argv[1], "r");
const head = Buffer.alloc(16);
fs.readSync(fd, head, 0, 16, 0);
const jsonSize = head.readUInt32LE(12);
const json = Buffer.alloc(jsonSize);
fs.readSync(fd, json, 0, jsonSize, 16);
fs.closeSync(fd);
console.log(crypto.createHash("sha256").update(json).digest("hex"));
JS
)
echo "new header hash: $HEADER_HASH"
# 6. Patch Info.plist (replaces the hash for Resources/app.asar)
sudo /usr/libexec/PlistBuddy -c \
"Set :ElectronAsarIntegrity:Resources/app.asar:hash $HEADER_HASH" \
"$APP/Contents/Info.plist"
# 7. Ad-hoc re-sign
sudo codesign --force --deep --sign - "$APP"
# 8. Launch
open "$APP"回滚方法:sudo rm -rf "$APP" && sudo mv "$APP.unpatched-…" "$APP"。
CLI 也提供修补/恢复 app.asar 及对应 ASAR 完整性元数据的辅助命令:
codex-forge-cli patch-app
codex-forge-cli restore-app如果 patch-app 之后 Codex 仍然崩溃,用 codex-forge-cli restore-app 恢复,并对照
已安装的 Desktop 构建重新检查手工补丁的定位串。
ChatGPT/Codex 透传
如果 ~/.codex/auth.json 存在且包含 tokens.access_token,forge 会暴露一个合
成的 gpt-5.5 目录条目,直接代理到:
https://chatgpt.com/backend-api/codex/responses该条目仅在令牌存在时才会出现在 /health、/v1/models、codex-forge-cli
list 和生成的 ~/.codex-forge/cli/model_catalog.custom.json 中。一旦你 codex logout 或文件缺
失,该 slug 就不再出现 —— 选择器因此永远不会显示一个首次使用就会 401 的选
项。运行 codex login 获取新令牌后,下一次 codex-forge-cli generate 会自动恢复
该条目。
透传保持 Codex 原生的 /v1/responses 载荷不变,把模型改为 gpt-5.5,并以
Authorization: Bearer <access_token> 发送你的 Codex 访问令牌,同时在存在时
附上 auth.json 中的 ChatGPT 账户 id。它完全绕过配置的 BYOK 路由,使用你的
ChatGPT 订阅额度。
codex-forge-cli generate 之后它就已经在 ~/.codex-forge/cli/model_catalog.custom.json
中。在选择器里选择 GPT-5.5,或运行:
codex-forge-cli model use gpt-5.5旧的本地配置或笔记可能使用 openai-gpt-5-5;服务器接受该前缀作为别名并路由
到同一透传。
路由工作原理
Codex Desktop ── /v1/responses ──▶ codex-forge (127.0.0.1:58767)
│
├── slug "gpt-5.5"
│ └─▶ chatgpt.com/backend-api/codex/responses
│ (Authorization: Bearer <auth.json access_token>)
│
├── provider "openai" / "generic-…"
│ └─▶ baseUrl/chat/completions
│ (Authorization: Bearer apiKey)
│
└── provider "anthropic"
└─▶ baseUrl/messages
(x-api-key: apiKey, anthropic-version: …)forge 把 Codex 的 Responses-API 请求翻译成上游的形状(chat completions 或
Anthropic Messages),并把流式回复翻译回来。来自 Anthropic 形态上游(Claude、
DeepSeek、GLM 等)的 extended-thinking 块通过 reasoning.encrypted_content 条
目往返。
Auto Router(智能路由)
可选地增加一个额外的选择器条目 —— Auto (smart routing)(slug
codex-auto)—— 它会按任务选择合适的模型:简单轮次走便宜模型,困难轮次升
级到最强模型。它完全基于你已配置的模型运行。
每个新任务开始时,forge 让你指定的便宜分类器模型给每个候选打分 0.0–1.0
(一次搞定该任务的可能性),分类器会读取每个候选的简短能力卡片。然后路由
到分数超过 threshold(默认 0.7)的最便宜候选,为该任务的工具调用往返
缓存该决策,并在任何错误时安全回退。分类器永远看不到价格,因此不会偏向昂贵模
型。
在 ~/.codex-forge/server/models.toml 中添加 [router] 段即可开启:
[router]
enabled = true
slug = "codex-auto"
classifier = "minimax-m3" # slug of a cheap configured model
threshold = 0.7
default = "minimax-m3"
cache = true
[[router.candidates]]
slug = "minimax-m3"
cost = 0.3
supports_images = false
card = "Cheap, fast. Single-file edits, codegen, simple refactors."
[[router.candidates]]
slug = "opus"
cost = 5.0
supports_images = true
card = "Frontier. Big multi-file refactors, hard debugging, images."不需要 key 和网络即可端到端验证:
node examples/auto_router_demo.mjs它会启动一个 mock 多后端服务器、以开启路由器的真实 forge 运行,并演示
简单→便宜、中等→中档、困难→强力、图像→支持图像、以及重复任务命中缓存。完整
配置、环境开关(CODEX_FORGE_ROUTER_LOG、CODEX_FORGE_DISABLE_ROUTER …)和故
障行为见 docs/AUTO_ROUTER.md。
工具调用与 agent 循环
Codex 期望 Responses-API 输出条目。大多数 BYOK 上游说 OpenAI chat completions 或 Anthropic Messages。forge 弥合这一差距:
| Codex/Responses 条目 | OpenAI 形态上游 | Anthropic 上游 |
|---|---|---|
| tools: [{type: "function", ...}] | tools: [{type: "function", function: ...}] | tools: [{name, description, input_schema}] |
| function_call 输出条目 | Chat tool_calls[] | tool_use 内容块 |
| function_call_output 输入条目 | Chat role: "tool" 消息 | tool_result 用户内容块 |
| 流式参数增量 | response.function_call_arguments.delta | response.function_call_arguments.delta |
| 并行调用 | 支持处通过 parallel_tool_calls 保留 | 多个 tool_use 块 |
正是这部分让 forge 对真实 Codex 运行有用,而不仅仅是文本聊天。模型可以让 Codex 运行工具,Codex 把工具输出经 forge 送回,上游模型继续同一循环。
原生 Responses 专属工具现在有 BYOK 回退:
| Responses 工具 | Chat/Anthropic 回退 |
|---|---|
| computer_use / computer_use_preview | computer_use 函数,参数 {action, x, y, text, ...} |
| web_search / web_search_preview | web_search 函数,参数 {query, ...} |
| apply_patch | apply_patch 函数,参数 {patch, ...} |
| local_shell / shell | local_shell 函数,参数 {command, ...} |
| Codex MCP 函数 | 作为普通函数工具透传 |
即使上游 API 是 chat-completions 或 Anthropic Messages 而非原生 Responses,BYOK
模型也能留在 Codex agent 循环里。ChatGPT 透传仍是第一方托管工具条目形状的最高
保真路径,但 BYOK 路由不再丢弃这些工具。支持视觉的 BYOK provider 会保留视觉反
馈:Responses input_image、computer_call_output 截图和视觉
function_call_output 载荷会变成 OpenAI chat image_url 部分或 Anthropic
image 块,而不是被压平成文本。
已知边界情况:
- BYOK 原生工具回退依赖 Codex 客户端/运行时识别并执行回退函数调用。forge 翻译 工具 schema 并往返工具输出;它本身不执行 computer、shell、patch 或 MCP 动 作。
- 一些 OpenAI 兼容 provider 宣称支持工具调用但流式输出格式错误的 JSON 参数。 forge 保留增量;provider 仍须在调用结束时给出合法 JSON。
- 如果 provider 忽略
parallel_tool_calls,Codex 可能仍一次只请求一个工具。 这是上游行为,不是目录问题。
web_search 服务端拦截
Codex Desktop 无法为 BYOK 模型执行 web_search 工具。当模型在流式响应中只产出
web_search 调用而无文本内容时,Codex Desktop 会标记调用为 "completed" 但无结果,
导致模型反复调用 web_search → 空白响应无限循环。
forge 在流式和非流式路径上均拦截 web_search_call,在服务端执行搜索(DuckDuckGo),
将结果作为 tool 消息追加到 follow-up 请求中,让模型基于搜索结果合成回答——
所有操作在同一个 SSE 流内完成,对 Codex Desktop 透明。主要特性:
- 递归拦截:若 follow-up 中模型再次调用 web_search,自动执行第二/三轮搜索(上限 3 轮)。
- DSML 过滤:DeepSeek 在 web_search 被剥离后可能以
<||DSML||tool_calls>文本 形式发出工具调用标记;filterDsml()跨 chunk 缓冲并过滤这些标记。 - 完整输出保留:各轮 reasoning / web_search_call / message 通过
completedItems在response.completed事件中一并返回。
会话压缩(Compaction)
Codex 可通过 POST /v1/responses/compact 压缩长会话。
| 路由 | 行为 |
|---|---|
| ChatGPT 透传(gpt-5.5 / openai-gpt-5-5*) | 转发到 ChatGPT 原生的 /backend-api/codex/responses/compact 端点,并把返回的模型元数据改写回请求的 forge slug。 |
| BYOK OpenAI/chat-completions provider | 通过 /chat/completions 发送非流式摘要请求,然后返回 Responses 形状的压缩窗口,其 output 可用作下一次 input。 |
| BYOK Anthropic provider | 通过 /messages 发送非流式压缩请求,然后返回相同的 Responses 形状压缩窗口。 |
BYOK 路径在转发前有意剥离 stream、service_tier 等对 provider 不友好的字
段。它保留实用的 Codex 行为 —— 更小的下一上下文窗口 —— 而不假装第三方
chat API 能发出 OpenAI 那种不透明的加密压缩条目。
Computer use、shell 命令、图像与 MCP
生成的目录声明了 Codex 作为 agent 运行所需的能力:
| 目录字段 | 取值 |
|---|---|
| shell_type | shell_command |
| apply_patch_tool_type | freeform |
| web_search_tool_type | text_and_image |
| supports_parallel_tool_calls | true |
| input_modalities | text,image,除非 noImageSupport: true |
| supports_image_detail_original | noImageSupport: true 时禁用 |
实际含义:
- Shell/文件操作仍由 Codex Desktop/CLI 执行。forge 只翻译模型请求和响应流。
- 图像/截图可以传给接受图像的 provider。Responses
input_image条目、computer_call_output截图和视觉工具输出会保留为 OpenAI chatimage_url部分或 Anthropic image 块。对纯文本上游设置noImageSupport: true,避免 Codex 发送它们无法解析的图像内容。 - Computer-use/原生托管工具在 ChatGPT 透传路径上使用原生 Responses 条目类
型。BYOK chat/Anthropic 路由获得确定性的函数工具回退(
computer_use、web_search、apply_patch、local_shell),从而留在同一 Codex 工具循环中。
Codex Desktop 会向每个模型转发三个通用 MCP 工具:
list_mcp_resourceslist_mcp_resource_templatesread_mcp_resource
它不会把各个 MCP server 的工具压平进函数列表。这是 Codex 客户端行为,不
是 forge 的限制。forge 路由的模型与内置 OpenAI 模型收到同样的 MCP 工具。模型应
调用 list_mcp_resources 来发现可用内容。
提示词捕获与请求拦截
有两个实用的拦截层:
1. 内置请求日志
每个 /v1/responses 请求的入站、转发和响应都会记录到
~/.codex-forge/server/logs/ 下的
分类日志文件中:
| 文件 | 内容 |
|------|------|
| requests.log | 入站请求(模型、工具列表、输入摘要)、转发(slug、URL、prompt 预览)、响应(状态码、响应预览);上游错误也写入此文件 |
| errors.log | 上游错误与异常 |
| lifecycle.log | 服务启动/停止等生命周期事件 |
tail -f ~/.codex-forge/server/logs/requests.log日志使用本地时间 + 毫秒精度时间戳(YYYY-MM-DD HH:mm:ss.SSS),API key 等敏感字段
自动脱敏。流式响应采用累积预览模式,捕获完整响应摘要而非仅首个 chunk。
2. forge 前面的本地提示词捕获代理
需要更深控制时,在 codex-forge 前面放一个小型本地代理,并让 Codex 指向该代
理。该层可以在完整 Responses 请求到达 forge 之前检查它,然后转发到
http://127.0.0.1:58767/v1/responses。
常见用途:
- 注入稳定的 system/developer 前言;
- 在重复样板文本烧掉 token 之前剥离它;
- 把 XML 风格的
<invoke ...>草稿等伪工具文本修复为结构化工具调用,再让 Codex 看到; - 把部分提示词路由到 ChatGPT 透传、其余路由到 BYOK 模型;
- 在日志中对大文件块做脱敏或哈希。
最小 Node.js 转发器形态(仅标准库):
import http from "node:http";
const UPSTREAM = "http://127.0.0.1:58767";
function catchPrompt(body) {
// Keep this deterministic. Codex retries are much easier to debug when the
// same input produces the same transformed payload.
return body;
}
http.createServer(async (req, res) => {
if (req.method === "POST" && req.url === "/v1/responses") {
let raw = "";
for await (const chunk of req) raw += chunk;
const body = catchPrompt(JSON.parse(raw)); // mutate or record the payload
const upstream = await fetch(`${UPSTREAM}/v1/responses`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(body),
});
res.writeHead(upstream.status, { "content-type": upstream.headers.get("content-type") || "application/json" });
res.end(Buffer.from(await upstream.arrayBuffer()));
} else {
res.writeHead(404).end();
}
}).listen(8766, "127.0.0.1");然后启动 Codex 时把 forge provider URL 设为 http://127.0.0.1:8766/v1 而不是
58767。除非你想让所有 BYOK 路由共享同一变更策略,否则把提示词捕获放在
src/translate.mjs 之外。
成本与速度基准测试
正确的基准是真实的 Codex 任务,而不是合成的 hello-world 补全。用同一仓库、同 一提示词、同一模型和同一工具预算对比不同路由。
建议的快速协议:
- 选一个用到工具的真实任务,例如"找到 bug、修改文件、运行聚焦测试"。
- 分别通过你的基线 Codex 路由和
gpt-5.5透传(或你的 BYOK 模型)各跑一 次。 - 记录墙钟时间、请求数、输入 token、输出 token、工具调用次数和最终测试结 果。
- 只对比端到端成功的运行。
实用的 shell 计时包装:
/usr/bin/time -f 'wall=%E cpu=%P max_rss_kb=%M' codex-forge-cli codex -- "your task here"包装器接受并剥离 -- 分隔符。它是可选的,但能防止以 - 开头的任务提示词被
解析为包装器标志。
一份好的报告形如:
Oracle: same repo commit, same prompt, same focused test command
Baseline: 12 requests, 210k input tokens, 19k output tokens, 18m42s, test passed
Forge: 8 requests, 31k input tokens, 11k output tokens, 2m35s, test passed
Result: 6.8x fewer billed input tokens, 7.2x faster wall time具体倍数取决于模型、提示词捕获策略、仓库大小、网络路径和 agent 调用工具的频 率。
命令
codex-forge-cli generate 通过 API 触发目录和配置生成
codex-forge-cli list 查看可用模型列表
codex-forge-cli enable 写入 Codex 配置(需要服务已运行)
codex-forge-cli show 查看工具端状态
codex-forge-cli doctor 只读诊断报告
codex-forge-cli disable 移除托管配置块并恢复原配置
codex-forge-cli model list 列出可用模型
codex-forge-cli model current 查看当前模型
codex-forge-cli model use <slug> 切换默认模型
codex-forge-cli config show 查看服务器连接配置
codex-forge-cli config set <k> <v> 修改连接配置 (host, port, token)
codex-forge-cli codex -- <args> 一次性 CLI 任务
codex-forge-cli app [path] 启动 Codex Desktop
codex-forge-cli patch-app 修补 macOS Codex Desktop 选择器
codex-forge-cli restore-app 恢复 macOS app.asar全局标志:
--settings <path>:仅用于本地 doctor 诊断,不会传给远程 server。--host <host>:工具端连接地址(默认127.0.0.1)。--port <port>:服务端端口(默认58767)。--token <token>:当 server 启用 bearer token 时使用的连接令牌。
patch-app 和 restore-app 始终针对 /Applications/Codex.app,不使用
--settings,在 Windows/Linux 上会以明确错误退出。
初始配置与默认模型选择
enable 和 app 会把 codex-forge 的 provider 配置写入 ~/.codex/config.toml。
写入时需要决定当前激活哪个模型,逻辑如下:
- 显式传入的
model use <slug>/-m <slug>。 - 本地
~/.codex/config.tomlmanaged block 中已有的模型。 - server 返回的第一个可用模型。
server 不返回“客户端 active model”;这个状态只属于 CLI 所在主机。
模型切换
模型切换由 CLI 完成,server 不写 ~/.codex/config.toml,也不重启 Codex
Desktop:
codex-forge-cli model list
codex-forge-cli model current
codex-forge-cli model use <slug>旧的 GET /picker 已移除;POST /api/switch 返回 410 Gone,响应中提示使用
codex-forge-cli model use <slug>。
安全与隐私
- forge 默认绑定
0.0.0.0,可用--host/--port或~/.codex-forge/cli/cli.json修改。 - server 设置
CODEX_FORGE_TOKEN后,除/和/health外的 API 都要求Authorization: Bearer <token>。 - CLI 可用
config set token <token>或--token <token>保存/传入连接令牌。 - 远程直连模式会把该 token 写入 Codex provider 的 bearer 配置;如果不希望把 token 写入 Codex 配置,请使用 TLS 反向代理承担认证。
- API key 留在你的设置文件中;生成的目录不包含它们。
- 请求日志自动脱敏 API key 等敏感字段;日志级别可通过
CODEX_FORGE_LOG_LEVEL环境变量调整。 - 运行时目录默认是
~/.codex-forge/;可用CODEX_FORGE_RUNTIME_DIR指向别处 (支持绝对路径、相对路径或~/…)。用于 CI/容器把运行时状态放在真实 home 之外;测试也用它隔离,避免污染真实目录。 - ChatGPT 透传在请求时读取
~/.codex/auth.json,且只把访问令牌转发给 ChatGPT 的 Codex 端点。 - 如果你在 forge 前面放了提示词捕获代理,该代理控制自己记录什么。请在那里对 大型/私有提示词正文做脱敏或哈希。
已知限制
- Codex 内部和模型选择器打包文件会变。ASAR 补丁天然对版本敏感。
- ChatGPT 透传端点是当前 Codex 构建使用的端点;未来的 Codex 版本可能移动或改 变其形状。
- BYOK provider 的工具调用质量参差不齐。forge 翻译形状;它无法让上游模型可靠 地发出合法的工具调用 JSON。
- 托管的 Responses 专属工具在 ChatGPT 透传路径上保真度最高。BYOK 路由获得普 通函数工具翻译。
bin/下的 POSIX shell 脚本在原生 Windows shell 中不可用,请改用node src/run.mjs ...。
故障排查
Forge 无法启动
codex-forge-cli doctor
codex-forge-cli show
tail -n 80 ~/.codex-forge/server/server.logcodex-forge-cli doctor 输出按分节组织的只读诊断报告。报告混合了两类检查,读的
时候需要区分:
- 本地文件检查:Node.js / Codex CLI 版本、
Local settings(本机上的~/.codex-forge/server/models.toml)、Codex 配置、代理绕过 —— 它们只描述 当前这台主机。 - HTTP 检查:守护进程健康、透传可用性等 —— 它们是对配置的
host发起的 HTTP 调用,描述的是远端或本地 server,而不是本机文件。
当 client 主机指向远程 server 时,本机没有 models.toml 是正常的:server 的
server/models.toml 位于 server 主机,因此 Local settings(该分节在跨主机时
标题为 Local settings (this host only))会把缺失的本地文件报告为 INFO,只有
同机部署时才报告 WARN。
该命令从不写配置、不启动/停止守护进程、不调用模型 provider,也不打印 API
key/令牌。只有检测到硬性 FAIL 时才以 1 退出;警告意在作为本地配置提示。
常见原因:
- Node.js 版本低于 22。
- 端口
58767已被占用。换端口启动:
codex-forge-server start --port 8766
codex-forge-cli --port 8766 enable~/.codex-forge/server/models.toml 缺失
只用 ChatGPT 透传时这没问题,前提是 server 主机 ~/.codex/auth.json 有有效的
tokens.access_token。此时 CLI 生成的目录只包含 gpt-5.5。如果 server 既没有
BYOK 模型也没有有效登录,codex-forge-cli list 会以非零退出:
codex-forge-server start --settings /path/to/my-models.tomlcodex-forge-cli list 以 "No models available" 退出 1
server 既没有在 ~/.codex-forge/server/models.toml 配置模型,
也没有有效的 Codex 登录。二选一:
codex login # populate ~/.codex/auth.json
# or, on the server host
codex-forge-server start --settings /path/to/my-models.tomlCodex 只显示 default
运行:
codex-forge-cli generate
codex-forge-cli model list如果目录里有你的模型但 Desktop 仍隐藏它们,使用 macOS 选择器补丁。在 Windows
Store/MSIX Desktop 上,同一允许列表可能把激活模型改回 gpt-5.5;BYOK 路由请
用 codex-forge-cli codex -- ... / Codex CLI,或使用能在不改写配置的情况下读取自
定义目录的非 MSIX/Desktop 构建。
Windows 代理把回环流量引离了 forge
如果 forge 健康但 codex.exe 返回代理/502 错误,可能是系统代理在拦截
http://127.0.0.1:58767。启动 Codex 前设置大小写两套绕过变量:
$env:NO_PROXY = "127.0.0.1,localhost,::1"
$env:no_proxy = "127.0.0.1,localhost,::1"codex-forge-cli app ... 和 codex-forge-cli codex -- ... 会为子进程自动设置这些条
目。
模型出现但请求 404
所选 slug 不在当前生成的目录中。编辑 server 主机上的
~/.codex-forge/server/models.toml(或 --settings 指定的文件),然后重新生成:
codex-forge-cli generate
codex-forge-cli model list
codex-forge-cli model use <slug>上游返回 401/403
模型设置文件里的 API key 错误、过期或缺少 provider 特定的头。ChatGPT 透传
请刷新 Codex 登录,使 ~/.codex/auth.json 包含有效的
tokens.access_token。
工具调用变成文本
先用 ChatGPT 透传路径确认 Codex 本身在发送工具。如果透传正常但某 BYOK 路由不
行,上游可能缺少原生工具调用支持或发出格式错误的流式参数。查看
~/.codex-forge/server/server.log 中请求的模型和工具数量。
纯文本模型上图像失败
在设置文件中为该模型设置 "noImageSupport": true 并重新生成目录。
流式输出挂起
检查上游在 Codex 之外是否能正常流式输出。然后重启本地守护进程:
codex-forge-server restart
tail -f ~/.codex-forge/server/server.log服务器使用较长的读超时,因为真实的编码 agent 轮次可能流式输出很久;静默挂起 通常是上游/网络/provider 行为。
打补丁后 macOS 应用崩溃
你重新打包了 app.asar 但没更新 ElectronAsarIntegrity 并重新签名,或者补丁
命中了错误的 JavaScript 打包文件。恢复后重试:
codex-forge-cli restore-app
codex-forge-cli patch-app重置生成的 forge 状态
codex-forge-server stop
# 按角色清理:只删本机对应的子目录即可
rm -rf ~/.codex-forge/server # 仅清理本机作为 server 主机时的服务端状态
rm -rf ~/.codex-forge/cli # 仅清理本机作为 client 主机时的工具端状态
# 如需完全清除运行时状态,也可以手动删除整个 ~/.codex-forge/;
# 这会同时移除 server 与 cli 两侧,跨主机部署时需在各自主机上分别执行
codex-forge-cli generate
codex-forge-server start文件结构
src/ Node.js ESM source (server + cli + translation)
dist/ built publishable tree (output of scripts/build.mjs)
bin/codex-forge-cli main entrypoint
bin/codex-forge-server server daemon manager
~/.codex-forge/server/ server host runtime: models.toml, pid, logs, debug (gitignored)
~/.codex-forge/cli/ client host runtime: cli.json, model catalog, backups (gitignored)
tests-node/ node:test suite配置行为:
codex-forge-cli generate、list、show、doctor、codex-forge-cli codex -- ...不会持久修改~/.codex/config.toml。codex-forge-cli enable、codex-forge-cli app和codex-forge-cli model use <slug>会 向~/.codex/config.toml写入托管块。如果已有的顶层 Codex 模型键被顶替, 托管块会记录它们,使 disable 能恢复这些键而不回滚无关的配置修改。codex-forge-cli disable移除托管块、在存在时恢复被顶替的顶层模型键。
许可证
MIT —— 见 LICENSE。
Codex Desktop 是 OpenAI 的商标。本项目与其无关联。
