Codex Mobile 连接 Mac 失败排障:一个守护进程的缺席

有些故障像门外的风声,听起来处处都有嫌疑。手机上显示“无法连接”,电脑端明明开着,局域网也像是通的,于是人很自然地开始怀疑网络、域名、系统服务、移动端设置。排障久了,才发现真正的门并不在眼前。它藏在一个守护进程里,像驿站里漏点的一盏灯,名义上存在,实际上没有照亮路。

这次的问题发生在 Android 手机上的 ChatGPT 连接 Mac 端 Codex 时。手机可以看到 Mac 设备名,但点击后显示“无法连接”,提示“确保这台电脑已唤醒且 Codex 已打开”。Mac 上 Codex.app 确实运行着,手机也能访问局域网里的 Mac 服务。看似万事俱备,只欠一个不肯露面的东风。

本文是重新脱敏后的公开版本。真实设备名、内网 IP、私有组网域名、用户目录、环境 ID 等信息均已替换为占位符。

问题现象

手机端进入 Codex 后,出现过几类状态:

  • 扫码授权后卡在“正在等待桌面应用”。
  • 设备列表能看到 Mac 的 .local 设备名。
  • 点击设备后显示“无法连接”。
  • 移动端切换网络出口配置后,ChatGPT 访问状态发生变化,但 Codex Mobile 仍然无法连接桌面端。

这类问题最麻烦的地方在于,它同时横跨三个层面:移动端访问 OpenAI 的链路、手机到 Mac 的本地网络链路,以及 Mac 端 Codex 自己的远程控制服务。三者任一处有问题,最后都可能长成同一张脸:“无法连接”。

初始误判

误判一:移动端网络出口配置影响局域网

一开始怀疑移动端网络出口配置把 .local 或局域网网段流量接管了。这个判断并非没有道理。Android 上的网络接管机制比较强势,若配置不当,本地地址也可能绕一圈远路,然后死在半途。

后续用一个简单测试排除了这个方向。手机访问 Mac 上的一个局域网服务:

1
http://<Mac 局域网 IP>:<服务端口>

可以成功打开。结论是:手机到 Mac 的局域网链路是通的,移动端网络出口配置不是最终根因。

误判二:用组网域名替代局域网地址

曾尝试访问一个组网工具提供的私有域名:

1
<私有组网域名>

手机浏览器报错:

1
DNS_PROBE_FINISHED_NXDOMAIN

这说明移动端当时没有正确接管该私有域名的解析。这里的教训是:不要在两个网络接管机制之间来回横跳。一个问题还没有定位清楚,又引入第二条虚拟网络,只会让路由表变成一页看似有字、实则失明的符纸。

误判三:Mac 的 Bonjour 或 .local 发现异常

Mac 上曾出现过本地发现服务查询异常:

1
DNSServiceBrowse failed -65563 (Service Not Running)

这很容易让人把矛头指向 Bonjour 或 .local。但后续手机仍能发现 Mac 设备,并且局域网 IP 服务可访问。因此本地发现虽然一度可疑,却不是最终阻断点。

关键证据

证据一:局域网是通的

手机能访问:

1
http://<Mac 局域网 IP>:<服务端口>

这一步很重要。它把问题从“手机能不能连到 Mac”缩小成“Codex Mobile 的特定连接机制为什么失败”。

证据二:Codex.app 已运行,但 remote connection 为 0

Mac 端 Codex 日志里能看到远程控制相关调用:

1
2
remoteControl/enable
connectionCount=0

这说明桌面端 UI 确实尝试启用 remote control,但没有形成有效连接。换句话说,门牌挂出来了,屋里却没人应声。

证据三:直接启动 remote-control 时提示缺少 standalone

执行:

1
/Applications/Codex.app/Contents/Resources/codex remote-control start --json

报错提示:

1
2
3
4
5
6
managed standalone Codex install not found at ~/.codex/packages/standalone/current/codex

This command requires the standalone install managed by the Codex installer,
because the daemon starts and updates app-server from that fixed path.
Install it with:
  curl -fsSL https://chatgpt.com/codex/install.sh | sh

