Claude Code Wiki
首页 深入解析 桥接与集成

Bridge 系统:IDE 双向通信与远程控制

高级 桥接与集成

Bridge 系统是 Claude Code 的核心通信基础设施,实现了 CLI 终端与 Web 界面(claude.ai)之间的双向实时通信。该系统支持两种主要场景:REPL Bridge(在本地 REPL 会话中启用远程控制)和 Remote-Control Bridge(作为持久化工作进程接受远程任务分发)。通过 WebSocket/SSE 传输层和 CCR(Claude Code Runtime)协议,Bridge 系统实现了会话同步、权限委托和远程命令执行,将本地终端转变为可通过 Web 界面远程访问和控制的开发环境。

Sources: bridgeMain.ts, replBridge.ts, types.ts

架构概览与核心概念

Bridge 系统采用客户端-服务器架构,其中 Claude Code CLI 作为客户端,通过 Anthropic 的后端服务与 claude.ai Web 界面通信。系统定义了三个核心概念:Environment(环境,代表一个可接受会话的工作器实例)、Session(会话,单次对话上下文)和 Work(工作项,服务器分发的任务单元)。每个 Environment 通过 OAuth JWT 认证,注册到后端后进入轮询循环,等待 Work 分发;每个 Session 通过 Session Ingress Token(JWT)建立 WebSocket/SSE 连接,实现双向消息流。

┌─────────────────┐
│   claude.ai     │
│   Web UI        │
└────────┬────────┘
         │ HTTP/WebSocket

┌─────────────────┐      Register      ┌──────────────────┐
│  Backend API    │◄───────────────────│  Claude Code CLI │
│  (Anthropic)    │                    │  (Bridge Client) │
│                 │─────── Work ──────►│                  │
└─────────────────┘  (poll response)   └──────────────────┘

                                              │ Spawn

                                      ┌──────────────────┐
                                      │  Child Process   │
                                      │  (claude session)│
                                      └──────────────────┘

传输协议版本对比

Bridge 系统支持两种传输协议版本,通过 GrowthBook 特性开关动态选择:

特性v1 (HybridTransport)v2 (SSE + CCRClient)
读取路径WebSocket (Session-Ingress)SSE (/worker/events/stream)
写入路径POST (Session-Ingress)POST (/worker/events)
认证方式OAuth TokenSession Ingress JWT
心跳机制无内置心跳20s 间隔心跳
序列号不支持SSE Last-Event-ID 支持
状态上报PUT /worker (requires_action)
适用场景单会话 REPL Bridge多会话 Remote-Control Bridge

Sources: replBridgeTransport.ts, types.ts, workSecret.ts

REPL Bridge:本地会话的远程控制

REPL Bridge 在交互式 REPL 会话中启用远程控制功能,允许用户从 claude.ai Web 界面发送消息、查看对话历史并控制权限模式。该模式通过 useReplBridge Hook 在 React 组件挂载时自动初始化,读取 OAuth Token、Git 上下文和会话 ID 后建立与后端的持久连接。

初始化流程与状态管理

REPL Bridge 的初始化流程分为八个阶段:运行时门控检查(GrowthBook 特性开关)、OAuth 认证验证(检查 claude.ai 订阅)、组织策略检查(allow_remote_control 权限)、跨进程退避(避免重复失败)、Token 刷新(主动刷新即将过期的 OAuth Token)、最小版本检查Environment 注册Transport 连接。每个阶段失败都会记录诊断日志并返回 null,成功则返回 ReplBridgeHandle 对象供后续消息写入和远程控制使用。

┌──────────────┐
│ useReplBridge│
│    Hook      │
└──────┬───────┘
       │ useEffect

┌──────────────────┐    No    ┌─────────────┐
│ Gate Check       ├─────────►│ Return null │
│ (BRIDGE_MODE)    │          └─────────────┘
└──────┬───────────┘
       │ Yes

┌──────────────────┐    No    ┌─────────────┐
│ OAuth Token?     ├─────────►│ Return null │
│                  │          └─────────────┘
└──────┬───────────┘
       │ Yes

┌──────────────────┐    No    ┌─────────────┐
│ Policy Allowed?  ├─────────►│ Return null │
│                  │          └─────────────┘
└──────┬───────────┘
       │ Yes

