Claude Code 源码解析
返回目录
界面与状态20

Bridge 与远程集成

IDE 双向通信与远程控制

核心洞察

Bridge 将 Claude Code 从独立 CLI 升级为 IDE 的智能内核

学习

概念讲解与核心设计分析

20.1 Bridge 系统概览

Claude Code 的 bridge/ 目录包含 30 个文件,实现了与 IDE(如 VS Code、JetBrains)的双向通信系统。Bridge 让 Claude Code 可以作为 IDE 的后端引擎运行,IDE 作为前端提供可视化界面。

  • bridgeMain.ts — Bridge 主循环,管理连接建立、心跳检测和消息路由。启动后持续监听来自 IDE 的请求
  • replBridge.ts — REPL 会话桥接,将终端 REPL 的输入输出转发到 IDE 的聊天面板
  • bridgeMessaging.ts — 基于 JSON 的消息协议,定义了请求/响应/通知三种消息类型。支持消息序列化、反序列化和超时控制
  • bridgePermissionCallbacks.ts — 权限委托机制,将文件写入、命令执行等权限确认请求转发给 IDE 端显示对话框,用户在 IDE 中确认后回传结果

20.2 认证与安全

Bridge 通信使用多层安全机制:

  • jwtUtils.ts — JWT 令牌工具,用于 Bridge 连接的身份验证。生成短期令牌、验证签名和过期时间
  • trustedDevice.ts — 设备信任管理,记录和验证已授权的设备指纹。首次连接需要用户确认信任
  • workSecret.ts — 工作区密钥,为每个项目生成唯一的通信密钥,防止跨项目的未授权访问

20.3 远程会话管理

remote/ 目录管理远程 Claude Code 会话:

  • RemoteSessionManager.ts — 远程会话管理器,负责创建、恢复和销毁远程会话。支持断线重连和状态同步
  • SessionsWebSocket.ts — WebSocket 连接管理,在本地客户端和远程 Claude Code 实例之间建立实时双向通道

远程模式允许 Claude Code 在云端服务器运行(更强的计算资源),本地客户端仅负责 UI 渲染和用户交互。

20.4 Teleport — 环境迁移

utils/teleport/(4 个文件)实现环境迁移功能,将本地开发环境"传送"到远程:

  • gitBundle — 将 Git 仓库打包为 bundle 文件,包含所有未推送的提交和未暂存的更改
  • environments — 环境快照管理,记录环境变量、工具版本和配置状态
  • environmentSelection — 环境选择器,让用户选择要迁移的环境配置子集

20.5 Computer Use — 计算机操控

utils/computerUse/(15 个文件)实现了 AI 直接操控计算机的能力:

  • 屏幕控制 — 截图、OCR 文字识别、界面元素定位
  • 应用检测 — 识别当前活动应用程序和窗口状态
  • 输入处理 — 模拟键盘输入、鼠标点击和拖拽操作
  • MCP 服务器 — 将 Computer Use 能力暴露为 MCP 工具,其他代理也可调用

20.6 CLI 传输层

CLI 的通信通过 handlers/(6 个文件)和 transports/(7 个文件)实现:

  • handlers — 请求处理器,分别处理 REPL、Bridge、Agent、远程等不同模式的消息
  • transports — 传输层抽象,支持标准输入输出(stdio)、WebSocket、HTTP SSE 等多种传输协议

20.7 Deep Link 处理

utils/deepLink/ 处理 claude:// 协议的深度链接。用户可以通过浏览器中的链接直接打开 Claude Code 并自动执行特定操作(如打开项目、恢复会话、执行命令)。

架构

模块关系与设计决策

Bridge / IDE / 远程集成架构图

IDE / 客户端层

VS Code 扩展
Bridge Client
JetBrains 插件
Bridge Client
终端 REPL
本地直连
↓ JSON 消息协议 ↓

Bridge 通信层 (bridge/)

bridgeMain
主循环
replBridge
REPL 桥接
messaging
消息协议
permissions
权限委托
JWT 认证
设备信任
工作区密钥

远程 & 传输

remote/
SessionManager
WebSocket
transports/
stdio / WS / SSE
7 个适配器
handlers/
6 种请求处理器

扩展能力

Teleport
环境迁移 (4 files)
gitBundle / 环境快照
Computer Use
屏幕操控 (15 files)
截图 / 输入 / OCR
Deep Link
claude:// 协议
项目/会话直达

源码

3 个关键代码示例

01
Bridge 消息协议与主循环
TypeScript
// bridgeMessaging.ts: JSON 消息协议
type BridgeMessage =
  | BridgeRequest
  | BridgeResponse
  | BridgeNotification;

interface BridgeRequest {
  type: "request";
  id: string;
  method: string;
  params: Record<string, unknown>;
}

interface BridgeResponse {
  type: "response";
  id: string;           // 对应 request.id
  result?: unknown;
  error?: { code: number; message: string };
}

