Bridge Layer (VS Code / JetBrains IDE Integration)
ภาพรวมสถาปัตยกรรม
Bridge (src/bridge/, ~31 ไฟล์) เชื่อมต่อ Claude Code CLI sessions กับ IDE extensions ระยะไกล (VS Code, JetBrains) และ claude.ai web UI โดยถูก gate ไว้หลัง feature('BRIDGE_MODE') ซึ่งค่าเริ่มต้นเป็น false
Protocols
Bridge ใช้ two transport generations:
| Version | Read Path | Write Path | Negotiation |
|---|---|---|---|
| v1 (env-based) | WebSocket ไปยัง Session-Ingress (ws(s)://.../v1/session_ingress/ws/{sessionId}) | HTTP POST ไปยัง Session-Ingress | Environments API poll/ack/dispatch |
| v2 (env-less) | SSE stream ผ่าน SSETransport | CCRClient → /worker/* endpoints | Direct POST /v1/code/sessions/{id}/bridge → worker JWT |
ทั้งคู่ wrap อยู่หลัง interface ReplBridgeTransport (replBridgeTransport.ts)
เส้นทาง v1: ลงทะเบียน environment → poll หางาน → acknowledge → spawn session
เส้นทาง v2: สร้าง session → POST /bridge เพื่อรับ JWT → SSE + CCRClient โดยตรง
Authentication
- OAuth tokens — ต้องการ claude.ai subscription (
isClaudeAISubscriber()) - JWT — Session-Ingress tokens (นำหน้าด้วย
sk-ant-si-) พร้อมexpclaimsjwtUtils.tsdecode และกำหนดเวลา refresh เชิงรุกก่อนหมดอายุ - Trusted Device token — header
X-Trusted-Device-Tokenสำหรับ sessions ที่มีความปลอดภัยสูง ลงทะเบียนผ่านtrustedDevice.ts - Environment secret —
WorkSecretที่ encode ด้วย base64url ประกอบด้วยsession_ingress_token,api_base_url, git sources, auth tokens
Dev override: CLAUDE_BRIDGE_OAUTH_TOKEN และ CLAUDE_BRIDGE_BASE_URL
(เฉพาะ ant, process.env.USER_TYPE === 'ant')
Message Flow (IDE ↔ CLI)
IDE / claude.ai ──WebSocket/SSE──→ Session-Ingress ──→ CLI (replBridge)
←── POST / CCRClient writes ──── Session-Ingress ←── CLI
Inbound (server → CLI):
usermessages (prompts จาก web UI) →handleIngressMessage()→ เข้าคิวไปยัง REPLcontrol_request(initialize, set_model, interrupt, set_permission_mode, set_max_thinking_tokens)control_response(การตัดสินใจ permission จาก IDE)
Outbound (CLI → server):
assistantmessages (การตอบของ Claude)usermessages (echo เพื่อ sync)resultmessages (การสิ้นสุด turn)- System events, tool starts, activities
Dedup: BoundedUUIDSet ติดตาม UUIDs ที่ posted/inbound เมื่อเร็วๆ นี้เพื่อปฏิเสธ echoes และการส่งซ้ำ
Lifecycle
- Entitlement check:
isBridgeEnabled()/isBridgeEnabledBlocking()→ GrowthBook gatetengu_ccr_bridge+ OAuth subscriber check - Session creation:
createBridgeSession()→ POST ไปยัง API - Transport init: v1
HybridTransportหรือ v2SSETransport+CCRClient - Message pump: อ่าน inbound ผ่าน transport เขียน outbound ผ่าน batch
- Token refresh: JWT refresh เชิงรุกผ่าน
createTokenRefreshScheduler() - Teardown:
teardown()→ flush pending → ปิด transport → archive session
Spawn modes สำหรับ claude remote-control:
single-session: Session เดียวใน cwd bridge จะปิดเมื่อจบworktree: Persistent server แต่ละ session ได้รับ isolated git worktreesame-dir: Persistent server sessions ใช้ cwd ร่วมกัน
Key Types
BridgeConfig— การตั้งค่า bridge ทั้งหมด (dir, auth, URLs, spawn mode, timeouts)WorkSecret— Decoded work payload (token, API URL, git sources, MCP config)SessionHandle— Running session (kill, activities, stdin, token update)ReplBridgeHandle— REPL bridge API (write messages, control requests, teardown)BridgeState—'ready' | 'connected' | 'reconnecting' | 'failed'SpawnMode—'single-session' | 'worktree' | 'same-dir'
Feature Gate Analysis
Must Work (ทำงานถูกต้องในปัจจุบัน)
gate feature('BRIDGE_MODE') ใน src/shims/bun-bundle.ts ค่าเริ่มต้นเป็น
false (อ่านจาก env var CLAUDE_CODE_BRIDGE_MODE) code paths วิกฤตทั้งหมด
ได้รับการ guard อย่างเหมาะสม:
| Location | Guard |
|---|---|
src/entrypoints/cli.tsx:112 | feature('BRIDGE_MODE') && args[0] === 'remote-control' |
src/main.tsx:2246 | feature('BRIDGE_MODE') && remoteControlOption !== undefined |
src/main.tsx:3866 | if (feature('BRIDGE_MODE')) (Commander subcommand) |
src/hooks/useReplBridge.tsx:79-88 | useAppState calls ทั้งหมด gate ด้วย feature('BRIDGE_MODE') ternary |
src/hooks/useReplBridge.tsx:99 | useEffect body gate ด้วย feature('BRIDGE_MODE') |
src/components/PromptInput/PromptInputFooter.tsx:160 | if (!feature('BRIDGE_MODE')) return null |
src/components/Settings/Config.tsx:930 | feature('BRIDGE_MODE') && isBridgeEnabled() spread |
src/tools/BriefTool/upload.ts:99 | if (feature('BRIDGE_MODE')) |
src/tools/ConfigTool/supportedSettings.ts:153 | feature('BRIDGE_MODE') spread |
Can Defer (bridge functionality เต็มรูปแบบ)
สิ่งต่อไปนี้ทั้งหมดอยู่หลัง feature gate และไม่ active:
runBridgeLoop()— Bridge orchestration เต็มรูปแบบในbridgeMain.tsinitReplBridge()— REPL bridge initializationinitBridgeCore()/initEnvLessBridgeCore()— Transport negotiationcreateBridgeApiClient()— Environments API callsBridgeUI— Bridge status display และ QR codes- Token refresh scheduling
- Multi-session management (worktree mode)
- Permission delegation ไปยัง IDE
Won’t Break
Static imports ของ bridge modules จากนอก src/bridge/ ไม่ crash เพราะ:
- Bridge files ทั้งหมดมีอยู่จริง — อยู่ใน repo imports จึง resolve ได้
- ไม่มี side effects ตอน import — bridge modules นิยาม functions/types แต่ไม่ execute bridge logic เมื่อ import
- Runtime guards — Functions เช่น
isBridgeEnabled()คืนค่าfalseเมื่อfeature('BRIDGE_MODE')เป็น falsegetReplBridgeHandle()คืนค่าnulluseReplBridgeshort-circuits ผ่าน ternary operators
ไฟล์ที่มี static imports ที่ไม่ได้ guard (ปลอดภัยเพราะ files มีอยู่จริง):
src/hooks/useReplBridge.tsx— import types และ utils จาก bridgesrc/components/Settings/Config.tsx— importisBridgeEnabled(คืนค่า false)src/components/PromptInput/PromptInputFooter.tsx— early-returns nullsrc/tools/SendMessageTool/SendMessageTool.ts—getReplBridgeHandle()คืนค่า nullsrc/tools/BriefTool/upload.ts— guard ที่ call sitesrc/commands/logout/logout.tsx—clearTrustedDeviceTokenCacheเป็น no-op
Bridge Stub
สร้าง src/bridge/stub.ts พร้อม:
isBridgeAvailable()→ คืนค่าfalseเสมอnoopBridgeHandle— silent no-opReplBridgeHandlenoopBridgeLogger— silent no-opBridgeLogger
พร้อมใช้สำหรับโค้ดในอนาคตที่ต้องการ fallback ที่ปลอดภัยเมื่อ bridge ปิด
Bridge Activation (งานในอนาคต)
เพื่อเปิดใช้งาน bridge:
1. Environment Variable
export CLAUDE_CODE_BRIDGE_MODE=true
2. Authentication Requirements
- ต้อง login เข้า claude.ai พร้อม active subscription
(
isClaudeAISubscriber()ต้องคืนค่าtrue) - OAuth tokens ได้มาจาก
claude auth login(ต้องการ scopeuser:profile) - GrowthBook gate
tengu_ccr_bridgeต้องเปิดใช้งานสำหรับ org ของ user
3. IDE Extension
- VS Code: Claude Code extension (เชื่อมต่อผ่าน Session-Ingress layer ของ bridge)
- JetBrains: Integration คล้ายกัน (protocol เดียวกัน)
- Web: URL
claude.ai/code?bridge={environmentId}
4. Network / Ports
- Session-Ingress: WebSocket (
wss://) หรือ SSE สำหรับอ่าน HTTPS POST สำหรับเขียน - API base: Production
api.claude.ai(ตั้งค่าผ่าน OAuth config) - Dev overrides:
CLAUDE_BRIDGE_BASE_URL, localhost ใช้ws://และ/v2/paths - QR code แสดงใน terminal ลิงก์ไปยัง
claude.ai/code?bridge={envId}
5. Running Remote Control
# Single session (ปิดเมื่อ session จบ)
claude remote-control
# Named session
claude remote-control "my-project"
# พร้อม spawn mode เฉพาะ (ต้องการ gate tengu_ccr_bridge_multi_session)
claude remote-control --spawn worktree
claude remote-control --spawn same-dir
6. Additional Flags
--remote-control [name]/--rc [name]— เริ่ม REPL พร้อม bridge ที่เปิดไว้ล่วงหน้า--debug-file <path>— เขียน debug log ลงไฟล์--session-id <id>— กลับสู่ session ที่มีอยู่
Chrome Extension Bridge
--claude-in-chrome-mcp (cli.tsx:72)
เปิด Claude-in-Chrome MCP server ผ่าน runClaudeInChromeMcpServer() จาก
src/utils/claudeInChrome/mcpServer.ts ซึ่ง:
- สร้าง
StdioServerTransport(MCP over stdin/stdout) - ใช้ package
@ant/claude-for-chrome-mcpเพื่อสร้าง MCP server - Bridge ระหว่าง Claude Code และ Chrome extension
- รองรับทั้ง native socket (local) และ WebSocket bridge (
wss://bridge.claudeusercontent.com) - Gate ด้วย GrowthBook flag
tengu_copper_bridge(หรือUSER_TYPE=ant)
ไม่ gate ด้วย feature('BRIDGE_MODE') — เป็น subsystem แยกต่างหาก ทำงานเมื่อเรียกด้วย flag --claude-in-chrome-mcp เท่านั้น
--chrome-native-host (cli.tsx:79)
เปิด Chrome Native Messaging Host ผ่าน runChromeNativeHost() จาก
src/utils/claudeInChrome/chromeNativeHost.ts ซึ่ง:
- Implement Chrome’s native messaging protocol (4-byte length prefix + JSON over stdin/stdout)
- สร้าง Unix domain socket server ที่ secure path
- Proxy MCP messages ระหว่าง Chrome extension และ Claude Code instances ในเครื่อง
- มี debug logging ของตัวเองที่
~/.claude/debug/chrome-native-host.txt(เฉพาะ ant)
ไม่ gate ด้วย feature('BRIDGE_MODE') — entry point แยกต่างหาก เปิดใช้เฉพาะเมื่อ Chrome เรียก registered native messaging host binary
Safety
เส้นทาง Chrome ทั้งคู่:
- เป็น dynamic imports — โหลดเฉพาะเมื่อมี flag เฉพาะ
- Return ทันทีหลัง
awaitของตัวเอง — ไม่มี side effects เมื่อ CLI เริ่มปกติ - ไม่สามารถ crash การทำงานปกติได้เพราะเป็น code paths แยกต่างหากทั้งหมด
- ไม่มี dependency กับ bridge feature flag
สรุปการตรวจสอบ
| การตรวจสอบ | สถานะ |
|---|---|
feature('BRIDGE_MODE') คืนค่า false โดยค่าเริ่มต้น | ✅ ตรวจสอบแล้วใน src/shims/bun-bundle.ts |
| Bridge code ไม่ execute เมื่อปิดการใช้งาน | ✅ call sites ทั้งหมดใช้ feature() guard |
| ไม่มี bridge-related errors เมื่อเริ่มต้น | ✅ Imports resolve (files มีอยู่จริง) ไม่มี side effects |
| CLI ทำงานใน terminal-only mode | ✅ Bridge เป็น purely additive |
| Chrome paths ไม่ crash | ✅ Dynamic imports แยกต่างหาก เฉพาะ flags ที่ชัดเจน |
| Stub พร้อมใช้เพื่อความปลอดภัย | ✅ สร้าง src/bridge/stub.ts แล้ว |