┌──────────────────┐
│ Refresh Token    │
│ (if expiring)    │
└──────┬───────────┘

┌──────────────────┐
│ Register         │
│ Environment      │
└──────┬───────────┘

┌──────────────────┐
│ Connect          │
│ Transport        │
└──────┬───────────┘

┌──────────────────┐
│ ReplBridgeHandle │
└──────────────────┘

ReplBridgeHandle 提供六个核心方法:writeMessages(将本地 Message[] 转换为 SDKMessage[] 并发送)、writeSdkMessages(直接发送 SDKMessage[])、sendControlRequest(发送控制请求如权限提示)、sendControlResponse(响应服务器的控制请求)、sendResult(发送 SDKResult 终止信号)和 teardown(优雅关闭连接)。这些方法通过 initBridgeCore 的注入式设计实现,避免将庞大的依赖树(如命令注册表、React 组件树)拉入 Agent SDK 包。

Sources: initReplBridge.ts, useReplBridge.tsx, replBridge.ts

消息路由与协议转换

Bridge 消息系统处理三种消息类型:用户消息(从 claude.ai 发送到 CLI)、助手消息(从 CLI 发送到 claude.ai)和 控制消息(权限请求、模型切换、模式变更)。bridgeMessaging.ts 提供消息解析、类型守卫和路由逻辑,通过 BoundedUUIDSet(容量为 1000 的 LRU 集合)实现消息去重,避免 WebSocket 重连时重复处理历史消息。

入站消息处理流程(服务器 → CLI):handleIngressMessage 解析原始 WebSocket 数据,首先检查是否为 control_response(权限决策回复),若是则调用 onPermissionResponse 回调;其次检查是否为 control_request(服务器发起的控制请求),若是则调用 onControlRequest 回调;最后验证是否为 SDKMessage 并检查 UUID 是否在 recentPostedUUIDs(回声去重)或 recentInboundUUIDs(重投递去重)中,若为新消息则调用 onInboundMessage 回调注入到 REPL。

出站消息过滤规则isEligibleBridgeMessage 仅转发三类消息:user(用户消息)、assistant(助手消息)和 system + local_command 子类型(斜杠命令系统事件)。虚拟消息(isVirtual: true,REPL 内部调用)、工具结果(tool_result)、进度消息(progress)等内部 REPL 通信被过滤,因为 bridge/SDK 消费者看到的是工具调用/结果的摘要而非内部细节。

Sources: bridgeMessaging.ts, replBridge.ts

权限委托与远程控制

当远程用户(在 claude.ai 上)尝试执行需要权限的操作时,服务器发送 can_use_tool 控制请求到 CLI,CLI 通过 remotePermissionBridge.ts 创建合成助手消息(synthetic assistant message)和工具存根(tool stub),然后在本地渲染权限提示对话框。用户的决策(允许/拒绝/始终允许)通过 sendControlResponse 发送回服务器,服务器将其应用于后续的工具调用。

合成助手消息构造createSyntheticAssistantMessageSDKControlPermissionRequest 中提取 tool_use_idtool_nameinput,构造一个最小化的 AssistantMessage 对象,其 message.idremote-${requestId}usage 字段全为零。该消息仅用于满足 ToolUseConfirm 类型要求,实际的工具调用在远程 CCR 容器中执行。

工具存根实现:当远程 CCR 拥有本地 CLI 未知的工具(如 MCP 工具)时,createToolStub 创建一个最小化的 Tool 对象,其 inputSchema 为空对象、isEnabled 返回 truerenderToolUseMessage 显示输入的前三个键值对、call 方法返回空数据。该存根路由到 FallbackPermissionRequest 组件,确保即使工具定义缺失,权限提示仍能正常显示。

Sources: remotePermissionBridge.ts, bridgeMessaging.ts

Remote-Control Bridge:持久化工作进程

Remote-Control Bridge(通过 /remote-control 命令启动)作为持久化守护进程运行,不断轮询后端服务器的 Work 分发,为每个 Work 项派生一个子 Claude Code 进程执行任务。该模式支持三种 Spawn 模式:single-session(单次会话,Work 完成后 Bridge 退出)、worktree(每个会话获得独立的 Git Worktree)和 same-dir(所有会话共享当前目录)。