interface BridgeNotification {
  type: "notification";
  method: string;
  params: Record<string, unknown>;
}

// bridgeMain.ts: Bridge 主循环
class BridgeMain {
  private transport: BridgeTransport;
  private handlers = new Map<
    string,
    (params: Record<string, unknown>) => Promise<unknown>
  >();

  async start(port: number): Promise<void> {
    this.transport = await createTransport(port);

    // 注册内置处理器
    this.handlers.set(
      "chat/send", this.handleChatSend.bind(this)
    );
    this.handlers.set(
      "file/read", this.handleFileRead.bind(this)
    );
    this.handlers.set(
      "permission/request",
      this.handlePermission.bind(this)
    );

    // 主消息循环
    while (true) {
      const msg = await this.transport.receive();
      if (msg.type === "request") {
        this.handleRequest(msg);
      }
    }
  }

  private async handleRequest(
    req: BridgeRequest
  ): Promise<void> {
    const handler = this.handlers.get(req.method);
    if (!handler) {
      this.transport.send({
        type: "response",
        id: req.id,
        error: { code: -1, message: "Unknown method" }
      });
      return;
    }

    try {
      const result = await handler(req.params);
      this.transport.send({
        type: "response",
        id: req.id,
        result
      });
    } catch (err) {
      this.transport.send({
        type: "response",
        id: req.id,
        error: {
          code: -1,
          message: String(err)
        }
      });
    }
  }

  // 向 IDE 发送通知(无需响应)
  notify(method: string, params: Record<string, unknown>): void {
    this.transport.send({
      type: "notification",
      method,
      params
    });
  }
}
02
认证与 Teleport 环境迁移
TypeScript
// jwtUtils.ts: JWT 认证工具
interface JwtPayload {
  sub: string;          // 用户 ID
  deviceId: string;     // 设备指纹
  workspaceId: string;  // 工作区 ID
  exp: number;          // 过期时间
  iat: number;          // 签发时间
}

function createJwt(
  payload: JwtPayload,
  secret: string
): string {
  const header = { alg: "HS256", typ: "JWT" };
  const headerB64 = base64url(JSON.stringify(header));
  const payloadB64 = base64url(JSON.stringify(payload));
  const signature = hmacSHA256(
    headerB64 + "." + payloadB64,
    secret
  );
  return headerB64 + "." + payloadB64 + "." + signature;
}

// trustedDevice.ts: 设备信任
class TrustedDeviceManager {
  private trustedDevices: Set<string>;

  isTrusted(deviceId: string): boolean {
    return this.trustedDevices.has(deviceId);
  }

  async trustDevice(deviceId: string): Promise<void> {
    this.trustedDevices.add(deviceId);
    await this.persistToFile();
  }
}

// workSecret.ts: 工作区密钥
function getWorkSecret(
  workspacePath: string
): string {
  const secretPath = join(
    workspacePath, ".claude", "work_secret"
  );
  if (existsSync(secretPath)) {
    return readFileSync(secretPath, "utf-8");
  }
  // 首次使用,生成新密钥
  const secret = randomBytes(32).toString("hex");
  writeFileSync(secretPath, secret);
  return secret;
}

// utils/teleport/gitBundle.ts: Git 仓库打包
async function createGitBundle(
  repoPath: string
): Promise<Buffer> {
  // 1. 收集未推送的提交
  const unpushed = await execGit(
    repoPath, "log", "--oneline", "@{u}..HEAD"
  );

  // 2. 收集未暂存的更改
  const stashResult = await execGit(
    repoPath, "stash", "create"
  );

  // 3. 创建 bundle
  const bundle = await execGit(
    repoPath, "bundle", "create", "-",
    "--all", "--not", "--remotes"
  );

  return bundle;
}

// utils/teleport/environments.ts: 环境快照
interface EnvironmentSnapshot {
  nodeVersion: string;
  pythonVersion: string;
  envVars: Record<string, string>;
  gitConfig: Record<string, string>;
  installedTools: string[];
  timestamp: number;
}

async function captureEnvironment(): Promise<EnvironmentSnapshot> {
  return {
    nodeVersion: process.version,
    pythonVersion: await getCommandOutput("python3 --version"),
    envVars: filterSafeEnvVars(process.env),
    gitConfig: await getGitConfig(),
    installedTools: await detectInstalledTools(),
    timestamp: Date.now()
  };
}
03
Computer Use 与远程会话
TypeScript
// utils/computerUse: AI 计算机操控
interface ScreenCapture {
  width: number;
  height: number;
  data: Buffer;         // PNG 图像数据
  timestamp: number;
}

interface ClickAction {
  type: "click";
  x: number;
  y: number;
  button: "left" | "right" | "middle";
}

interface TypeAction {
  type: "type";
  text: string;
  modifiers?: string[];
}

type ComputerAction =
  | ClickAction
  | TypeAction
  | { type: "screenshot" }
  | { type: "scroll"; x: number; y: number; delta: number };

