中文默认版。英文版见 README.en.md。
Codex Remote Bridge 是一个轻量级、单机、单进程、SQLite 的 Codex Desktop 本地插件。它不是浏览器自动化,也不是独立聊天系统,而是通过 Codex app-server 的 thread/turn 协议,把外部设备接入真实的 Codex 会话。
- 在手机、平板、另一台电脑或自研客户端中连接本机 Codex Desktop。
- 读取 Codex 原生会话列表,选择已有 session 继续对话。
- 新建 Codex 原生 session,并通过 app-server 执行模型对话。
- 将 Codex app-server 的流式事件转成简单稳定的 HTTP/WebSocket 接口。
- 在远程工作目录内安全预览 Markdown 文件。
- 不做浏览器输入框模拟。
- 不暴露
codex_thread_id给客户端。 - 不把
sessionId当权限凭证。 - 不保存明文 device token。
- 不引入 Redis、Postgres、微服务、复杂 RBAC 或独立管理后台。
- 不做跨平台桌面端,也不扩展所有文件类型预览。
- 插件形态:Codex Desktop plugin + MCP server
- Bridge 服务:Node.js + TypeScript + Fastify + WebSocket
- 本地状态:SQLite,使用
better-sqlite3 - Codex 通信:Codex app-server
thread/turn协议 - 默认 app-server transport:
stdio - 配置:
runtime/bridge.config.json
.codex-plugin/ Codex 插件 manifest
assets/ 图标和 README 配图
bridge/ Node.js + TypeScript bridge 服务
prebuilt/ Windows 预构建运行包
scripts/ 安装脚本、daemon、MCP 启动器、无窗口 launcher
runtime/ 安装后本机运行目录
skills/ Codex 使用该插件时的技能说明
install.ps1 便携安装入口
bridge.config.example.json
README.md
README.en.md
安装后插件会集中放在:
%USERPROFILE%\.codex\plugins\codex-remote-bridge\
运行时数据位于安装目录下的 runtime/,包括配置、SQLite、日志和默认 workspace。
从 Git 克隆仓库后,在仓库根目录运行:
powershell -ExecutionPolicy Bypass -File .\install.ps1常用参数:
powershell -ExecutionPolicy Bypass -File .\install.ps1 -WorkspaceRoot "<your-workspace>"
powershell -ExecutionPolicy Bypass -File .\install.ps1 -SharedKey "<your-long-shared-key>"
powershell -ExecutionPolicy Bypass -File .\install.ps1 -CodexExe "<path-to-codex.exe>"
powershell -ExecutionPolicy Bypass -File .\install.ps1 -NodePath "<path-to-node.exe>"
powershell -ExecutionPolicy Bypass -File .\install.ps1 -ForceSourceBuild安装脚本会:
- 复制当前插件仓库到
%USERPROFILE%\.codex\plugins\codex-remote-bridge\ - 清理旧版重复嵌套路径和旧 marketplace 配置
- 生成
runtime/bridge.config.json - 默认解压仓库内的 Windows 预构建 bridge 运行包
- 默认使用用户机器上的
Node.js - 构建无窗口 MCP launcher,避免直接显示
node.exe终端窗口 - 生成插件内
.mcp.json - 注册本地 Codex plugin marketplace,并直接更新
config.toml启用该插件
普通安装需要用户机器上已有可用的 Node.js,但不需要 Visual Studio C++ 或 Windows SDK,因为默认不会在目标机器上编译 better-sqlite3。只有显式传入 -ForceSourceBuild 时,安装脚本才会回到源码构建模式,并要求本机具备可用的 Node.js + npm 环境。
安装结果默认仍然是 marketplace 模式。安装脚本不依赖 codex plugin marketplace 子命令,而是直接维护本地 marketplace 清单和 config.toml,避免因为 Codex CLI 版本差异导致安装中断。
安装脚本会优先选择 Codex Desktop 自带的较新 codex.exe。如果本机有多个 Codex CLI 版本,建议用 -CodexExe 显式指定与当前 Desktop 同版本的可执行文件。
插件 manifest 指向安装目录内生成的 .mcp.json。Codex Desktop 加载该插件的 MCP server 时,会启动:
scripts/launcher/bin/CodexRemoteBridgeMcpLauncher.exe
scripts/bridge-mcp.mjs
scripts/bridge-daemon.mjs
bridge daemon 会提供:
- HTTP/WebSocket bridge,默认
127.0.0.1:8787 - Codex app-server 连接,默认由 adapter 以
stdio方式按需拉起
默认模式下没有独立的 14555 app-server 端口。14555 只在你把 codex.transport 改成 standaloneWs 时才会作为可选 WebSocket app-server 端口使用。
当前实现依赖 Codex Desktop 的插件/MCP 生命周期触发 bridge 启动。它不是 Windows 开机服务,也不会安装计划任务。
主配置文件:
%USERPROFILE%\.codex\plugins\codex-remote-bridge\runtime\bridge.config.json
这个配置在每次 bridge 启动时读取,不只是安装时读取。修改配置后需要重启 bridge/MCP 进程或重启 Codex Desktop。
关键字段:
| 字段 | 说明 |
|---|---|
host |
bridge 监听地址。局域网访问通常设为 0.0.0.0。 |
port |
bridge HTTP/WebSocket 端口,默认 8787。 |
sharedKey |
设备首次登记和受保护管理操作使用的共享 key。 |
workspaceRoot |
远程会话工作目录,也是 Markdown 预览根目录。 |
databasePath |
bridge SQLite 路径。相对路径基于 runtime/ 配置目录解析。 |
maxLiveDevices |
单 session 最大在线设备数,默认 3。 |
maxControllers |
固定为 1。 |
deviceTokenTtlMinutes |
device token 有效期。 |
heartbeatTimeoutSeconds |
WebSocket 心跳和 controller 租约超时。 |
eventRetentionHours |
bridge 标准化事件保留时长。 |
markdownPreviewMaxBytes |
Markdown 预览最大读取字节数。 |
codex.transport |
默认 stdio。可选 stdio、standaloneWs、desktopProxy。 |
codex.codexExe |
Codex CLI 可执行文件路径。 |
codex.codexHome |
Codex home。应指向目标 Desktop 使用的 .codex。 |
codex.appServerUrl |
仅 standaloneWs 模式需要。 |
codex.appServerProxySocket |
仅 desktopProxy 模式需要。 |
示例见 bridge.config.example.json。
bridge 不自建一套独立聊天记录。会话列表、会话历史、新建和续写都走 Codex app-server 原生能力:
- 列表:
thread/list - 新建:
thread/start - 恢复:
thread/resume - 历史:
thread/read - 发送:
turn/start - 中断:
turn/interrupt - 标题/索引物化:
thread/name/set
Codex 原生本地数据包括:
%USERPROFILE%\.codex\sessions\YYYY\MM\DD\rollout-*.jsonl
%USERPROFILE%\.codex\session_index.jsonl
%USERPROFILE%\.codex\state_5.sqlite
bridge 的 SQLite 只保存远程接入和桥接状态:
remote_sessionssession_deviceslive_connectionssession_eventsaudit_logs
新 session 正常通过目标 Desktop 的 CODEX_HOME 和同版本 Codex app-server 创建后,应由 Codex 原生能力生成 rollout、更新 session_index.jsonl,并写入 state_5.sqlite.threads。如果日志中出现 state DB migration checksum mismatch,需要先修复本机 Codex state DB 或统一 Codex CLI/Desktop 版本,否则 Codex app-server 可能只能写 rollout,无法完整维护索引和 threads 表。
一个 session 同一时刻只允许一个 controller:
- controller 可以发送消息和中断 turn。
- viewer 可以连接、看状态、看流式事件和读历史,但不能发消息。
request-control成功后会广播controller.changed和每个设备自己的session.connected状态。- controller 主动释放、断开、被撤销或租约过期时,bridge 会从在线且可控的 viewer 中自动晋升下一个 controller。
GET /health
POST /api/session/list
POST /api/device/register
POST /api/device/reconnect
POST /api/session/history
POST /api/session/request-control
POST /api/session/release-control
POST /api/session/send
POST /api/session/interrupt
POST /api/device/revoke
POST /api/file/preview-md
通用约定:
- 请求和响应均为 UTF-8 JSON。
- 错误形如
{ "error": "message", "details": ... }。 sharedKey用于首次登记、拉取 session 列表和受保护撤销入口。deviceToken只在登记时明文返回一次,bridge 只保存哈希。sessionId不是权限凭证,受保护操作需要deviceId + deviceToken + sessionId。
- 客户端输入
Address / Port / Shared Key。 - 调用
/api/session/list获取 Codex 原生 session 列表。 - 用户选择已有
sessionId,或在/api/device/register中不传sessionId新建 session。 /api/device/register返回deviceId、deviceToken、sessionId。- 用
sessionId + deviceId + deviceToken打开 WebSocket。 - 调用
/api/session/history显示历史记录。 - 调用
/api/session/request-control申请 controller。 - controller 调用
/api/session/send发送消息。 - 从 WebSocket 读取
turn.started、message.delta、message.completed。 - 必要时调用
/api/session/history刷新原生历史。
新建 session 是两步流程:先不传 sessionId 调用 /api/device/register,拿到返回的 sessionId 后再调用 /api/session/send。/api/session/send 不接受空 sessionId。
| 接口 | 请求体 | 返回 | 说明 |
|---|---|---|---|
POST /api/session/list |
sharedKey, limit? |
sessions[] |
通过 Codex thread/list 获取原生 session。 |
POST /api/device/register |
sharedKey, sessionId?, deviceName? |
deviceId, deviceToken, sessionId, codexReady, state |
sessionId 为空则 thread/start 新建;有值则绑定已有原生 thread。 |
POST /api/device/reconnect |
deviceId, deviceToken, sessionId |
allowed, state |
使用已保存 token 重连。 |
POST /api/session/history |
deviceId, deviceToken, sessionId, limit? |
sessionId, lastSeq, events[] |
优先通过 Codex thread/read 读取历史。 |
POST /api/session/request-control |
deviceId, deviceToken, sessionId |
granted, state |
申请成为 controller。 |
POST /api/session/release-control |
deviceId, deviceToken, sessionId |
released, state |
释放 controller,并可能自动晋升 viewer。 |
POST /api/session/send |
deviceId, deviceToken, sessionId, message |
accepted, activeTurnId, state |
只有 controller 可以调用。 |
POST /api/session/interrupt |
deviceId, deviceToken, sessionId |
interrupted, state |
中断当前 active turn。 |
POST /api/device/revoke |
sharedKey 或设备凭据,targetDeviceId? |
revoked, sessionId |
撤销设备,在线连接会收到 device.revoked 并断开。 |
POST /api/file/preview-md |
deviceId, deviceToken, sessionId, path |
kind, path, fileName, summary, content?, truncated |
只允许 workspaceRoot 内 .md。 |
| 字段 | 说明 |
|---|---|
sessionId |
客户端使用的 session id,与 Codex 原生 thread id 对齐,但不额外暴露 codex_thread_id 字段。 |
title |
Codex 原生名称或预览文本。 |
source |
bridge 视角来源,当前为 desktop。 |
codexSource |
Codex 原生来源,例如 cli、vscode、appServer。 |
modelProvider |
Codex 原生模型提供方。 |
cwd |
原生 thread 工作目录。 |
indexed |
是否来自 Codex 原生索引。 |
activeTurnId |
bridge 当前记录的 active turn。 |
controllerDeviceId |
当前 controller 设备。 |
onlineDevices |
当前在线设备数量。 |
连接地址:
GET /ws/session?sessionId=...&deviceId=...&token=...&afterSeq=...
标准化事件:
session.connectedcontroller.changedturn.startedmessage.deltamessage.completedfile.markdown.previewdevice.revokederror
事件结构:
{
"type": "message.delta",
"sessionId": "019e...",
"seq": 12,
"createdAt": "2026-05-18T08:00:00.000Z",
"payload": {}
}afterSeq 只回放 bridge 自己保存的标准化事件。完整会话正文请调用 /api/session/history,由 Codex 原生 thread/read 返回。
只支持 .md:
- 只允许
workspaceRoot内路径。 - 做路径规范化,禁止路径穿越。
- 只按 UTF-8 读取。
- 遵守
markdownPreviewMaxBytes。 - 超长时返回
truncated: true。
其它文件类型只返回路径、文件名和简要摘要,不返回正文预览。
普通安装不需要重新构建 bridge。下面这些命令只属于开发者模式。
安装目录内从源码重建:
cd "$env:USERPROFILE\.codex\plugins\codex-remote-bridge\bridge"
npm ci
npm run build刷新仓库内的 Windows 预构建运行包:
powershell -ExecutionPolicy Bypass -File .\scripts\prepare-portable-runtime.ps1常用检查:
npm run self-check
npm run controller-handoff-check
npm run live-check
npm run reuse-session-check端口与健康检查:
Get-NetTCPConnection -LocalPort 8787
curl.exe http://127.0.0.1:8787/health只有 codex.transport 为 standaloneWs 时才需要检查 14555:
Get-NetTCPConnection -LocalPort 14555
curl.exe http://127.0.0.1:14555/readyz客户端至少保存:
last_addresslast_portlast_session_iddevice_iddevice_token
连接时优先走 /api/device/reconnect。如果 token 失效或设备被撤销,再回到 /api/device/register。
See README.en.md.