主循环与 Work 分发机制

runBridgeLoop 实现 Remote-Control Bridge 的核心轮询逻辑,维护六个关键数据结构:activeSessions(Map<sessionId, SessionHandle>)、sessionStartTimes(Map<sessionId, timestamp>)、sessionWorkIds(Map<sessionId, workId>)、sessionIngressTokens(Map<sessionId, JWT>)、sessionTimers(Map<sessionId, timeout>)和 completedWorkIds(Set)。循环通过 pollForWork API 调用阻塞等待新 Work,收到 Work 后解码 WorkSecret 获取 Session Ingress Token 和 API Base URL,然后调用 createSessionSpawner 派生子进程。

Work Secret 解码与验证decodeWorkSecret 从 base64url 编码的 secret 中解析 JSON 对象,验证 version 字段为 1、session_ingress_token 为非空字符串、api_base_url 存在。该 secret 包含会话的完整启动配置:认证 Token、Git 源信息、MCP 配置、环境变量和 CCR v2 选择器。解码失败抛出错误,触发 Bridge 的错误处理逻辑。

会话派生与生命周期管理createSessionSpawner 返回一个 SessionSpawner 对象,其 spawn 方法使用 child_process.spawn 启动新的 Claude Code 进程,传入 --sdk-url--access-token 和其他运行时参数。子进程的 stdout 通过 readline 接口解析为 JSON 消息,提取工具使用活动并推入 SessionHandle.activities 环形缓冲区(容量 10);stderr 行推入 lastStderr 缓冲区(容量 10)。子进程退出时,SessionHandle.done Promise 解析为 completed(正常退出)、failed(错误退出)或 interrupted(被杀死)。

┌──────────────────────┐
│  runBridgeLoop       │
│  (bridgeMain.ts)     │
└──────────┬───────────┘


    ┌──────────────┐
    │ pollForWork  │◄─────┐
    │  (blocking)  │      │
    └──────┬───────┘      │
           │              │
           ▼              │
    ┌──────────────┐      │
    │ decodeSecret │      │
    └──────┬───────┘      │
           │              │
           ▼              │
    ┌──────────────┐      │
    │ spawnSession │      │
    └──────┬───────┘      │
           │              │
           ▼              │
    ┌──────────────┐      │
    │ await done   │      │
    └──────┬───────┘      │
           │              │
           ▼              │
    ┌──────────────┐      │
    │ ackWork      │──────┘
    └──────────────┘

Sources: bridgeMain.ts, sessionRunner.ts, workSecret.ts

容量管理与会话限制

Remote-Control Bridge 通过 maxSessions 配置参数限制并发会话数量(默认 32),当 activeSessions.size >= maxSessions 时,pollForWork 调用传入 reclaimOlderThanMs 参数(默认 300,000ms = 5 分钟),请求服务器回收超过该时长的闲置 Work。服务器返回的 Work 响应包含 state 字段,若为 reclaimed 则表示该 Work 已被重新分配,Bridge 应跳过处理。

容量唤醒机制createCapacityWake 创建一个 CapacitySignal 对象,包含 waitUntilBelowCapacity 方法(在达到容量上限时阻塞,直到有会话完成)和 notifySessionDone 方法(会话完成时唤醒等待者)。该机制确保 Bridge 在满载时不会继续轮询新 Work,避免服务器端队列积压;同时实现快速响应——会话完成后立即接受新任务,无需等待下一个轮询周期。

会话超时与强制终止:Bridge 为每个会话设置超时定时器(默认 24 小时,通过 --session-timeout 可配置),超时后调用 SessionHandle.forceKill()(发送 SIGKILL)。timedOutSessions Set 记录超时会话 ID,在 onSessionDone 回调中区分超时终止与服务器发起的中断,前者归档为 failed,后者归档为 interrupted

Sources: bridgeMain.ts, capacityWake.ts, types.ts

IDE 集成与 MCP 桥接

Bridge 系统通过 IDE 自动检测MCP 动态配置实现与 IDE 的深度集成。useIDEIntegration Hook 在 REPL 挂载时调用 initializeIdeIntegration,扫描进程树和锁文件以检测运行中的 IDE(VS Code、Cursor、Windsurf、JetBrains 系列),检测成功后将 IDE 作为动态 MCP 服务器添加到配置中,启用文件系统访问、代码补全和诊断信息同步。