这就是转折点。Codex.app 存在,并不等于 Codex Mobile 依赖的 standalone Codex 已经安装。桌面窗口只是舞台,真正负责远程控制的,是后台的 app-server daemon。

根因

Codex Mobile 不是单纯通过局域网直接连接 Mac。它依赖 OpenAI 的安全 relay 层。手机端和 Mac 端都要能连接 OpenAI relay,Mac 端还必须有可由 daemon 管理的 standalone Codex:

1
~/.codex/packages/standalone/current/codex

本机之前缺少这个组件,导致 remote-control daemon 无法真正启动。手机端即使能发现 Mac,也无法建立控制连接。

修复过程

安装 Codex standalone

执行官方安装脚本:

1
curl -fsSL https://chatgpt.com/codex/install.sh | sh

安装完成后,版本为:

1
Codex CLI 0.133.0

安装路径类似:

1
2
~/.codex/packages/standalone/releases/<version>-aarch64-apple-darwin
~/.codex/packages/standalone/current/codex

在可访问 OpenAI 的网络环境中启动 remote-control daemon

如果 Mac 需要通过特定网络出口访问 OpenAI,先在 shell 环境中完成对应配置。公开记录不写具体出口地址、端口或账号,只保留核心启动命令:

1
~/.codex/packages/standalone/current/codex remote-control start --json

成功返回的关键字段如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
{
  "mode": "daemon",
  "status": "connected",
  "serverName": "<mac-hostname>.local",
  "environmentId": "env_xxx",
  "timedOut": false,
  "daemon": {
    "status": "bootstrapped",
    "backend": "pid",
    "autoUpdateEnabled": true,
    "remoteControlEnabled": true,
    "managedCodexPath": "~/.codex/packages/standalone/current/codex",
    "managedCodexVersion": "0.133.0",
    "socketPath": "~/.codex/app-server-control/app-server-control.sock",
    "cliVersion": "0.133.0",
    "appServerVersion": "0.133.0"
  }
}

再次执行时,可能返回:

1
2
3
4
5
6
7
8
{
  "status": "connected",
  "daemon": {
    "status": "alreadyRunning",
    "managedCodexVersion": "0.133.0",
    "appServerVersion": "0.133.0"
  }
}

看到 "status": "connected",说明 Mac 端 remote-control daemon 已经注册到 OpenAI relay。

下次复现时的最短路径

如果 Codex Mobile 再次显示“无法连接”,先不要从手机网络开始绕圈。先在 Mac 上检查 remote-control daemon:

1
~/.codex/packages/standalone/current/codex remote-control start --json

如果返回:

1
2
3
{
  "status": "connected"
}

说明 Mac 端 relay 服务正常。

如果提示缺少 standalone,则先安装:

1
curl -fsSL https://chatgpt.com/codex/install.sh | sh

安装后再启动 remote-control。

如果 daemon 正常但手机仍无法连接,再按顺序检查:

  • 手机 ChatGPT 是否能访问 OpenAI。
  • Mac Codex.app 是否打开。
  • 手机是否重新扫码授权,而不是使用旧二维码。
  • 手机是否能访问 Mac 局域网 IP,例如 http://<Mac 局域网 IP>:<服务端口>
  • 移动端网络出口配置是否错误接管了局域网流量。

结论

这次问题的真正根因是:

1
Mac 缺少 Codex standalone 组件,remote-control daemon 没有真正启动并注册到 OpenAI relay。

不是:

1
2
3
4
手机网络出口配置必须关闭
局域网不通
必须使用私有组网域名
必须使用分应用代理

修复后的核心状态是:

1
2
3
4
5
{
  "status": "connected",
  "remoteControlEnabled": true,
  "serverName": "<mac-hostname>.local"
}

技术排障里最容易骗人的,是那些“看起来已经打开”的东西。窗口开着,不等于服务在。设备可见,不等于连接成了。像《庄子》里说的“名者,实之宾也”,名字只是客人,真正住在屋里的,是进程、路径、权限和那条最终连上的 relay。