Full activity streaming — thinking, tool calls, and responses in real-time. Self-hosted, open-source.
Quick Start • Why Remo Code • Architecture • Deploy
OpenClaw popularized the idea of talking to an AI agent from your phone. But it requires you to trust a third-party runtime with shell access to your machine, and security researchers have already found real data exfiltration in community-contributed OpenClaw skills.
Remo Code gives you the same "chat with your agent from anywhere" workflow, but with full activity streaming and complete control:
| OpenClaw | Claude Code Remote Control | Remo Code | |
|---|---|---|---|
| Self-hosted | Partial (local agent, cloud relay) | No (Anthropic relay) | Yes, fully |
| Open source | Yes | No | Yes (MIT) |
| Activity streaming | No | No | Yes (thinking, tool calls, text) |
| Web UI | No (messaging apps only) | Yes (claude.ai) | Yes (your own domain) |
| Multi-session | No | No | Yes |
| File attachments | No | No | Yes (images + text files) |
| Auth & data storage | Third-party servers | Anthropic servers | Your Supabase instance |
- Developers who want to check on long-running Claude Code tasks from their phone
- Teams who want a shared dashboard for multiple Claude Code sessions
- Security-conscious users who don't want third-party tools with shell access to their machines
- Self-hosters who want full control over their data and infrastructure
- Bun runtime
- Claude Code CLI installed
- A Supabase project (free tier works)
git clone https://github.com/finedesignz/remo-code.git
cd remo-code
bun installCreate a Supabase project and run the migrations in supabase/migrations/ via the SQL Editor.
cp hub/.env.example hub/.env
# Edit: SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, HUB_ALLOWED_ORIGINS
cp web/.env.example web/.env
# Edit: VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY, VITE_HUB_URL# Terminal 1 — Hub server (port 3040)
bun run dev:hub
# Terminal 2 — Web dev server (port 5173)
bun run dev:webOpen http://localhost:5173 and create your account on the setup form.
Generate an API key in Settings, then run the agent in your project directory:
npx remo-code-agent --api-key YOUR_API_KEY --local-outputThat's it. The agent spawns a Claude Code process, and everything streams to your browser in real-time — thinking, tool calls, file edits, and responses. You get both terminal output and web UI.
Each agent = one Claude Code session. To connect multiple projects, run the agent in each project directory. Each gets its own session in the web UI. Sessions auto-resume by project directory.
Add an alias so you can run claude-remote instead of the full command:
Windows (PowerShell)
Add to your PowerShell profile ($PROFILE):
# Open profile in editor (creates it if it doesn't exist)
if (!(Test-Path $PROFILE)) { New-Item -Path $PROFILE -Force }
notepad $PROFILEAdd this line:
function claude-remote { npx remo-code-agent --api-key YOUR_API_KEY --local-output }Reload: . $PROFILE or open a new terminal.
macOS / Linux (bash)
Add to ~/.bashrc (or ~/.bash_profile on macOS):
alias claude-remote='npx remo-code-agent --api-key YOUR_API_KEY --local-output'Reload: source ~/.bashrc
macOS / Linux (zsh)
Add to ~/.zshrc:
alias claude-remote='npx remo-code-agent --api-key YOUR_API_KEY --local-output'Reload: source ~/.zshrc
fish
Add to ~/.config/fish/config.fish:
alias claude-remote 'npx remo-code-agent --api-key YOUR_API_KEY --local-output'Reload: source ~/.config/fish/config.fish
Then just run claude-remote in any project directory — same as running claude but with remote streaming to the web UI.
If you don't want to self-host, use the hosted hub at app.remo-code.com:
npx remo-code-agent --api-key YOUR_API_KEY --local-outputThe default hub URL is https://app.remo-code.com — no --hub-url needed.
Browser (React SPA)
↕ WebSocket + REST API
Hub Server (Bun + Hono)
↕ WebSocket
Local Agent (one per project)
↕ subprocess stdin/stdout (stream-json)
Claude Code CLI
Four packages in a Bun workspace:
- hub/ — Bun + Hono server handling auth (Supabase JWT), message relay, and session management. Broadcasts Claude's activity events (thinking, tool use, text) to subscribed browsers.
- web/ — React 19 + Vite + Tailwind CSS 4 chat UI with activity feed, session switching, file attachments, light/dark theme, and unread badges.
- agent/ — Local streaming agent that runs on your dev machine. Spawns a persistent Claude Code CLI process with
--input-format stream-json --output-format stream-json, parses events, and relays to the hub. Published asremo-code-agenton npm. - channel/ — (Legacy) Claude Code channel plugin. Kept for backward compatibility.
- You run
npx remo-code-agent --api-key xxxin your project directory - The agent connects to the hub via WebSocket and registers a session
- The agent spawns
claude --input-format stream-json --output-format stream-json --verbose - When you send a message in the web UI, the hub forwards it to the agent
- The agent writes the message to Claude's stdin as JSON
- Claude responds — thinking, tool calls, text stream out via stdout
- The agent parses the stream-json events and relays them to the hub
- The hub broadcasts to all subscribed browsers in real-time
Session resume: The agent reuses existing sessions by matching the project directory. Restart the agent and it reconnects to the same session with full message history.
Conversation memory: The agent keeps a single persistent Claude process — full conversation context is maintained across messages, just like the terminal.
- Activity streaming — see Claude's thinking, tool calls, and text responses in real-time
- File attachments — paste images (Ctrl+V) or attach text files in the chat
- Multi-session — run agents in multiple project directories, switch between them
- Session resume — restart the agent and reconnect to the same session
- Unread badges — know when sessions have new messages
- Light/dark theme — toggle in the header
- Mobile-first — responsive design with safe-area support for notched devices
Build and deploy with Docker:
docker build -t remo-code .
docker run -p 3040:3040 \
-e SUPABASE_URL=... \
-e SUPABASE_ANON_KEY=... \
-e SUPABASE_SERVICE_ROLE_KEY=... \
-e HUB_ALLOWED_ORIGINS=https://your-domain.com \
remo-codeThe Docker image builds the web frontend and serves it from the hub — one container, one port. The agent runs on your dev machine, not on the server.
├── hub/ # Bun + Hono server (HTTP, WebSocket, auth)
│ └── src/
│ ├── api/ # REST endpoints (sessions, messages, profile, setup)
│ ├── auth/ # JWT + API key verification middleware
│ ├── db/ # Supabase clients and data access layer
│ ├── middleware/ # Rate limiting
│ ├── utils/ # Shared utilities (token generation)
│ └── ws/ # WebSocket handlers (agent, channel, client) + Zod schemas
├── web/ # React 19 + Vite + Tailwind CSS 4 SPA
│ └── src/
│ ├── components/ # Layout, ChatPanel, ActivityFeed, Sidebar, etc.
│ └── hooks/ # useAuth, useWebSocket, useSessions, useChat, useActivity
├── agent/ # Local streaming agent (npm: remo-code-agent)
│ └── src/
│ ├── index.ts # Entry point — wires hub client, Claude runner
│ ├── claude-runner.ts # Persistent Claude CLI process management
│ ├── hub-client.ts # WebSocket client to hub
│ └── config.ts # Config loading (CLI args, env vars, config file)
├── channel/ # (Legacy) Claude Code channel plugin
├── supabase/ # Database migrations
└── Dockerfile # Multi-stage production build
- Supabase JWT auth on all API and WebSocket endpoints
- Row-Level Security on all database tables — multi-tenant by default
- API keys stored as SHA-256 hashes with timing-safe comparison
- CSP, HSTS, and security headers on all responses
- Rate limiting on API routes, setup endpoints, and WebSocket messages
- Per-IP connection limits on WebSocket endpoints
- Path traversal protection on static file serving
- Non-root Docker user in production
- Setup endpoint mutex preventing race conditions
Your data stays in your Supabase instance. Your Claude Code sessions stay on your machine. The hub is just a relay — and you own it.
Apache-2.0