IDE 检测机制与锁文件解析

IDE 检测支持两种传输协议:WebSocketws-ide)和 Server-Sent Eventssse-ide)。检测流程分为三步:进程扫描(通过 ps 命令匹配 IDE 进程名,如 Cursor Helpercode.exe)、锁文件读取(从 ~/.cursor/port~/.vscode/port 等路径读取端口号和工作区信息)和 连接验证(尝试建立 WebSocket/SSE 连接并验证响应)。

锁文件格式:IDE 锁文件为 JSON 格式,包含 workspaceFolders(工作区路径数组)、pid(IDE 进程 ID)、ideName(IDE 名称)、transport(传输类型:wssse)、runningInWindows(布尔值,标识是否在 Windows 上运行)和 authToken(可选认证令牌)。DetectedIDEInfo 接口封装这些信息,提供 url(如 ws://localhost:9222)、isValid(连接是否成功)和 ideRunningInWindows(用于 WSL 路径转换)。

自动连接逻辑:当满足以下任一条件时,自动连接到检测到的 IDE:全局配置 autoConnectIdetrue、特性开关 autoConnectIdeFlagtrue、运行在支持的终端(如 VS Code 集成终端)、环境变量 CLAUDE_CODE_SSE_PORT 已设置、或 ideToInstallExtension 参数非空(用户正在安装扩展)。自动连接通过 setDynamicMcpConfig 将 IDE 添加为作用域为 dynamic 的 MCP 服务器。

Sources: useIDEIntegration.tsx, ide.ts, useReplBridge.tsx

MCP 服务器配置与动态作用域

IDE 集成通过 ScopedMcpServerConfig 接口定义 MCP 服务器配置,包含 typews-idesse-ide)、url(WebSocket/SSE 端点)、ideName(IDE 名称)、authToken(认证令牌)、ideRunningInWindows(Windows 运行标识)和 scope(作用域:dynamic 表示运行时动态添加,不持久化到配置文件)。该配置通过 setDynamicMcpConfig 合并到现有的 MCP 配置中,键名为 ide

路径转换:当 IDE 在 Windows 上运行而 CLI 在 WSL 中运行时,WindowsToWSLConverter 将 Windows 路径(如 C:\Users\...)转换为 WSL 路径(如 /mnt/c/Users/...)。转换逻辑通过 checkWSLDistroMatch 验证 WSL 发行版匹配,避免跨发行区访问导致的权限问题。

Sources: useIDEIntegration.tsx, ide.ts

认证与安全机制

Bridge 系统采用多层认证架构,区分 Environment 认证(OAuth Token)和 Session 认证(Session Ingress JWT)。Environment 认证用于注册和轮询 Work,使用 claude.ai 订阅的 OAuth Token;Session 认证用于 WebSocket/SSE 连接和事件上报,使用后端颁发的短期 JWT(包含 session_idworker 角色声明)。

OAuth Token 刷新与 401 重试

createBridgeApiClient 接受 onAuth401 回调参数,在收到 401 响应时调用 handleOAuth401Error 尝试刷新 Token。刷新成功后,API 客户端重试一次原始请求;刷新失败或重试仍返回 401,则抛出 BridgeFatalError 终止 Bridge。该机制与 withRetry.ts 中的 v1/messages 重试逻辑一致,确保短暂的认证服务器故障不会导致 Bridge 退出。

跨进程退避:当 OAuth Token 连续 3 次刷新失败时,getGlobalConfig().bridgeOauthDeadExpiresAt 记录失败的 expiresAt 时间戳,后续进程检测到该时间戳匹配且失败计数 ≥ 3 时,跳过 Bridge 初始化,避免多个进程同时冲击认证服务器。用户执行 /login 后,新 Token 的 expiresAt 不同,退避自动解除。

Trusted Device Token:当服务器启用 elevated auth enforcement 时,Bridge API 调用需要携带 X-Trusted-Device-Token 头,通过 getTrustedDeviceToken 获取。该 Token 在设备信任流程中颁发,存储在安全存储中,用于提升会话的安全层级(SecurityTier=ELEVATED)。

