Claude in Browser lets you chat with Claude in a web page — no setup, no API keys, no cloud accounts. If Claude Code works in your terminal, this works too.
Because everything is local. The server is running on your own computer, so there's no network delay between the browser and the server. The only real wait is for Claude to think — and the response starts appearing the moment the first words are ready, not after the entire reply is finished.
When you set up Claude Code (the terminal tool), it created a login session on your computer. This app reuses that exact same session. The server simply asks Claude Code to handle your message, and Claude Code already has your credentials. That's why there's nothing to configure.
How Claude in Browser connects your browser to the Claude CLI via WebSocket and process spawning.
claude -p which reuses your existing Claude Code OAuth session.
user message and an empty assistant placeholder, sets isStreaming: true, and sends the full conversation history over the WebSocket as { type: "chat", messages: [...] }.handleChat() formats the conversation, then spawns:claude -p --verbose --output-format stream-json-p flag is pipe mode — stdin in, stdout out.assistant event, the server extracts the text delta (new text since last send) and forwards it as { type: "text", text: "..." }. On result, sends { type: "done" }.MessageBubble, transitioning from a pulsing cursor to growing text.| File | Purpose |
|---|---|
main.tsx | Entry point — renders BrowserChat into #root |
index.css | Design tokens, base styles, dark theme |
claude-in-browser/index.tsx | Chat view — message list, auto-scroll, empty state, typing indicator |
claude-in-browser/store.ts | Zustand store — WebSocket, messages, streaming state |
components/ChatInput.tsx | Auto-resizing textarea, Enter-to-send |
components/MessageBubble.tsx | User/assistant bubbles, pulsing cursor while streaming |
components/StatusBar.tsx | Connection status, clear button, initiates WebSocket on mount |
| File | Purpose |
|---|---|
server/index.ts | Express + WebSocket server, spawns claude -p per chat request |
server/run-claude.sh | Shell wrapper — strips Claude env vars to avoid nested session detection |
When running inside Claude Code, env vars like CLAUDECODE are set. The CLI detects these and refuses to run (nested session protection). The server strips them before spawning:
unset CLAUDECODE CLAUDE_CODE CLAUDE_CODE_ENTRYPOINT CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS
Both HTTP and WebSocket traffic are proxied through Vite to avoid CORS:
| Path | Target | Protocol |
|---|---|---|
/api/* | http://localhost:4820 | HTTP |
/ws/* | ws://localhost:4820 | WebSocket |
SIGTERM to the running claude process.claude -p instance. The process exits when the response is complete.claude -p emits the full response in one assistant event rather than token-by-token. Streaming granularity depends on CLI buffering.| Service | Port | Notes |
|---|---|---|
| Express + WebSocket | 4820 | Backend API |
| Vite dev server | 5214 | Frontend, proxies to 4820 |