Skip to content

Repository files navigation

Codex Remote Bridge

中文默认版。英文版见 README.en.md

Codex Remote Bridge 是一个轻量级、单机、单进程、SQLite 的 Codex Desktop 本地插件。它不是浏览器自动化,也不是独立聊天系统,而是通过 Codex app-server 的 thread/turn 协议,把外部设备接入真实的 Codex 会话。

Codex Remote Bridge flow

适用场景

  • 在手机、平板、另一台电脑或自研客户端中连接本机 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。可选 stdiostandaloneWsdesktopProxy
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_sessions
  • session_devices
  • live_connections
  • session_events
  • audit_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 表。

Controller / Viewer

一个 session 同一时刻只允许一个 controller:

  • controller 可以发送消息和中断 turn。
  • viewer 可以连接、看状态、看流式事件和读历史,但不能发消息。
  • request-control 成功后会广播 controller.changed 和每个设备自己的 session.connected 状态。
  • controller 主动释放、断开、被撤销或租约过期时,bridge 会从在线且可控的 viewer 中自动晋升下一个 controller。

HTTP API

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

推荐客户端流程

  1. 客户端输入 Address / Port / Shared Key
  2. 调用 /api/session/list 获取 Codex 原生 session 列表。
  3. 用户选择已有 sessionId,或在 /api/device/register 中不传 sessionId 新建 session。
  4. /api/device/register 返回 deviceIddeviceTokensessionId
  5. sessionId + deviceId + deviceToken 打开 WebSocket。
  6. 调用 /api/session/history 显示历史记录。
  7. 调用 /api/session/request-control 申请 controller。
  8. controller 调用 /api/session/send 发送消息。
  9. 从 WebSocket 读取 turn.startedmessage.deltamessage.completed
  10. 必要时调用 /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

sessions[] 常用字段

字段 说明
sessionId 客户端使用的 session id,与 Codex 原生 thread id 对齐,但不额外暴露 codex_thread_id 字段。
title Codex 原生名称或预览文本。
source bridge 视角来源,当前为 desktop
codexSource Codex 原生来源,例如 clivscodeappServer
modelProvider Codex 原生模型提供方。
cwd 原生 thread 工作目录。
indexed 是否来自 Codex 原生索引。
activeTurnId bridge 当前记录的 active turn。
controllerDeviceId 当前 controller 设备。
onlineDevices 当前在线设备数量。

WebSocket

连接地址:

GET /ws/session?sessionId=...&deviceId=...&token=...&afterSeq=...

标准化事件:

  • session.connected
  • controller.changed
  • turn.started
  • message.delta
  • message.completed
  • file.markdown.preview
  • device.revoked
  • error

事件结构:

{
  "type": "message.delta",
  "sessionId": "019e...",
  "seq": 12,
  "createdAt": "2026-05-18T08:00:00.000Z",
  "payload": {}
}

afterSeq 只回放 bridge 自己保存的标准化事件。完整会话正文请调用 /api/session/history,由 Codex 原生 thread/read 返回。

Markdown 预览

只支持 .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.transportstandaloneWs 时才需要检查 14555

Get-NetTCPConnection -LocalPort 14555
curl.exe http://127.0.0.1:14555/readyz

面向客户端开发者的最小状态

客户端至少保存:

  • last_address
  • last_port
  • last_session_id
  • device_id
  • device_token

连接时优先走 /api/device/reconnect。如果 token 失效或设备被撤销,再回到 /api/device/register

英文版

See README.en.md.

About

一个可以连接codex中的会话的插件,A plugin that can connect sessions in Codex。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages