Claude Code in your browser. We reverse-engineered the undocumented WebSocket protocol hidden inside the CLI and built a web UI on top of it. No API key needed, it runs on your existing Claude Code subscription.
bunx the-companionOpen localhost:3456. That's it.
Foreground mode is also available explicitly with:
the-companion serveClaude Code is powerful but stuck in a terminal. You can't easily run multiple sessions, there's no visual feedback on tool calls, and if the process dies your context is gone.
The Companion fixes that. It spawns Claude Code processes, streams their output to your browser in real-time, and lets you approve or deny tool calls from a proper UI.
- Multiple sessions. Run several Claude Code instances side by side. Each gets its own process, model, and permission settings.
- Streaming. Responses render token by token. You see what the agent is writing as it writes it.
- Tool call visibility. Every Bash command, file read, edit, grep, visible in collapsible blocks with syntax highlighting.
- Subagent nesting. When an agent spawns sub-agents, their work renders hierarchically so you can follow the full chain.
- Permission control. Four modes, from auto-approve everything down to manual approval for each tool call.
- Session persistence. Sessions save to disk and auto-recover with
--resumeafter server restarts or CLI crashes. - Environment profiles. Store API keys and config per-project in
~/.companion/envs/without touching your shell.
The Claude Code CLI has a hidden --sdk-url flag. When set, it connects to a WebSocket server instead of running in a terminal. The protocol is NDJSON (newline-delimited JSON).
┌──────────────┐ WebSocket (NDJSON) ┌─────────────────┐ WebSocket (JSON) ┌─────────────┐
│ Claude Code │ ◄───────────────────────► │ Bun + Hono │ ◄───────────────────► │ Browser │
│ CLI │ /ws/cli/:session │ Server │ /ws/browser/:session │ (React) │
└──────────────┘ └─────────────────┘ └─────────────┘
- You type a prompt in the browser
- Server spawns
claude --sdk-url ws://localhost:3456/ws/cli/SESSION_ID - CLI connects back over WebSocket
- Messages flow both ways: your prompts to the CLI, streaming responses back
- Tool calls show up as approval prompts in the browser
We documented the full protocol (13 control subtypes, permission flow, reconnection logic, session lifecycle) in WEBSOCKET_PROTOCOL_REVERSED.md.
git clone https://github.com/The-Vibe-Company/companion.git
cd companion/web
bun install
bun run dev # backend + Vite HMR on :5174Production: bun run build && bun run start serves everything on :3456.
Install as a launchd service that starts on login and restarts on crash:
bun install -g the-companion
the-companion installOther commands:
the-companion start # start the installed background service
the-companion status # check if the service is running
the-companion stop # stop the service (keeps it installed)
the-companion restart # restart the service
the-companion logs # tail stdout/stderr logs
the-companion uninstall # remove the serviceUse --port <n> with install to override the default port (3456).
Dev uses port 3457 for the backend and 5174 for Vite HMR, so both dev and prod can run simultaneously.
Bun runtime, Hono server, React 19, Zustand, Tailwind v4, Vite.
Check open issues, fork, branch, PR. For protocol-level work, read the WebSocket spec first.
MIT
