mew includes a web UI that connects to the daemon over WebSocket. It provides a browser-based alternative to the TUI with the same agent capabilities.
Starting the web UI
Section titled “Starting the web UI”mew daemon --port 127.0.0.1:9847mew-webThen open http://localhost:9847 in your browser. The mew-web bridge
serves the built React app and relays WebSocket connections to the daemon.
For development with hot reload:
just dev-uiThis starts Vite with HMR and auto-spawns the daemon. Use --open to
launch the browser automatically:
just dev-ui -- --openWhat you see
Section titled “What you see”The web UI has a layout similar to the TUI but optimized for browser interaction:
- Chat surface: streaming markdown with syntax-highlighted code blocks (Shiki). Tool calls appear as cards with inline output and expand/collapse.
- Model picker: shows available models with thinking variant selection. Click to switch models.
- Title strip: shows the session title and connection status.
- Session rail: lists previous sessions. Click to resume. The folder button opens a project picker — pick a recent project directory or type a path to start a new session in that directory.
- Input area: type your prompt.
Cmd/Ctrl+Enterto send. - Status footer: shows token count, model, and connection state.
- Todo panel: renders the agent’s todo list when active.
- Subagent panel: shows running and completed subagents.
- Ask-user cards: interactive question cards when the agent asks.
- Permission prompts: approve or deny tool calls inline.
Features
Section titled “Features”| Feature | TUI | Web UI |
|---|---|---|
| Streaming markdown | ratatui-mdstream | Shiki syntax highlighting |
| Tool call cards | inline | inline with expand/collapse |
| Model picker | Ctrl+P |
click model pill |
| Thinking variant | Ctrl+P cycle |
dropdown |
| Session list | /sessions |
sidebar rail |
| Subagent panel | sidebar | dedicated panel |
| Todo list | sidebar panel | dedicated panel |
| Ask-user prompts | modal | inline card |
| Permission prompts | modal (a/s/d) |
inline buttons |
| Reconnect | n/a | exponential backoff (2s, 4s, 8s, cap 30s) |
| Theme | terminal colors | system, light, dark |
Architecture
Section titled “Architecture”Browser → mew-web (bridge) → mew daemon (Unix socket)Three packages in a pnpm workspace:
mew-web-bridge(Rust): TCP+WS listener that relays browser WebSocket connections to the daemon’s Unix socket. Serves the built React app frommew-web-ui/dist/as static assets. Auto-spawnsmew daemonif not running.mew-web-client(TypeScript): Typed client for the wire protocol. Builds to ESM with.d.tstypes. TheMewClientclass manages the WebSocket connection, dispatches events to typed listeners, and provides promise-based methods for request/response patterns.mew-web-ui(TypeScript/React): React app with TanStack Router. Vite build todist/. Uses Zustand for state management.
The bridge serves the built React app from embedded assets at runtime.
Vite hashes asset filenames, so files are served dynamically by path
lookup rather than hardcoded include_bytes!.
Connection lifecycle
Section titled “Connection lifecycle”The web UI handles disconnection gracefully:
- On unexpected WS close, the client retries with exponential backoff (2s, 4s, 8s, up to 30s).
- The session ID is saved to
localStorage. On reload, the client reconnects viaattachSession, falling back tonewSessionif the session is gone. - When reconnected, the full message history is replayed.
Multiple browser tabs can attach to the same session. Permission and
ask-user prompts go to all connected clients. Any client can respond.
RequestResolved dismisses the prompt across all clients.
See Daemon Protocol for the wire-level details, and Web UI Development for the developer guide.