Sources: bridgeApi.ts, initReplBridge.ts, trustedDevice.ts

Session Ingress JWT 与 Worker 注册

CCR v2 传输协议使用 Session Ingress JWT 进行认证,该 JWT 由后端在 Work 分发时生成,包含 session_idworker 角色、exp(过期时间)和 iat(签发时间)声明。JWT 通过 CLAUDE_CODE_SESSION_ACCESS_TOKEN 环境变量传递给子进程,或通过 getAuthToken 闭包(多会话场景)动态获取。

Worker 注册流程registerWorker 函数向 /worker/register 端点发送 POST 请求,携带 Session Ingress JWT 作为 Bearer Token。服务器返回 worker_epoch(单调递增的整数),标识该 Worker 实例的代际。子进程的 CCRClient 在后续所有请求中携带该 epoch,服务器通过 epoch 比较检测僵尸 Worker(旧 epoch 的请求被拒绝)。

JWT 刷新与会话恢复:Session Ingress JWT 的 TTL 约为 4 小时,在 Work 重新分发时刷新(Poll 循环返回新的 Work 响应)。REPL Bridge 在 Transport 重连时调用 createV2ReplTransport 并传入新的 ingressToken,触发重新注册 Worker 并更新 epoch。该设计确保长时间运行的会话不会因 JWT 过期而中断。

Sources: workSecret.ts, replBridgeTransport.ts, jwtUtils.ts

错误处理与恢复策略

Bridge 系统实现了分级错误处理策略,区分可恢复错误(网络故障、临时 5xx)和致命错误(认证失败、策略拒绝)。可恢复错误通过指数退避重试,退避参数包括 connInitialMs(初始延迟 2s)、connCapMs(上限 120s)、connGiveUpMs(放弃阈值 600s);致命错误立即终止 Bridge 并通知用户。

传输层重连与序列号恢复

CCR v2 传输协议通过 SSE 序列号实现断点续传。SSETransport 维护 lastSequenceNum 高水位标记,在 Transport 重连时通过 from_sequence_num 查询参数或 Last-Event-ID 头发送给服务器,服务器从该序列号之后开始重放事件流。该机制避免在 WebSocket 重连时重新发送整个会话历史(可能数千条消息)。

Transport 交换流程:REPL Bridge 在检测到传输层故障(WebSocket 关闭、SSE 错误)时,调用 createV2ReplTransport 创建新 Transport,传入 initialSequenceNum 参数(从旧 Transport 的 getLastSequenceNum() 读取)。新 Transport 的 connect() 方法阻塞直到 SSE 流建立,然后 replBridge.ts 更新 transport 变量并恢复消息处理。

心跳与租约延长:Remote-Control Bridge 通过 heartbeatWork API 定期发送心跳(默认 60s 间隔),延长 Work 项的租约。服务器返回 { lease_extended: boolean, state: string },若 lease_extendedfalse 则表示租约已过期,Work 被重新分配,Bridge 应停止处理该会话。心跳失败(网络错误)触发退避重试,不立即终止会话。

Sources: bridgeMain.ts, replBridgeTransport.ts, replBridge.ts

调试与诊断工具

Bridge 系统提供多层调试支持--debug-file 参数将所有 API 调用、消息传输和状态变更记录到指定文件;bridgeDebug.ts 模块暴露 injectBridgeFault 函数(用于故障注入测试)和 registerBridgeDebugHandle 函数(用于运行时检查 Bridge 状态);diagLogs.ts 模块提供 PII 安全的诊断日志,过滤敏感信息(Token、文件路径)。

故障注入框架wrapApiForFaultInjection 包装 BridgeApiClient,根据 FAULT_INJECT_* 环境变量在特定 API 调用中注入错误。例如,FAULT_INJECT_POLL_TIMEOUT=1 使 pollForWork 超时,FAULT_INJECT_REGISTER_500=1 使注册返回 500 错误。该框架用于测试 Bridge 的错误恢复逻辑,确保退避、重试和降级路径正确工作。

状态可视化:Remote-Control Bridge 通过 bridgeUI.tscreateBridgeLogger 输出实时状态显示,包含 Environment ID、活跃会话数、最近活动和运行时间。状态每秒更新一次(STATUS_UPDATE_INTERVAL_MS = 1000),使用 ANSI 转义码清屏并重绘,提供类似 htop 的交互式监控界面。

