07-bridge-remote
Shared from "Claude-Code" on Inkdown
Bridge & Remote Control
How Claude Code sessions can be controlled from the web (claude.ai/code) and mobile app.
What Is the Bridge?
The bridge system turns a locally-running Claude Code session into a remotely accessible experience. You can:
- Start a session on your laptop
- Open claude.ai/code in your browser
- Watch and interact with the same session in real-time
- Do the same from the Claude mobile app
Two Operational Modes
1. Standalone Bridge (claude remote-control)
Runs as a persistent server that:
0000_start_here_index_and_recommended_reading_order.md
- Registers itself as an "environment" with the server
- Polls for work items
- Spawns child Claude Code processes for each session
- Supports up to 32 concurrent sessions
2. REPL Bridge (/remote-control)
Bridges an already-running REPL session:
- Creates a bridge environment
- Flushes session history to the server
- Maintains a live WebSocket/SSE connection
- Supports crash recovery (resume with
--continue)
Architecture
Core Concepts
Environment
An "environment" is the bridge's identity on the server:
Session
A Claude Code conversation, bound to an environment:
Work Item
A dispatchable unit of work queued to an environment's Redis stream:
Work Secret
Decoded from the work item:
Transport Versions
v1 โ Session Ingress (WebSocket)
v2 โ CCR (Server-Sent Events)
The server decides per-session via secret.use_code_sessions.
Session Spawning
When a work item arrives, the bridge spawns a child process:
Environment variables set on the child:
CLAUDE_CODE_SESSION_ACCESS_TOKEN โ JWT for session auth
CLAUDE_CODE_USE_CCR_V2 โ selects v2 transport
CLAUDE_CODE_WORKER_EPOCH โ worker epoch for v2
Session Handle
The spawner returns a SessionHandle:
Activity Tracking
The spawner parses the child's NDJSON stdout to extract:
- Tool activities: "Editing src/foo.ts", "Running tests..."
- Permission requests
- First user message (for auto-derived session title)
Messaging Protocol
SDK Messages (User โ Session)
Only user type messages are forwarded to the REPL. Other types (tool_result, progress, etc.) are internal and filtered out.
Control Requests (Server โ Session)
Server-initiated requests with a ~10-14s timeout:
| Subtype | Purpose |
|---|
initialize | Session lifecycle handshake |
set_model | Change the AI model |
set_max_thinking_tokens | Adjust thinking budget |
set_permission_mode | Change permission mode |
interrupt | Interrupt current turn |
Control Responses (Session โ Server)
Permission decisions forwarded from the server.
Echo Deduplication
Two bounded UUID sets prevent message echoes:
Flush Gate
Gates message writes during initial history flush to prevent ordering races:
Keep-Alive
A silent keep_alive frame is sent every 120s (configurable via GrowthBook) to prevent upstream proxies from garbage-collecting idle sessions.
REPL Bridge Details
Initialization
Crash Recovery
In perpetual mode, the bridge writes bridge-pointer.json:
On restart with --continue:
- Read pointer file
- Re-register environment with
reuseEnvironmentId
- Reconnect session (same session ID, URL stays valid)
Reconnection Strategy
Strategy 1 โ Reconnect in place:
- Re-register with same environment ID
- Reconnect session
- Session ID stays the same
Strategy 2 โ Fresh session fallback:
- If environment is truly gone (TTL expired)
- Archive old session
- Create new session on fresh environment
Both strategies have a reentrancy guard (reconnectPromise) and cap at 3 attempts.
State Machine
Multi-Session Architecture
Spawn Modes
| Mode | Behavior |
|---|
single-session | One session, bridge exits when done |
same-dir | Persistent server, all sessions share directory |
worktree | Persistent server, each session gets isolated worktree |
Capacity Management
Token Refresh
Proactive scheduler fires ~5 minutes before JWT expires:
- v1: Delivers fresh OAuth token to child via stdin
- v2: Calls
reconnectSession to trigger server-side re-dispatch
Graceful Shutdown
Key Files Reference
| File | Purpose |
|---|
src/bridge/bridgeMain.ts | Standalone bridge server |
src/bridge/replBridge.ts | REPL bridge (existing session) |
src/bridge/bridgeConfig.ts | Auth/URL resolution |
src/bridge/bridgeMessaging.ts | Message parsing and routing |
src/bridge/createSession.ts | Session API client |
src/bridge/sessionRunner.ts | Session spawner |
src/bridge/types.ts | Shared type definitions |
src/bridge/flushGate.ts | Flush gate mechanism |
src/bridge/capacityWake.ts | Capacity wake signals |
src/bridge/workSecret.ts | Work secret decoding |
src/bridge/jwtUtils.ts | JWT utilities |
src/bridge/trustedDevice.ts | Trusted device management |
src/bridge/pollConfig.ts | Poll configuration |
src/bridge/replBridgeTransport.ts | REPL bridge transport wiring |
src/bridge/replBridgeHandle.ts | REPL bridge handle API |
src/remote/ | Remote session management |
src/server/ | Direct connect server |