如果代码、依赖和开发环境已经放在办公室的一台 Mac 上,换到另一台 MacBook 时,能不能继续让那台电脑干活,自己只负责输入指令、看结果和处理审批?
Codex CLI 的远程终端模式可以这样使用:在办公室主机上运行 codex app-server,客户端通过网络连接。文件操作、命令执行和模型请求都留在主机,客户端提供交互界面。
我已经跑通了局域网连接,也做过一次客户端断线后任务继续执行的验证。外网访问还没有部署,本文后半部分介绍的是可采用的组网路径。
本文整理于 2026 年 10 月 30 日。原始实测使用服务端 Codex 0.166.0、客户端 0.162.1;WebSocket app-server 在官方文档中仍标记为实验性、未受支持的接口。下面保留实测版本的经验,升级后需重新核对参数和行为。地址、口令及私有路径均已改为示例。
代码和任务究竟在哪台电脑上
这里把办公室实际运行 Codex 的 Mac 称为 Server,另一台输入指令的电脑称为客户端。
| 内容 | 所在位置或执行方 |
|---|---|
| 项目文件、依赖、测试、Git 操作 | Server |
| Shell 命令和工具调用 | Server |
| 模型请求 | 由 Server 发出,推理由所配置的模型提供方完成 |
| 输入指令、查看输出、处理审批 | 客户端 |
| 会话历史 | Server 使用的 Codex 用户目录 |
客户端当前所在目录不会自动上传或同步到 Server。在客户端发出创建文件的指令,文件也会写入远端会话的工作目录。
连接后,可以先发一条只读指令确认环境:
执行 hostname、whoami 和 pwd,只读检查,不修改文件。服务启动时的默认目录,与某个会话保存的工作目录也可以不同。判断文件写到哪里,应以当前会话实际返回的 pwd 为准。
先理解 WSS 入口和 app-server 的关系
本次测试使用两个独立进程,连接关系如下:
客户端 Codex CLI
│ WSS:加密连接
▼
Server 的 TLS 入口(端口 4500)
│ WS:只走本机 127.0.0.1:4501
▼
Codex app-server
│ 原生 Token 校验、模型请求、文件和命令执行
▼
Server 上的项目TLS 入口负责加密,连接 Token 仍由 app-server 原生校验。这两个测试进程没有替换原先使用中的 Codex 后台服务。
TLS 入口是额外的部署前提。 app-server 的 WebSocket 监听参数使用 ws://;客户端要连接 wss://,需要由反向代理或独立 TLS 入口完成加密。只把客户端地址中的 ws 改成 wss,不会让明文端口自动支持 TLS。
带 Token 连接非本机地址时,CLI 要求使用 WSS。明文 WS 只适合本机或 SSH 端口转发等场景。下面以 wss://codex.example.com:4500 作为占位地址,实际使用时需要替换为可达、且与服务证书匹配的名称或 IP。
在客户端准备证书和连接 Token
先检查客户端版本和支持的参数:
codex --version
codex --help需要支持 --remote 和 --remote-auth-token-env。本文的客户端连接已在 0.162.1 上验证。
私有 CA 要先核对,再信任
如果 TLS 入口使用公开受信任机构签发的有效证书,通常无需额外配置私有 CA。下面的证书步骤针对本次使用私有 CA 的测试方式。
让 Server 管理员通过可信渠道提供公开 CA 证书和 SHA-256 指纹。证书放到固定目录,可以避免重启或清理临时目录后丢失:
mkdir -p "$HOME/.config/codex-lan"本次 TLS 入口还提供了 /ca.pem 下载地址。这是测试入口自己的约定,不是 app-server 内置的证书下载接口。 如果你的入口也提供该文件,可以这样取回并核对:
CODEX_SERVER_HOST='codex.example.com'
CODEX_CA_SHA256='替换为通过独立可信渠道取得的64位SHA-256值'
curl --noproxy '*' -kfsS \
"https://${CODEX_SERVER_HOST}:4500/ca.pem" \
-o "$HOME/.config/codex-lan/ca.pem"
printf '%s %s\n' \
"$CODEX_CA_SHA256" \
"$HOME/.config/codex-lan/ca.pem" \
| shasum -a 256 -c -只有校验显示 ca.pem: OK 才继续。-k 只用于首次取回公开证书,真实性依靠事先从独立可信渠道收到的指纹;从同一个未验证的下载地址再拿一份指纹,没有建立额外的信任。
后面的 Codex 连接仍正常校验证书。这个测试方式不需要把 CA 安装进系统钥匙串,也不需要把 CA 私钥或服务端私钥复制给客户端。
连接 Token 与模型登录是两回事
Server 的连接 Token 是访问这台 app-server 的凭据,不是模型 API Key,也不是 ChatGPT 密码。它应是专门分配的高强度随机值,不应复用模型服务凭据。
下文假设管理员已通过可信渠道提供 Token,并将其保存到客户端的以下文件中:
~/.config/codex-lan/remote-token该文件只保存 Token 本身,限制读取权限,并放在版本控制之外:
chmod 600 "$HOME/.config/codex-lan/remote-token"示例会从文件读入命令环境变量,不把真实 Token 写进文章或命令参数。
连接远程主机并指定项目
完成地址、TLS、证书和 Token 准备后,在客户端执行:
CODEX_REMOTE_TOKEN="$(cat "$HOME/.config/codex-lan/remote-token")" \
CODEX_CA_CERTIFICATE="$HOME/.config/codex-lan/ca.pem" \
SSL_CERT_FILE="$HOME/.config/codex-lan/ca.pem" \
codex --remote wss://codex.example.com:4500 \
--remote-auth-token-env CODEX_REMOTE_TOKEN原始 0.162.1 测试中,仅设置 CODEX_CA_CERTIFICATE 仍遇到 UnknownIssuer,同时设置 SSL_CERT_FILE 后连接成功,因此这里保留两项设置,并指向同一份 CA 文件。当前官方文档说明前者优先于后者;这条实测经验不代表所有版本都必须同时设置。上述环境变量只作用于当前命令。
如果要为新会话指定项目,在命令中加 -C,传入 Server 上的绝对路径:
CODEX_REMOTE_TOKEN="$(cat "$HOME/.config/codex-lan/remote-token")" \
CODEX_CA_CERTIFICATE="$HOME/.config/codex-lan/ca.pem" \
SSL_CERT_FILE="$HOME/.config/codex-lan/ca.pem" \
codex --remote wss://codex.example.com:4500 \
--remote-auth-token-env CODEX_REMOTE_TOKEN \
-C /absolute/path/on/server/my-project这个目录需要提前存在于 Server。客户端上有同名文件夹,不意味着远端也有这份代码;恢复已有会话时,还要留意是否沿用了该会话保存的目录。
开发服务器也运行在远端。如果它只监听 Server 的 127.0.0.1,客户端浏览器无法直接打开。预览页面需要另外配置端口转发或合适的监听方式,Codex 连接成功并不意味着项目的所有端口都能远程访问。
退出后,怎样恢复远程会话
会话历史保存在 Server 的 Codex 用户目录中,正常保存的历史不会因客户端退出而删除。恢复时仍然要带上远程地址和鉴权参数:
CODEX_REMOTE_TOKEN="$(cat "$HOME/.config/codex-lan/remote-token")" \
CODEX_CA_CERTIFICATE="$HOME/.config/codex-lan/ca.pem" \
SSL_CERT_FILE="$HOME/.config/codex-lan/ca.pem" \
codex resume --all \
--remote wss://codex.example.com:4500 \
--remote-auth-token-env CODEX_REMOTE_TOKEN用方向键选择会话,再按回车恢复。--all 用于显示所有目录的候选会话,避免因为目录过滤找不到目标。如果询问使用哪个目录,应根据需要选择原会话目录。
也可以先在原会话中用 /status 记下 Session ID,之后把 resume --all 换成 resume SESSION_ID,直接恢复指定会话。
不要省略远程地址,只在客户端执行 codex resume,否则可能打开客户端本地的历史。多个项目共用一台 Server 时,也不宜只凭 --last 猜测要恢复哪个会话。
客户端断网,任务还会继续吗
需要区分“客户端暂时看不到输出”和“远端任务已经被中断”。
如果请求已被 Server 接收,只是客户端与 Server 之间的网络断开,而 Server 仍然醒着、进程正常且能访问模型服务,任务可以继续运行。
原始实验做过一次实际验证:Server 执行一个等待 45 秒的命令;执行途中直接断开客户端 TCP 连接,没有发送停止指令。断线后,第一条命令完成,Codex 还发起并完成了第二次独立工具调用,最终该轮状态为 completed。该实验使用服务端 0.166.0。
这证明了本次纯连接断开场景中的继续执行能力,不能扩大为任意故障下都保证完成:
| 情况 | 应怎样理解 |
|---|---|
| 客户端断网,Server 正常 | 已接收的任务可继续;本次已验证后续工具调用也能完成 |
| 请求尚未送达 Server 就断网 | 任务可能尚未启动,需要重连检查 |
| 等待审批、提问或客户端动态工具结果 | 可能等待或失败,不能保证无人值守完成 |
主动发送停止指令或 turn/interrupt | 会请求中断当前任务 |
| 按 Ctrl+C 或正常退出客户端 | 可能发送中断或退订,不能当作本次验证过的纯断网 |
| Server 睡眠、关机或 Codex 进程退出 | 不能继续正常执行;历史存在不等于任务自动恢复 |
| 模型网络、额度、凭据或工具执行出错 | 仍可能让任务失败,WSS 和 VPN 无法替代这些依赖 |
重连后,先恢复原会话,检查任务状态、工具输出和文件结果。如果仍在运行,就继续观察;如果已经失败,再从完成的位置继续。尤其是部署、上传或写入外部系统,不要在未确认状态前直接重复发送原任务。
必须持续运行并保留输出的构建、下载等任务,可以在 Server 中用 tmux 或任务管理工具执行并保存日志。但它们不会替 Codex 回答审批,也不能抵御 Server 关机。
在办公室以外,怎样访问同一台 Server
优先考虑 VPN 或 Tailscale 这类私有组网。OpenAI 官方也建议用 VPN 或组网工具连接远端,而不是把 app-server 直接暴露到互联网。
这部分尚未在本环境部署,下面是两种可选路径。
沿用办公室局域网地址
如果希望保留原来的局域网连接地址,可以使用 Tailscale 子网路由:
- 在办公室的常开设备与外出 MacBook 上安装并接入同一个私有网络。
- 配置办公室设备发布所需的主机路由或实际网段。
- 在管理端批准路由,并用访问规则限制允许访问的设备和端口。
- 确认客户端能经过该路由访问 TLS 入口。
- 继续使用对应地址、证书和远程恢复命令。
仅仅在两端安装 Tailscale,不会自动让办公室原有内网地址可达。路由需要配置和批准;外出网络若使用重叠网段,还要检查路由冲突。
改用主机的私有组网地址或名称
也可以直接连接办公室主机的 Tailscale 地址或名称,减少对原局域网路由的依赖。
这时要相应调整 TLS 入口监听范围,并为新的名称或 IP 签发匹配的服务证书。不能只改客户端地址,就假定原证书对新地址仍然有效。
如果使用桌面 App,官方还提供在 Connections 设置中添加 SSH 主机、选择远程项目的路径。它与本文的原生 CLI WSS 连接不同;本文没有验证桌面 App 能直接填写这里的 WSS 地址。具体入口和可用性以 App 版本及账号开放情况为准。
Server 端需要预先准备什么
办公室主机需要接通电源、保持清醒,并保持网络及模型服务可用。显示器可以熄屏,但主机睡眠会影响执行;笔记本合盖也可能进入睡眠。切换网络后,要重新确认地址、监听范围和证书匹配关系。
原始测试使用手动启动的后台进程,没有配置开机自启。重启后需要重新启动服务,历史记录不会让未完成的任务自动续跑。
以下是 app-server 的服务端命令形态。它假设 Codex 已安装并完成模型鉴权,专用 Token 文件已准备好,TLS 入口也已另行配置;不包含证书签发和 TLS 代理的完整部署脚本。
先在 Server 上检查端口归属,避免重复启动或干扰其他会话:
lsof -nP -iTCP:4500 -iTCP:4501 -sTCP:LISTEN确认测试服务已经停止、端口空闲后,才启动一个新的 app-server:
codex app-server \
--listen ws://127.0.0.1:4501 \
--ws-auth capability-token \
--ws-token-file "$HOME/.config/codex-server/remote-token"这里的 $HOME 属于 Server。服务端文件中的 Token 应与发给客户端的连接 Token 一致;它与 Server 访问模型所使用的凭据分开管理。
TLS 入口应把已授权客户端的加密连接转发到这个本机端口,后端 app-server 自己执行 Token 检查。长期使用时还要安排进程托管、开机启动、日志和证书续签,并限制网络访问范围。
证书有效期应从实际部署的证书中读取。例如,在 Server 上执行以下命令,查看你保存的服务证书到期时间:
openssl x509 -in /path/to/server.pem -noout -enddate公开 CA 证书可以交给客户端,CA 私钥、服务端私钥和模型凭据留在 Server。CA 更换后,客户端也要重新取得并核对公开证书。
常见错误怎么查
| 错误或现象 | 检查方向 |
|---|---|
| 提示远程鉴权只允许 WSS 或 loopback WS | 非本机带 Token 连接使用 WSS,确认不是明文入口 |
InvalidContentType 或 received corrupt message | 检查是否把 WSS 连到了明文 WS 端口 |
UnknownIssuer | 检查 CA 路径;参考上文实测版本的两个证书环境变量设置 |
| 证书名称或 IP 不匹配 | 连接地址必须包含在服务证书中,换地址后要更新证书 |
| 证书过期 | 服务端续签;CA 变化时,客户端重新获取并核对 |
401 Unauthorized | 检查 Token 文件、环境变量名称和两端值是否一致 |
| 连接被拒绝或超时 | 检查主机状态、进程、地址、防火墙与 VPN 路由 |
| 恢复列表找不到会话 | 带上远程地址,使用 resume --all,确认 Server 的 Codex 用户环境一致 |
远程使用最关键的是执行位置和状态:代码属于哪台主机、会话保存在哪里、TLS 与 Token 是否正确配置、断线后任务到底完成到哪一步。把这些边界分清,换设备时才能继续使用同一份开发环境。