The Problem
Claude Code is powerful but confined to a terminal: no visual feedback on tool execution, no easy way to run multiple sessions simultaneously, and lost context if the process terminates. There is no browser or mobile UI for managing sessions, streaming output, or approving tool calls without editing code directly.
What This Does
Companion is a web UI (36 files in web/) built on a reverse-engineered WebSocket protocol that sits in front of the Claude Code CLI. It spawns claude --sdk-url processes, streams NDJSON responses to the browser in real time, and surfaces tool calls as approvable blocks. Core files include web/server/index.ts (entry point, CORS, WebSocket handling), web/server/ws-bridge.ts (36 functions, state management, session restore), web/src/App.tsx (root component, reaches one function), and web/server/cli-launcher.ts (launches CLI processes, persists state). The protocol is documented in WEBSOCKET_PROTOCOL_REVERSED.md. No API key is required beyond an existing Claude Code subscription.
How It Is Wired
Execution starts at web/server/index.ts:107 (message) and web/server/index.ts:98 (open). The message function reaches 21 downstream functions; open reaches 10. The traced path to outbound network is message -> handleCLIMessage -> routeCLIMessage -> handleSystemMessage -> broadcastToBrowsers [network via ws.send]. broadcastToBrowsers is the most widely called function in the internal call graph (10 call sites), followed by post (8 sites), gitSafe (8 sites), and get (8 sites). The module graph shows web/src/store as a high-traffic hub (10 importers, 1 export, instability 0.09), while web/src/App has the highest instability score (0.89) with 1 importer and 8 exports, indicating it is a leaf that many others depend on. web/server/ws-bridge.ts owns session lifecycle effects (makeDefaultState, restoreFromDisk, setCLISessionId); web/server/cli-launcher.ts owns process lifecycle (launch, relaunch, kill); web/server/index.ts owns CORS and gateway effects. Files with wide blast radius: web/src/components/HomePage.tsx (632 lines, ripple-prone), web/src/components/Composer.tsx (deep nesting, guard-clause opportunity).
How To Use It
Setup:
git clone https://github.com/moses-y/companion.git
cd companion/web
bun install
Configuration: Required environment variables are defined in .env.example (file present in root). No API keys are needed if running against an existing Claude Code subscription, but the server expects the --sdk-url flag to be passed to the CLI.
Running it: Development: bun run dev starts the Hono backend on port 5174 and Vite HMR. Production: bun run build && bun run start serves everything on port 3456. The CLI entry point is web/bin/cli.ts.
Real-World Use
A user opens Companion in a browser, clicks New Session, and a claude --sdk-url ws://localhost:3456/ws/cli/SESSION_ID process spawns on the server. The user types a prompt; the server relays it over WebSocket. The CLI streams NDJSON back: token-level output, tool calls (bash, grep, edit), and status messages. The browser renders streaming text token-by-token and surfaces tool calls in collapsible blocks with syntax highlighting. The user approves or denies each tool call via the UI. Multiple sessions run side by side, each with independent state saved to ~/.companion/envs/ (environment profiles). If the CLI crashes, --resume auto-recoveries the session from disk.
Code Health & Issues
- [HIGH] Pin third-party GitHub Actions to commit SHAs –
.github/workflowspinsgoogleapis/release-please-action@v4andoven-sh/setup-bun@v2without SHA pins; tags can move, risking secret exposure with your token. - [HIGH] No test suite – 31 source files, zero test files; any change reaches production with no signal that behavior is preserved.
- [HIGH] Wildcard CORS origin –
web/server/index.tsusescors()with a wildcard paired with credentials, allowing any site to perform authenticated requests via the browser. - [MEDIUM] No dependency update bot – 2 manifest files with no Dependabot/Renovate configuration; published advisories go unpatched until manual audit.
- [MEDIUM] Oversized HomePage –
web/src/components/HomePage.tsxat 632 lines; hard to hold in one mind, changes ripple widely. - [LOW] Stale TODO/FIXME markers – 3 markers in
web/src/components/Playground.tsxunresolved.
These findings are deterministic outputs of static analysis (32 of 32 code files analyzed, 222 functions, 58 classes). They are not opinions.
The Bottom Line
Companion successfully brings Claude Code into a browser with real-time streaming, tool visibility, and session persistence—no API key beyond a subscription required. The codebase is functional but untested, has a wildcard CORS misconfiguration, and lacks dependency automation. It is suitable for teams already bought into Claude Code who need a visual, mobile-friendly session manager; others may want to wait until testing and supply-chain hygiene are addressed.