手机连接 Codex 总是失败?你可能遇到了 WebSocket 的代理问题
如果你正在尝试用手机上的 ChatGPT 连接电脑上的 Codex(比如实现远程控制或跨设备协作),却在 Mac 端看到“无法更新远程状态”的提示,那么这篇文章可能会帮你省下好几个小时的排查时间。
我今天刚好踩了一遍这个坑,从一脸茫然到最终解决,整个过程并不复杂,但需要知道该往哪个方向找问题。下面我会把完整的现象、诊断步骤、解决方法以及几个容易忽略的细节整理出来。

一、先确认正确的连接步骤
在排查问题之前,最好先确认一下操作流程本身有没有遗漏。手机和电脑之间的 Codex 连接,标准步骤是这样的:
-
在 Mac 上打开 Codex 应用 -
进入 Connections(或“连接”)设置项,找到 Set up Codex mobile(设置 Codex 移动端) -
打开 “允许发现并控制此设备” 这个开关 -
在手机 ChatGPT 中,扫描 Mac 上 Codex 显示的二维码 -
确认手机和 Mac 使用的是同一个 ChatGPT 账号,并且位于同一个 workspace(工作区)
理论上,做完这几步之后,手机就能看到并控制 Mac 上的 Codex 了。但如果你的网络环境比较特殊(比如在国内使用代理),那大概率会卡在第 3 步之后——Mac 端一直显示“无法更新远程状态”,手机扫码也没反应。
二、现象是什么?
我遇到的情况是这样的:
- •
Mac 端的 Codex 已经打开了“允许发现并控制此设备” - •
页面提示“无法更新远程状态”(英文可能是 “Unable to update remote status”) - •
手机 ChatGPT 扫码后,始终无法连接本机的 Codex - •
浏览器访问 ChatGPT 网页版是完全正常的,聊天、对话都没问题
也就是说,表面上网络似乎是通的,但 Codex 自己的远程控制链路就是不通。
三、先跑一次诊断
Codex 自带了一个诊断工具,很多人可能还不知道它的存在。在 Mac 的终端里执行下面这个命令:
/Applications/Codex.app/Contents/Resources/codex doctor
这个命令会检查 Codex 的运行状态、网络连通性、代理配置等。在我运行之后,看到了类似这样的输出:
websocket Responses WebSocket timed out
endpoint wss://chatgpt.com/backend-api/...
关键信息是 WebSocket timed out(WebSocket 连接超时)。这说明问题不在 Codex 本身能不能启动,而是它无法通过 WebSocket 协议连接到 ChatGPT 的后端。
这里需要稍微解释一下:浏览器里能正常访问 ChatGPT,靠的是普通的 HTTP/HTTPS 请求。但 Codex 的手机远程控制功能,依赖的是一条 WebSocket 长连接链路(wss://chatgpt.com/backend-api/...)。WebSocket 和普通 HTTP 走的虽然是同一个端口(443),但在网络代理的处理方式上有时会有差异。
四、为什么浏览器能打开,Codex 却连不上?
这是一个容易让人困惑的地方。浏览器通常会自动使用系统的代理设置(比如你开了 Clash、Surge、V2Ray 等工具),所以访问 ChatGPT 没问题。
但 Codex 是一个本地应用,它的内部组件(包括一个叫 app-server 的服务)不会自动继承你在终端或系统偏好里设置的那些代理环境变量。换句话说:
- •
浏览器:能走代理 ✅ - •
Codex app-server:没有代理环境 ❌
codex doctor 的输出也证实了这一点:它显示没有检测到 proxy env vars(代理环境变量)。于是,Codex 试图直接连接 ChatGPT 后端的 WebSocket 端点,结果就是超时。
五、解决办法(实测有效)
解决思路很简单:手动把代理环境变量注入到 Codex 的启动环境里。注意,不是给终端设置代理,而是让整个 launchctl 管理的用户环境都带上代理变量。
在 Mac 上执行以下三行命令(端口号请换成你自己代理软件的实际端口,比如 7897、1087、2017 等):
launchctl setenv HTTP_PROXY http://127.0.0.1:7897
launchctl setenv HTTPS_PROXY http://127.0.0.1:7897
launchctl setenv ALL_PROXY socks5h://127.0.0.1:7897
执行完之后,需要完全退出 Codex(不是只关掉窗口,要确保进程彻底退出,可以在活动监视器里检查一下),然后重新打开 Codex。
再次进入移动端连接流程,在手机 ChatGPT 上重新扫描二维码。这时应该就能正常连接了。
如何确认已经修好了?
再次运行诊断命令:
/Applications/Codex.app/Contents/Resources/codex doctor
如果看到类似这样的输出:
websocket connected (HTTP 101 Switching Protocols)
说明 WebSocket 握手成功了,连接已经畅通。
六、几个容易踩的坑
在实际操作中,有几个地方特别容易让人走弯路,我把它列出来,你可以对照着检查一下。
1. 退出 Cursor 不一定有用
有些人会怀疑是不是 Cursor 编辑器里的旧版 Codex app-server 在干扰,因为 Cursor 也集成了 Codex 功能。我尝试过关掉 Cursor,但问题并没有解决。所以如果你也遇到类似情况,可以先把精力放在代理配置上,不用在 Cursor 上纠结太久。
2. 浏览器能打开 ChatGPT ≠ Codex 能连
这个前面已经说过了,但值得再强调一遍。因为这是最容易被误解的地方。很多人会想:“我网页能用啊,肯定是 Codex 的问题”。但实际上,Codex 需要的是 WebSocket 通,而且需要自己的进程能走代理。
3. WebSocket 是关键
普通的 HTTP 连通性只能保证你能登录、能看页面。远程控制需要的是一个持续的双向通道,这就是 WebSocket 的用处。如果 WebSocket 握手失败,手机就收不到电脑的状态信息,反过来也一样。
4. 同账号、同 workspace 必须一致
这个听起来像是废话,但实际操作中很容易疏忽。有些人手机上登的是个人账号,电脑上登的是团队账号(或者不小心切换了 workspace),这样即使网络通了也连不上。建议在手机 ChatGPT 和 Mac Codex 里都确认一下当前账号和 workspace 名称是否一致。
5. 团队或企业 workspace 可能有管理员开关
如果你用的是团队空间或企业空间,即使账号和 workspace 都对,也可能连不上。因为这类空间的管理员可以在后台关闭 Remote Control(远程控制)权限。如果所有网络配置都正确但仍然失败,可以去问问管理员是否开放了这个功能。
七、常见问题解答(FAQ)
问:我的代理端口不是 7897,怎么知道是多少?
答:查看你使用的代理软件(如 ClashX、Surge、V2RayU、Shadowsocks 等)的配置界面,通常在“设置”或“本地代理”部分会显示 HTTP/HTTPS 和 SOCKS5 的监听端口。常见的有 7890、7897、1087、1080、2017 等。把上面命令里的 7897 换成你实际的端口号即可。
问:设置完 launchctl 环境变量后,需要重启电脑吗?
答:不需要重启电脑,但必须完全退出 Codex 再重新打开。注意是“完全退出”——右键点击 Codex 的 Dock 图标,选择“退出”,或者用 Command+Q 快捷键,确保进程被终止。重新打开后环境变量才会生效。
问:我执行了 launchctl setenv 命令,但还是不行,怎么办?
答:可以按顺序检查以下几点:
-
确认端口号是否正确; -
确认代理软件本身正在运行,并且允许局域网连接(如果不需要局域网连接,至少保证本机代理生效); -
再次运行 codex doctor,看输出中是否显示有 proxy env vars; -
如果没有显示代理变量,可以尝试在终端先执行 echo $HTTP_PROXY,如果终端里没有,说明 launchctl 设置的可能没生效,可以重启一次 Codex 或者考虑用其他方式(比如在 Codex 启动脚本里直接 export)。
问:这些环境变量设置会一直生效吗?会影响其他应用吗?
答:launchctl setenv 设置的是当前用户 launchd 进程的环境变量,会影响通过 launchd 启动的所有新进程(包括 GUI 应用)。如果你不希望这样,可以在使用完 Codex 后撤销。撤销方法见下文。
问:手机和电脑在同一个 Wi-Fi 下吗?
答:是的,通常手机和电脑需要在同一个局域网内。不过 WebSocket 连接主要还是通过 ChatGPT 后端的中继服务器,所以即使在同一 Wi-Fi 下,代理问题仍然会出现。确保 Wi-Fi 没有隔离客户端之间的通信,但这是次要因素。
问:我的系统是 Windows,该怎么设置?
答:原文基于 macOS 环境。如果你用的是 Windows,方法不同。一般需要在系统环境变量中设置 HTTP_PROXY、HTTPS_PROXY 和 ALL_PROXY,或者在 Codex 的快捷方式启动参数中指定。建议参考 Codex 官方文档。
问:如何撤销之前设置的环境变量?
答:如果你后续希望恢复原状,可以执行以下命令清除:
launchctl unsetenv HTTP_PROXY
launchctl unsetenv HTTPS_PROXY
launchctl unsetenv ALL_PROXY
同样需要重新启动 Codex 才会生效。
八、完整的操作流程(步骤清单)
为了方便你跟着做,我把整个解决方案浓缩成一个可操作的清单:
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 确认代理软件的本地端口 | 例如 ClashX 默认 HTTP 端口 7890,SOCKS5 端口 7891 |
| 2 | 在终端执行 launchctl setenv 命令 |
分别设置 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY |
| 3 | 完全退出 Codex | 使用 Command+Q 或活动监视器强制退出 |
| 4 | 重新打开 Codex | 从应用程序文件夹或 Launchpad 启动 |
| 5 | 进入 Connections → Set up Codex mobile | 打开“允许发现并控制此设备” |
| 6 | 运行 codex doctor 检查 WebSocket 状态 |
确认看到 “websocket connected” |
| 7 | 在手机 ChatGPT 中扫码 | 确保同账号、同 workspace |
| 8 | 测试远程控制功能 | 尝试从手机操作电脑上的 Codex |
九、总结与要点回顾
手机连接不上 Codex,大多数情况下并不是 Codex 本身坏了,而是网络链路上出了问题。尤其是当你在中国大陆使用代理时,Codex 的 app-server 组件很可能没有继承到正确的代理环境。
最直接的诊断方法是运行 codex doctor,看输出中是否有 WebSocket timeout。如果有,就说明问题出在代理上。
解决方法也很明确:通过 launchctl setenv 手动为 Codex 注入代理环境变量。注意端口号要跟你代理软件的实际端口一致。
另外别忘了检查账号、workspace 和管理员权限这些非网络因素。
最后放一张成功连接后的示意(来自实际操作截图):

希望这篇文章能帮你少走一些弯路。如果你按照上面的步骤操作后仍然有问题,可以先跑一遍 codex doctor,把输出中的错误信息记录下来,那通常是定位问题的最可靠线索。