Sources: bridgeDebug.ts, debugUtils.ts, bridgeUI.ts

命令接口与用户交互

用户通过 /remote-control 命令(别名 /rc)启动 Remote-Control Bridge,该命令接受可选的 [name] 参数作为会话标题。命令实现位于 src/commands/bridge/bridge.js,加载后调用 bridgeMain.tsrunBridgeLoop 函数,传入配置对象和命令行参数。

命令行参数与配置选项

参数类型默认值说明
--spawnsingle-session | worktree | same-dirsingle-session会话派生模式
--capacitynumber32最大并发会话数
--session-timeoutnumber (ms)86400000 (24h)单会话超时时间
--debug-filestring-调试日志文件路径
--session-idstring-恢复的会话 ID(Backend 格式)
--sandboxbooleanfalse启用沙箱模式
--verbosebooleanfalse详细日志输出

会话恢复机制--session-id 参数用于恢复先前崩溃的会话,传入 Backend 颁发的 environment_id。Bridge 通过 reuseEnvironmentId 配置字段发送该 ID,服务器识别为重连请求,返回相同的 Environment 并重新分发该会话的 Work。该机制用于 crash recovery,确保长时间运行的任务不会因 Bridge 崩溃而丢失。

Sources: commands/bridge/index.ts, bridgeMain.ts, types.ts

性能优化与资源管理

Bridge 系统通过多项优化技术降低资源消耗:消息批处理(writeBatch 方法合并多个消息为单个 HTTP 请求)、环形缓冲区(限制内存使用)、懒加载模块(动态 import 避免包膨胀)和选择性消息转发(过滤内部 REPL 通信)。这些优化确保 Bridge 在长时间运行和高并发场景下保持稳定性能。

消息批处理与写入优化

CCR v2 的 writeBatch 方法通过 SerialBatchEventUploader 将多个 SDKMessage 合并为单个 POST 请求,减少 HTTP 开销。批处理窗口为 100ms 或消息数量达到 50 条(以先到者为准),确保低延迟场景下的快速响应和高吞吐场景下的网络效率。批处理失败时,maxConsecutiveFailures 机制(默认 5 次)触发降级,丢弃后续批次避免内存积压。

环形缓冲区实现SessionHandle.activitieslastStderr 使用固定容量数组实现环形缓冲区,新条目覆盖最旧条目。该设计确保长时间运行的会话不会因活动日志无限增长而耗尽内存,同时保留最近的诊断信息用于错误排查。droppedBatchCount 属性跟踪被丢弃的批次数量,用于监控网络质量。

Sources: sessionRunner.ts, replBridgeTransport.ts

模块懒加载与包大小优化

REPL Bridge 通过动态 import 延迟加载重量级模块:initReplBridge 在运行时 import createSession.ts(避免编译时拉入 OAuth 客户端和模型选择逻辑)、bridgeMessaging.ts(避免拉入消息类型定义)、sessionStorage.ts(避免拉入命令注册表)。该设计使 Agent SDK 包大小减少约 1300 个模块,显著改善冷启动性能。

注入式依赖设计initBridgeCore 接受 BridgeCoreParams 对象,将所有可能引入重量级依赖的功能抽取为回调:createSession(会话创建)、archiveSession(会话归档)、toSDKMessages(消息转换)、onAuth401(OAuth 刷新)、getPollIntervalConfig(轮询配置)。调用者(REPL wrapper 或 Daemon wrapper)提供具体实现,核心模块保持轻量。

Sources: initReplBridge.ts, replBridge.ts


Bridge 系统通过精细的架构设计和多层抽象,实现了 Claude Code 与 claude.ai 之间的无缝双向通信。从 REPL Bridge 的交互式远程控制到 Remote-Control Bridge 的持久化任务分发,从 WebSocket/SSE 传输层到 CCR v2 协议,该系统为开发者提供了强大的远程协作能力。理解 Bridge 系统的内部机制,有助于调试连接问题、优化性能和扩展功能。下一步可探索 LSP 集成:语言服务器协议支持 了解 Bridge 如何与语言服务器协作,或阅读 协调器模式:多代理任务协调 探索 Bridge 在多代理场景中的应用。