The Problem
Developers who work with Claude Code locally need a way to reach a running terminal session from a phone or any remote device. Without a dedicated tunnel they must expose ports manually (ngrok, port‑forwarding) or keep a laptop attached to the same network, which adds friction and security risk.
What This Does
The repository implements a small self‑hosted service that starts a local PTY, creates a Cloudflare (or Tailscale) tunnel, and serves a single‑page web UI that can be opened on a mobile device.
server/index.tshosts the WebSocket control channel, broadcasts messages, and persists session data.server/pty-session.tswraps the PTY process, exposinggetInfo,isExecutable, and other helpers.web/app.js(1797 lines) renders the UI, handles QR‑code display and forwards user input to the WebSocket.- Tunnel providers live under
server/tunnel/(cloudflare.ts,tailscale.ts) and are selected viaserver/config.ts.
All runtime code is TypeScript except the monolithic UI bundle (web/app.js).
How It Is Wired
Execution begins when the CLI (npx claude-code-remote) runs the start script defined in package.json, which imports server/index.ts. The primary entry point is the WebSocket handler:
handleControlMessage(server/index.ts:247) receives commands from the browser, reaches 44 functions across the codebase and is the only place that callsws.send(network outbound).- It frequently invokes
sendControl(called 31 times) which builds a control packet and writes it to the WebSocket. handleControlMessagealso callscleanupSessionHandlers,getInfo(server/pty-session.ts),broadcastToAll, andgetSession.
Session lifecycle is managed by server/session-manager.ts, whose createSession, getSession, and destroySession are referenced by 1–3 callers each. The scheduler (server/scheduler.ts) reads/writes schedule files and performs a cryptographic operation when generating tokens.
Tunnel startup follows a short chain: startTunnel (server/tunnel/index.ts:19) → isAvailable (server/tunnel/cloudflare.ts or tailscale.ts) → start (creates the remote URL). This path touches only three functions.
File‑level responsibilities (ordered by blast radius):
| File | Core duties | External effect |
|---|---|---|
server/index.ts | WebSocket routing, client broadcast | Network (ws.send), file I/O |
server/scheduler.ts | Load/create cron schedules, token crypto | File I/O, crypto |
server/pty-session.ts | PTY process control, info queries | File I/O |
server/tunnel/* | Tunnel provider abstraction, remote URL creation | Network |
server/auth.ts | Token validation middleware | Network |
web/app.js | UI rendering, QR code, input forwarding (1797 LOC) | Browser ↔ WebSocket |
The import graph shows no circular dependencies; the most “unstable” module is server/index (instability = 1) because it imports nine others but is not imported itself, so changes there have the widest impact.
How To Use It
# Clone the exact repo
git clone https://github.com/moses-y/claude-code-remote
cd claude-code-remote
# Install dependencies (Node 18+ required)
npm ci
# Run the service (creates a local server and a Cloudflare tunnel)
npx claude-code-remote
The CLI prints a local URL (e.g., http://localhost:3456) and a remote Cloudflare URL with a QR code. Scanning the code with a phone opens the UI from web/index.html served by the Express server in server/index.ts. No additional configuration files are required; optional cloudflared must be installed separately if remote access is desired (see README).
Real‑World Use
A developer starts the tool on a workstation, scans the QR code on a phone, and runs git status inside the PTY from the mobile UI. Because the tunnel is managed automatically, the session persists across Wi‑Fi changes and can be revisited hours later without re‑authenticating.
Code Health & Issues
- High – Oversized file:
web/app.js(1797 LOC) makes the UI hard to maintain. - Medium – Deep nesting: Same file reaches indentation depth 6.
- Medium – High branching density:
server/activity-detector.tsandserver/process-detector.tseach contain >44 branch points in <150 LOC. - Medium – Missing tests: No test files detected across the repo.
- Medium – No LICENSE: Repository lacks a license file despite the README claiming MIT; legal reuse is ambiguous.
CI is present (.github/workflows/publish.yml), lockfile exists, and no secrets are committed.
The Bottom Line
The project delivers a functional, zero‑config remote terminal for Claude Code with a clear separation between server logic and tunnel providers. However, the monolithic UI bundle, lack of automated tests, and missing license hinder long‑term maintainability. Suitable for teams needing rapid remote access and willing to refactor the front‑end and add tests before scaling.