// Computer Use MCP 服务器
class ComputerUseMcpServer {
  getTools(): ToolDefinition[] {
    return [
      {
        name: "computer_screenshot",
        description: "截取当前屏幕截图",
        inputSchema: { type: "object", properties: {} }
      },
      {
        name: "computer_click",
        description: "在指定坐标点击",
        inputSchema: {
          type: "object",
          properties: {
            x: { type: "number" },
            y: { type: "number" },
            button: { type: "string" }
          }
        }
      },
      {
        name: "computer_type",
        description: "输入文本内容",
        inputSchema: {
          type: "object",
          properties: {
            text: { type: "string" }
          }
        }
      }
    ];
  }

  async handleTool(
    name: string,
    params: Record<string, unknown>
  ): Promise<unknown> {
    switch (name) {
      case "computer_screenshot":
        return await captureScreen();
      case "computer_click":
        return await performClick(
          params.x as number,
          params.y as number,
          (params.button as string) || "left"
        );
      case "computer_type":
        return await typeText(params.text as string);
      default:
        throw new Error("Unknown tool: " + name);
    }
  }
}

// remote/RemoteSessionManager.ts: 远程会话管理
class RemoteSessionManager {
  private sessions = new Map<string, RemoteSession>();

  async createSession(
    config: RemoteConfig
  ): Promise<RemoteSession> {
    // 1. 建立 WebSocket 连接
    const ws = new SessionsWebSocket(config.endpoint);
    await ws.connect();

    // 2. JWT 认证
    const token = createJwt({
      sub: config.userId,
      deviceId: config.deviceId,
      workspaceId: config.workspaceId,
      exp: Date.now() + 3600_000,
      iat: Date.now()
    }, config.secret);
    await ws.authenticate(token);

    // 3. 可选: Teleport 环境
    if (config.teleport) {
      const bundle = await createGitBundle(config.repoPath);
      const env = await captureEnvironment();
      await ws.send("teleport", { bundle, env });
    }

    const session: RemoteSession = {
      id: generateSessionId(),
      ws,
      status: "connected",
      createdAt: Date.now()
    };

    this.sessions.set(session.id, session);
    return session;
  }

  // 断线重连
  async reconnect(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session) throw new Error("Session not found");

    await session.ws.reconnect();
    session.status = "connected";
  }
}

互动

步进式流程演示

互动演示

Bridge 与远程集成交互式演练

Step 1: IDE 建立 Bridge 连接

VS Code 扩展启动时,通过本地端口与 Claude Code 进程建立 Bridge 连接。首次连接需要设备信任确认和 JWT 认证。

VS Code 扩展启动:
  1. 发现本地 Claude Code 进程 (port: 7463)
  2. 生成设备指纹: "device_abc123"
  3. 首次连接: 弹出信任确认对话框
  4. 用户确认 → trustedDevice.trustDevice()
  5. 创建 JWT: { sub: "user", deviceId: "device_abc123" }
  6. Bridge 连接建立 ✔

Step 2: 消息双向通信

IDE 通过 Bridge 发送用户消息,Claude Code 处理后通过通知推送结果。权限确认请求被转发到 IDE 显示对话框。

IDE → Bridge: {
  type: "request", id: "r1",
  method: "chat/send",
  params: { message: "重构 auth 模块" }
}

Bridge → IDE: {
  type: "notification",
  method: "chat/streaming",
  params: { content: "我来分析..." }
}

Bridge → IDE: {
  type: "request", id: "p1",
  method: "permission/request",
  params: { action: "write", path: "src/auth.ts" }
}
IDE → Bridge: { type: "response", id: "p1", result: true }

Step 3: Teleport 环境迁移

用户需要将本地项目迁移到远程强力服务器上运行 Claude Code。Teleport 打包 Git 仓库和环境快照,通过 WebSocket 传送到远程实例。

Teleport 流程:
  1. gitBundle: 打包未推送提交 + 未暂存更改 (2.3MB)
  2. 环境快照: Node 20.x, Python 3.11, 12 个工具
  3. WebSocket 传输 → 远程服务器
  4. 远程恢复: git unbundle + 环境变量设置
  5. 远程 Claude Code 就绪 ✔
  6. 本地 → 远程无缝切换

Step 4: Computer Use 操控

Claude Code 通过 Computer Use MCP 服务器直接操控桌面应用。截图识别界面元素,模拟点击和输入完成自动化任务。

Computer Use 操作序列:
  1. computer_screenshot → 截取桌面 (1920x1080)
  2. AI 分析: 识别到 "Submit" 按钮 at (450, 320)
  3. computer_click(450, 320, "left") → 点击按钮
  4. 等待页面加载...
  5. computer_screenshot → 验证操作结果
  6. computer_type("测试数据") → 填写表单
  7. AI 确认: 任务完成 ✔

相关源文件

bridge/remote/utils/teleport/utils/computerUse/