A self-hosted, multi-host dashboard for Claude Code — run, monitor, and resume Claude Code sessions across your entire fleet of machines from one browser tab.
Run Claude Code on every machine your team operates. Watch all of them work in real time from a single browser tab. Resume a conversation on a different device that you started somewhere else. Dispatch a task to whichever host has the right credentials, the right files, or the right hardware.
A working blueprint for Claude Code fleet management, multi-machine agent orchestration, and team-wide AI coding collaboration — open source, self-hosted, no SaaS lock-in.
What this gives a team:
- 🛰️ See every Claude Code session across the fleet, live, in one tree
- 📱 Resume any session on any device — desktop, laptop, phone, tablet
- 🚦 Spot a teammate's session going sideways and steer it back, without breaking your flow
- 🛠️ Dispatch the same task to many hosts in parallel without SSH chains
- 🧠 Searchable archive of every conversation your team has ever had — regardless of which Claude client wrote it (Code CLI, Claude Desktop, VS Code extension, the in-browser Chat — all surface in the same dashboard)
⭐ If this blueprint helps your team, a star helps other teams find it.
We are four engineers running ~8 sessions in parallel across 8 machines. Without Nexus we lose ~30 minutes a day reconstructing what we did yesterday and what each other is up to. Three pages — Operations, Browse, Chat — replace that overhead. They are the workflow. Everything else is supporting infrastructure.
The radar screen. The page is split into a topology map (left), a session list (middle), and a session detail pane (right). For any selected session the detail pane shows three stacked sections:
- AGENTS — a real-time dataflow graph of the parent session and every sub-agent it has spawned via the
Tasktool. Each sub-agent is a node tagged with its role (General/Explore/Plan/ etc.), title, live token-usage badge, and the tools it has used so far. Curves connect Main to its children. This is the "multi-agent" view — when one Claude session fans out into N parallel sub-agents, you see all of them at once with their relative load. - TOOLS — every tool call in the parent session as a chronological stream —
Bash,Read,Edit,Agent,TaskCreate,TaskUpdate,browser_*— withjust nowtimestamps that update live. - CONVERSATION — the most recent USER and CLAUDE turns, full markdown.
The screenshot below was taken at a moment when this exact README was being produced. The Main session (Opus 4.6, on Dev 201) had fanned out three General sub-agents in parallel — each translating a batch of markdown files from English to 繁中, each with its own token budget and Read history. That's one session, three agents, all visible on one panel.
With four engineers each running sessions like this, Operations replaces "I have no idea what's happening" with "you're tracking your teammate's parallel sub-agents in real time." When something is going sideways — a Claude session looping, eating tokens, stuck waiting on input — one click closes it. When you want to take a teammate's session over, one click resumes it into Chat.
This is also the cross-review surface: read a colleague's running session graph, and if any branch is drifting, drop into the same session_id and steer the parent in your next prompt.
Eight machines, 691 sessions, 282 thousand messages of conversation history at the time this screenshot was taken. Browse is the indexed, searchable archive of all of it.
It captures every Claude client, not just the in-browser Chat. Anything the team types into the Claude Code CLI, the VS Code Claude extension, or Claude Desktop on any host writes JSONL to ~/.claude/projects/, and claude-sync (event-driven, <1s) pushes those updates straight into the same store Browse reads from. So an engineer's terminal session at 9am, a quick Claude Desktop chat at lunch, and a VS Code refactor in the afternoon all land in the same searchable timeline — no separate tools, no copy-paste.
Structure: Server → Project → Session → Full conversation. Every Claude conversation our team has ever had is here, with the full pipeline (Read → Bash → Edit → Bash → …), every user prompt, every response, file references, timestamps. New engineer joining? Browse tells them in 10 minutes what every active project is doing and why. Picking up a project after a week away? Browse the last few sessions and you have full context. Reviewing a teammate's work? Read their session, see the decisions, leave a corrective note in your own follow-up prompt.
The Resume button on any session opens it directly into Chat — keeping the same session_id so Claude has the entire prior context. That's the bridge between the archive and live work.
The terminal version of Claude Code is great. But once a team has many sessions across many projects across many hosts, the terminal alone is no longer enough. Chat is the daily driver, at the desk and away from it.
The GIF below is a real, resumed session — the team's Raspberry Pi sister project, projects/pibar on .201 Dev, with 76 messages of context already loaded. As we scroll, you can see the things Chat actually gives you: tool-call pipelines collapse into one block (PIPELINE Edit×3, Bash×4), markdown is rendered (lists, bold, inline code), every USER turn pairs with a Claude RESPONSE, and the heartbeat in the header (1s → 8s) ticks live so you always know the WebSocket is alive.
At the desk, Chat beats the terminal for everything past a single session:
- 🪟 Each Chat is its own window, sized for real work — opening Resume spawns a 1400×900 native browser window (not a tab). On a wide monitor you arrange 4–6 Chat windows side-by-side and watch every Claude type at once, no tab-switching latency. Try doing that with eight tmux panes in a single terminal window.
- 🎨 Real markdown rendering — tables, syntax-highlighted code blocks, ordered lists, links. Terminals don't render markdown; Chat does, and complex Claude responses become 5× more readable.
- 🧩 Tool-call pipelines collapse into one expandable block — a 12-step
Read → Bash → Edit → Bash → ...chain shows as a single line you can expand, instead of a wall of terminal output you have to scroll through. - 🔄 Partial streaming you can actually watch — see Claude typing one chunk at a time, not after the whole turn lands. Useful when a long response is "is it doing the right thing?" — you can interrupt early.
- 📎 Drag-drop screenshots and files — paste a screenshot of a UI bug straight into the prompt. The terminal makes you upload, copy the path, type it in.
- 🔗 Sharable session URL —
nexus.local/chat?session=abc...is a link you can drop in Slack. Your teammate clicks it, opens the same conversation; the duplicate-open guard kicks in and lets you decide who keeps the live session. Cross-engineer review without screen-sharing. - 📑 Window title reflects state —
Chat · pibar (.Dev)so even with 6 chat windows open you find the right one in the OS window switcher (Alt-Tab / Mission Control). The title flips to✓ idleor⚠ waiting on toolwhen state changes — peripheral awareness without raising the window.
Away from the desk, Chat is the only interface:
- 📱 Phone, tablet, second monitor at home, hotel laptop — any device with a browser opens the same conversations.
- 🔒 Four-layer duplicate-open guard (in-memory lock → BroadcastChannel → sessionStorage lease → server registry) means a session opened on your desktop and your phone never accidentally forks. If two views exist, both get warned and the user decides.
- 🌙 The mobile UI is functionally identical — bottom nav, same chat thread, same tool collapsing. No "watered-down mobile version."
The simple version: terminal Claude Code is the engine; Chat is the cockpit you actually fly from.
Our engineering fleet runs across 8 machines — dev servers, a Docker host, an AI box, two Windows workstations, a Raspberry Pi, and a PVE node. Each one is essential for different reasons: proximity to specific datasets, SSH credentials for specific networks, GPU availability, VPN membership.
Once Claude Code was running on all of them, three operational problems showed up immediately: no visibility (eight tmux sessions, no idea who'd finished what), no mobility (a conversation on the workstation couldn't be continued from a phone in a meeting), friction-heavy dispatch (SSH in, attach tmux, type prompt, detach — repeated for every target host).
Claude Nexus is the dashboard built to fix all three. A Next.js + WebSocket front end with a small Python service running on every host. It has been running in production as part of our internal tooling for months.
The full source code is not included in this repository. The deliberate choice: anyone reading this README can rebuild the parts that fit their own infrastructure with an AI coding tool. That is the bet of this repo — provide the blueprint, the design decisions, the prompt recipes, and enough scaffolding that your team can stand up its own control plane in a sprint or two.
Three structural choices keep the running cost well below a comparable closed-source fleet:
- One physical box, many VMs — most of the Linux side of the fleet (dev server, Docker host, DNS, Nexus host, stock-trading box, AI server) actually runs as VMs on a single Proxmox VE node. One rack-unit of hardware, full logical isolation between roles. Adding a ninth host is
qm clone, not a purchase order. - Fully open-source stack — Ubuntu, PostgreSQL, MySQL, Redis, MinIO, FastAPI, Next.js, Postfix, BIND, Nginx, OpenResty, Mattermost, Jellyfin, Ollama. Zero per-seat / per-core / per-CAL licensing. Replacing Windows Server + SQL Server alone removes a recurring 5–6-figure annual line item from the budget.
- The Linux surface is delegated to AI — apt upgrades,
restart: unless-stoppedaudits, systemd debugging, certificate rotation, container rescue — the operator describes intent in natural language, and Claude (via this dashboard and thefleet-dispatchMCP) executes on the right host. You don't need a Linux specialist on payroll to keep the fleet healthy; the dashboard is the specialist.
Combined effect: a small team runs production-grade infrastructure that would normally need an SRE, a DBA, and a Microsoft-licensed budget. Same uptime, fraction of the cost.
CPU / RAM / disk / Docker / Claude Code authentication on every machine. Plan-usage meter for the active subscription. Active sessions across the fleet. CLI/SDK version with one-click upgrade. The first page you load to confirm the fleet is healthy.
486 projects across the fleet at the time of this screenshot, automatically tiered, tagged, and grouped by domain (Claude ecosystem, finance/trading, government, education, production systems, etc.). Tier-1 projects (the ones that matter to the business) bubble to the top. Activity bars show 30-day message counts at a glance.
Pre-built templates for common workflows: full-stack, security audit, refactor, data analysis, debug emergency, devops, content creation, UI design, business strategy, product planning. Each template defines a set of roles; dispatching one launches a coordinated multi-agent team across the fleet.
Bring Opus, Sonnet, and Gemini into the same conversation. Each participant gets their own column, speaks in turn (configurable rounds), and renders responses with full markdown. The GIF below is a real two-model debate (Sonnet Reviewer + Opus Devil-Advocate) on a single topic — same prompt, two perspectives, side-by-side, in <60 s.
We use this when a design decision benefits from competing takes side-by-side instead of a single model's first answer.
Every conversation feeds a knowledge pipeline that surfaces SOPs, server configurations, problem/solution pairs, technical decisions, tool know-how, and stored preferences. 372 wiki entries auto-generated from the team's own conversation history at the time of this screenshot. Tagged, versioned, searchable, deduplicated.
For any project we point Nexus at, it runs a tree-sitter pass and produces a layered architecture graph: pages, components, APIs, services, modules, configs, databases, externals — connected by imports/calls/renders/proxies/reads/writes/depends edges. The example below is the auto-generated graph of Nexus itself — 29 nodes, 37 edges, 5 layers.
There's also an inline AI Q&A box ("How does this API authenticate?") that answers questions about the graph. New engineer who just joined and wants to learn how the chat WebSocket proxy connects to the per-host servers? One click to the graph, one search for "WebSocket," one read.
A self-referential page — Nexus surfaces its own GitHub repos here, treating itself as one of the artifacts it manages. Lists every repo the team publishes with live stats (stars / forks / watchers / open issues), recent commits, recent issues + PRs (interleaved with PR/IS badges), and a collapsible README preview that auto-detects multilingual variants — README.md / README.zh-TW.md / README.ja.md / etc. become tabs you can switch between without leaving the page.
The first repo on the list is this one — Nexus shows itself. Adding another repo is a one-line edit to a config file. Phase 2 (next) adds a 「重新分析」 button: Claude reads the recent commits, proposes README updates, renders a unified diff, and pushes only after you confirm.
→ Build pattern in recipes/06-repo-dashboard.md.
Bottom nav, card-stack layouts, full feature parity with desktop. Pick up where you left off from anywhere.
Nexus is not a single binary; it's the centerpiece of a small constellation. Each piece is independently deployable, communicates with Nexus over a stable HTTP/WebSocket API, and could be replaced without touching the others.
Every component below is first-party — built by us, owned by us, in production daily on our own fleet. None of it is wrapping someone else's hosted service.
| Component | Lives where | What it does |
|---|---|---|
| Nexus dashboard ✦ | central host (one) | the Next.js + WebSocket app you've seen above |
chat_server.py ✦ |
every host (N) | per-host FastAPI :8082 — spawns Claude SDK locally, exposes /health, /worker/list, /instances, /ws/chat, /worker/dispatch |
claude-sync ✦ |
every host (N) | watchdog/inotify daemon; pushes JSONL transcript changes from every Claude client (CLI, Desktop, VS Code, web Chat) to Postgres in <1s |
browser-knowledge MCP ✦ |
central host | MCP server backing /knowledge (wiki extraction + cross-conversation search across the whole archive) |
fleet-dispatch MCP ✦ |
central host | MCP server that lets the control plane tell any host to run a command locally — no SSH chain |
✦ = built in-house. The Nexus showcase repo (this one) covers the patterns for all five. Standalone open-source releases of chat_server / claude-sync / the two MCP servers are something we may extract later — let us know if you'd find that useful.
The same activity API and /ws/updates push that the Nexus dashboard consumes is open for anything else to consume. The list below is what we're building (or have built) on top. Each will get its own repo as it stabilizes.
| Codename | Form factor | What it does | Status |
|---|---|---|---|
📊 pibar |
Raspberry Pi 5 + 7.9″ touchscreen (1280×400) | Always-on desk strip showing every active Claude session across the fleet next to live solar-inverter readings. Touch to drill in. | running on a real desk; repo coming soon |
🔔 echo |
Mac/Windows menu-bar tray | Active session count in the menu bar; native desktop notification when any session enters awaiting_input or completed. Subscribes to /ws/updates. |
sketched |
🧭 glance |
Chrome / Firefox extension | Toolbar badge with total active sessions, popup with per-host breakdown, click-through deep-links into the Nexus session view. | sketched |
📝 loom |
VS Code / Cursor extension | Sidebar of "every Claude conversation that touched this repo, across all hosts," with one-click jump-to-session. | sketched |
💡 lumen |
Hue / LIFX smart-bulb daemon | Bulb glows blue when Claude is thinking, green on completion, red on error. Ambient AI status that doesn't need a screen. | sketched |
🛡️ gate |
GitHub Action | Posts a PR comment listing the Claude sessions that produced the diff — provenance for AI-generated code. | sketched |
More form factors in the works. They'll show up on this list (and on the live /showcase page inside the dashboard) as their repos go public.
Two ways to consume Nexus from another tool:
- HTTP —
GET /api/claude/activity,/api/projects-all,/api/sessions/[sessionId], etc. Stable JSON shapes, documented in the architecture doc. This is howpibarworks. - WebSocket — connect to
wss://nexus/ws/updatesand you get the same fan-in payload the dashboard receives — every 5 seconds, all hosts, all sessions, all worker states, in one push. Fewer than 30 lines of JS gives you a custom live monitor.
If you build something on top, open an issue or PR — we'll list it here.
flowchart TB
Browser["🖥️ Browser<br/>desktop · tablet · phone"]
subgraph CP["Control plane (one host)"]
Node["Custom Node server<br/>HTTP + 2× WebSocket on one port"]
WSC["/ws/chat<br/>SSH-less chat proxy"]
WSU["/ws/updates<br/>real-time fan-in (5s push)"]
end
subgraph SVC["Central services"]
BK["browser-knowledge MCP<br/>wiki extraction · cross-conversation search"]
FD["fleet-dispatch MCP<br/>local-exec on target host · no SSH chain"]
PG[("PostgreSQL<br/>conversation store")]
end
subgraph EDGE["Per-host edge (× N)"]
CS["chat_server.py :8082<br/>FastAPI + Claude Agent SDK<br/>spawns sessions locally"]
CLI["Claude clients<br/>Code CLI · Desktop · VS Code · web Chat"]
SYNC["claude-sync<br/>watchdog/inotify · event-driven"]
end
Browser -- HTTPS --> Node
Browser -. WSS .-> WSC
Browser -. WSS .-> WSU
Node --- WSC
Node --- WSU
WSC -- "HTTP :8082" --> CS
Node -- search --> BK
Node --> FD
FD -- "dispatch (local exec)" --> CS
CS --> CLI
CLI -- "JSONL transcript" --> SYNC
SYNC -- "<1s push" --> PG
BK <--> PG
ASCII version (for terminal viewers)
┌─────────────────────────────────┐
│ Browser (desktop + mobile) │
└───────┬──────────────────┬──────┘
│ HTTPS │ WSS
▼ ▼
┌──────────────────────────────────────────────┐
│ Next.js 15 + custom Node server │
│ • HTTP + WS on one port │
│ • /ws/chat → SSH-less chat proxy │
│ • /ws/updates → real-time fan-in │
└──────┬──────────────────────┬────────────────┘
│ HTTP :8082 │ fleet-dispatch
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ chat_server.py │ │ browser-knowledge │
│ (every host, local) │ │ MCP + Postgres │
│ • spawns Claude SDK │ │ • cross-convo search│
│ • /health /workers │ │ • wiki extraction │
│ • /instances │ │ • digests │
└─────────┬───────────┘ └──────────▲──────────┘
│ │ <1s
▼ │
┌─────────────────────┐ ┌──────────┴──────────┐
│ Claude CLI + SDK │──▶ │ claude-sync │
│ writes JSONL log │ │ (watchdog/inotify) │
└─────────────────────┘ │ event-driven push │
└─────────────────────┘
The key design choice: Claude Code runs locally on each host, never as a centralized service. The dashboard is intentionally thin. Each machine retains its own filesystem, its own credentials, its own network context. Nexus aggregates visibility and steering — it does not replace the runtime.
→ Full architecture in docs/architecture.md.
Each of these is a fork in the road where the alternative looked tempting but was wrong:
- Claude Code runs locally on each host — never a centralized server SSH-ing out.
- Event-driven sync — watchdog/inotify replaces polling. Sync lag dropped from ~30 min to under a second.
- Four-layer duplicate-open guard for session resume — memory lock + BroadcastChannel + sessionStorage lease + server registry.
- Operations as a tree, not a flat list — host → project → session → tool call. Two earlier pages collapsed into one.
- fleet-dispatch, no SSH chain — the control plane instructs each host to run a command locally instead of hopping through a jump box.
- WebSocket fan-in — the server polls hosts; the browser receives a single push. Significantly less load on a fleet at this size.
→ Full reasoning, including the approaches that did not work, in docs/design-decisions.md.
Rather than fork this repository, read the recipes and rebuild a version that fits your environment. Each one is a standalone pattern:
01-fleet-topology.md— multi-host chat-server topology02-event-driven-sync.md— watchdog/inotify → Postgres03-ws-fan-in.md— one WebSocket server, many hosts behind it04-cross-device-resume.md— the four-layer guard in detail05-prompt-recipes.md— how to prompt Claude to generate each component (the vibe-coding layer)
Plus four minimal skeletons under examples/ that can be fed to an LLM as a starting point:
chat_server_skeleton.py— FastAPI :8082 that spawns a local Claude SDK sessionserver-ws-fanin.js— Node HTTP+WS fan-in serverclaude_sync_watchdog.py— inotify → Postgresresume-lock.ts— cross-tab session-open guard
Frontend: Next.js 15 (App Router) · React 19 · TypeScript · Tailwind CSS v4 · framer-motion · react-resizable-panels · xterm.js · react-markdown + remark-gfm · dagre + @xyflow/react (graph)
Per-host backend: FastAPI · Claude Agent SDK · watchdog · psycopg2
Central services: PostgreSQL (conversation store + search) · browser-knowledge MCP · fleet-dispatch MCP
Deployment: systemd unit fronted by HTTPS — self-signed inside the trust boundary, fronted by a reverse proxy at the edge.
We didn't invent any of this from scratch. Below is the lineage — what we built on, and what we borrowed ideas from.
- Anthropic Claude Code & Claude Agent SDK — the runtime everything else orbits.
query(),ClaudeAgentOptions, session resume, SessionStore. - Next.js 15 (Vercel) + React 19 — the App Router, Server Components, Turbopack dev server.
- Tailwind CSS v4 — every pixel of styling.
- ssh2 — pure-JS SSH for the in-browser xterm.js terminal.
- watchdog — cross-platform filesystem events powering claude-sync.
- FastAPI + uvicorn — the per-host chat server.
- React Flow / @xyflow/react + dagre — Architecture Graph layout and rendering.
- xterm.js — the in-browser SSH terminal.
- PostgreSQL — conversation store, full-text search, knowledge wiki backend.
- Model Context Protocol — the integration spec that lets browser-knowledge and fleet-dispatch plug into Claude Code as MCP servers.
- Andrej Karpathy — the "LLM Wiki" idea (auto-extract structured knowledge from chat history) and the broader vibe-coding-as-recipe ethos. Our
recipes/directory and the "blueprint over binary" stance both descend from posts of his. - codecrafters/build-your-own-x — the repository pattern we use here: teach the reader to build their own version, don't hand them a fork.
- Simon Willison & the
llmCLI — README-first developer-tool design, individual-engineer-blog tone. - Phoenix LiveView / Pusher — the WebSocket fan-in pattern (server polls, clients receive consolidated push) was directly inspired by how these systems handle real-time multi-client updates.
- Tailscale — "thin central, thick edge" identity model, adapted to AI runtimes (each host owns its keys, the control plane never replaces it).
- Multica — operational observability patterns (heartbeat, JSONL direct read, monitor decoupled from WS lifecycle) that fixed our P0 visibility issues.
- Aider · Cursor · Windsurf · Continue.dev — AI coding tools that overlap with parts of what Nexus does. None of them solve the multi-host fleet problem; that's the gap Nexus fills.
Sketches, not promises. See docs/roadmap.md for the full list.
- Graph v2 — function-level call graphs from tree-sitter over the team's codebases, stitched with the knowledge graph derived from Claude Code history.
- Team Dispatch v2 — execution plans with real cross-host parallelism, not just templates.
- Skills Lock — explicit per-project rule activation before each session.
- Issue tracker integration — Linear / GitHub Issues surfaced inline with the conversation that produced them.
- Learning Center — extract behavior rules from the team's Claude Code transcripts (180+ candidate rules so far).
This is internal infrastructure. It is not productized, not multi-tenant, not a SaaS offering. The source code is intentionally absent from this repository — the value here is the blueprint, not the binary.
If a pattern saves your team a week, a star is appreciated. If you build something similar, we'd be glad to hear about it.
- Code in
examples/— MIT (skeletons, not production-ready). - Everything else (docs, recipes, diagrams, prose) — CC BY-SA 4.0.
See LICENSE.















