前言
在 Claude 桌面客户端的 Claude Code 会话里打开 Remote Control(手机或网页远程接管本机会话),一直弹出:
Remote Control failed to connect: Remote Control initialization failed这个问题一直存在,卸载重装客户端也没有解决。奇怪的是,同一台机器的终端里,claude CLI 开 Remote Control 完全正常。账号、网络都是同一套,问题只出在客户端里。本文记录这次排查过程和最终原因:根源是 ~/.claude/settings.json 里的 DISABLE_TELEMETRY=1。
结论先行
只要设置了
DISABLE_TELEMETRY(以及DO_NOT_TRACK、CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC这类关闭遥测的变量),Claude Code 就不会去拉取远程功能开关(GrowthBook),也就拿不到 Remote Control 的开关tengu_ccr_bridge。这时只剩一条兜底判断:本地登录凭证里有 refreshToken,并且是 Pro / Max / Team / Enterprise 订阅,才放行 Remote Control。
终端 CLI 用的是钥匙串里的完整登录,带 refreshToken,所以兜底判断通过。
桌面客户端启动会话时,只把一个 access token 通过环境变量
CLAUDE_CODE_OAUTH_TOKEN传给内置 CLI 子进程,没有 refreshToken,兜底判断失败,Remote Control 就初始化失败。修复:从
~/.claude/settings.json的env里删掉DISABLE_TELEMETRY,然后新建会话(或重启客户端)。
环境
macOS,Claude 桌面客户端 2.42304.0
客户端内置的 Claude Code:2.1.299(位于
~/Library/Application Support/Claude/claude-code/)终端里的 Claude Code:2.1.302
Max 订阅,claude.ai 账号登录
排查过程
1. 看客户端日志
客户端日志在 ~/Library/Logs/Claude/。main.log 里每次点开关只有一句:
[info] Enabling remote control for session local_xxxx
[error] Failed to toggle remote control for local_xxxx: "Remote Control initialization failed"没有任何具体原因。不过 remote-control.log 显示,客户端全局的 Remote Control 开关可以正常注册环境(registered (new) env=...)。这说明账号权限和网络都没问题,失败的只是「单个会话开启 Remote Control」这一步。
2. 会话 Remote Control 是谁在做
用 ps 看客户端的进程树:每个 Code 会话都是一个内置 CLI 子进程,以 stream-json 模式运行:
~/Library/Application Support/Claude/claude-code/2.1.299/.../claude \
--output-format stream-json --input-format stream-json ...客户端开 Remote Control,就是给这个子进程发一条 remote_control 控制请求,由子进程自己去建桥。所以真正报错的是这个内置 CLI。
再对比子进程的环境变量和终端里的差异,最显眼的是认证方式。子进程拿到的是:
CLAUDE_CODE_OAUTH_TOKEN=<access token>
CLAUDE_CODE_OAUTH_SCOPES=user:inference终端 CLI 则直接读钥匙串里的完整登录信息。
3. 用同一个内置 CLI 复现
在终端里直接启动内置的 2.1.299,手动发控制请求:
B=~/Library/Application\ Support/Claude/claude-code/2.1.299/*/claude.app/Contents/MacOS/claude
( echo '{"type":"control_request","request_id":"r1","request":{"subtype":"initialize"}}'
sleep 6
echo '{"type":"control_request","request_id":"r2","request":{"subtype":"remote_control","enabled":true}}'
sleep 15
) | "$B" -p --output-format stream-json --input-format stream-json --verbose --debug-file debug.log用钥匙串登录(不设 token 环境变量):返回
session_url,Remote Control 成功。像客户端一样只给
CLAUDE_CODE_OAUTH_TOKEN:返回Remote Control initialization failed,debug 日志里是:
[bridge:repl] Skipping: bridge not enabled程序是同一个,settings 也是同一套,唯一的变量就是凭证形态。
4. 找到判断逻辑
在内置 CLI 里搜 bridge not enabled,能找到决定 Remote Control 是否可用的函数(代码是压缩过的,下面整理成易读的形式,变量名按 2.1.299):
async function bridgeDisabledReason() {
if (managedSettings.disableRemoteControl) return "managed_disabled";
if (!isFirstParty()) return "not_first_party";
if (isCloudSession()) return "cloud_session";
if (!isClaudeAiAuth()) return "not_subscription_auth";
if (telemetryOffFallback() || await gate("tengu_ccr_bridge")) return null; // 放行
if (!growthBookEnabled()) return "flags_disabled";
return "gate_off";
}
// 遥测关闭时的兜底
function telemetryOffFallback() {
if (growthBookEnabled() || telemetryMode() !== "no-telemetry" || ...) return false;
const creds = readOAuthCredentials();
const sub = creds?.refreshToken ? creds.subscriptionType : null;
return ["pro", "max", "team", "enterprise"].includes(sub);
}
function telemetryMode() {
if (env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC) return "essential-traffic";
if (env.DISABLE_TELEMETRY) return "no-telemetry";
if (env.DO_NOT_TRACK) return "no-telemetry";
return "default";
}逻辑很清楚:
遥测开着时,走远程开关
tengu_ccr_bridge,订阅用户正常放行。设置了
DISABLE_TELEMETRY后,GrowthBook 被关,只能靠兜底判断,而兜底判断要求凭证里有 refreshToken。客户端子进程的凭证来自环境变量,只有 access token,refreshToken 为空,兜底判断返回 false,最终报
flags_disabled,也就是bridge not enabled。
顺带一提:如果设的是 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC,连兜底判断都进不去(模式不是 no-telemetry),终端 CLI 也会用不了 Remote Control。
修复
编辑 ~/.claude/settings.json,把 env 里的 DISABLE_TELEMETRY 删掉。我保留了关闭错误上报的设置:
{
"env": {
"DISABLE_ERROR_REPORTING": "1"
}
}注意:已经开着的会话子进程不会重新读取设置,要在客户端里新建会话或者重启客户端,再打开 Remote Control。改完后验证通过。
另外检查一下 shell 配置(~/.zshrc 等)里有没有 export 这几个变量。客户端从 Dock 启动时一般不继承 shell 环境,但从终端用 open 启动时可能会继承。
小结
「CLI 能用、客户端不能用」时,先想到两者的凭证形态不同:客户端给子进程的是一次性的环境变量 token,不是完整登录。
关闭遥测的变量不只关掉了统计,还会关掉远程功能开关,有些功能会因此走进更严格的兜底判断。
客户端报错信息太笼统时,直接把内置 CLI 拿出来用
stream-json加--debug-file复现,是定位问题最快的办法。
默认评论
Halo系统提供的评论