<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: henryopen</title>
    <description>The latest articles on DEV Community by henryopen (@henryopen).</description>
    <link>https://dev.to/henryopen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3901488%2Fd0aa9f7c-5ede-4df4-a73a-f1f919c77e95.png</url>
      <title>DEV Community: henryopen</title>
      <link>https://dev.to/henryopen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/henryopen"/>
    <language>en</language>
    <item>
      <title>I built a self-hosted dashboard for running Claude Code across 8 machines</title>
      <dc:creator>henryopen</dc:creator>
      <pubDate>Tue, 28 Apr 2026 03:55:52 +0000</pubDate>
      <link>https://dev.to/henryopen/i-built-a-self-hosted-dashboard-for-running-claude-code-across-8-machines-4dm5</link>
      <guid>https://dev.to/henryopen/i-built-a-self-hosted-dashboard-for-running-claude-code-across-8-machines-4dm5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — Four engineers, eight machines, ~8 Claude Code sessions in parallel at any time. Stitching it together by SSH-ing into every host was costing us ~30 minutes a day. We built a single-page dashboard that surfaces every session, lets us resume any of them on any device, and indexes the entire conversation history of every Claude client (CLI, VS Code extension, Claude Desktop, in-browser chat) into one searchable archive. Open-source, self-hosted, MIT — repo and full write-up linked at the bottom.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Claude Code is a terminal-first tool. That's perfect for one person on one laptop. It stops being perfect the moment you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More than one machine where Claude can do useful work (a Mac for frontend, a Linux box for ML, a Windows box for the legacy build, a Pi for the embedded toolchain)&lt;/li&gt;
&lt;li&gt;More than one engineer touching those machines&lt;/li&gt;
&lt;li&gt;More than one session running at a time on any of them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The terminal model gives you no view into what's happening anywhere except where you're sitting. You SSH in, you &lt;code&gt;ls ~/.claude/projects/&lt;/code&gt;, you open the JSONL with &lt;code&gt;less&lt;/code&gt;, you try to remember which session was the one you started yesterday. Multiply that by 8 hosts and 4 engineers and you've spent half the morning before writing a line of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we built
&lt;/h2&gt;

&lt;p&gt;Three pages, each replacing one of those daily pains:&lt;/p&gt;

&lt;h3&gt;
  
  
  Operations — situational awareness for the whole fleet
&lt;/h3&gt;

&lt;p&gt;A topology map of every machine on the left, a live session list in the middle, and a detail pane on the right. The detail pane has three stacked sections that update in real time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AGENTS&lt;/strong&gt; — a dataflow graph of the parent session and every sub-agent it has spawned via the &lt;code&gt;Task&lt;/code&gt; tool. Each sub-agent is a node tagged with role, title, live token-usage badge, and the tools it has used. Curves connect the main session to its children.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TOOLS&lt;/strong&gt; — every tool call in chronological order with &lt;code&gt;just now&lt;/code&gt; timestamps that update live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CONVERSATION&lt;/strong&gt; — the most recent USER and CLAUDE turns rendered as markdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a teammate's session starts looping or eating tokens, you see it from across the room. One click closes it. One click resumes it into the chat page so you can steer it back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Browse — the team's shared memory
&lt;/h3&gt;

&lt;p&gt;Eight machines, hundreds of sessions, hundreds of thousands of messages. Browse is a server → project → session → full-conversation tree, fully searchable, with every Claude client feeding the same store: terminal CLI, VS Code Claude extension, Claude Desktop, in-browser chat. New engineer? Browse tells them in 10 minutes what every active project is doing and why.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chat — every Claude client, in one browser tab
&lt;/h3&gt;

&lt;p&gt;xterm.js + WebSocket SSH proxy on the same port as the dashboard. Switch hosts in the sidebar, type into Claude on whichever machine has the right credentials. Resume any prior session by clicking it in Browse. Phone, tablet, anywhere — same dashboard, same session, same context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one technical decision worth highlighting
&lt;/h2&gt;

&lt;p&gt;Sub-second latency from "Claude wrote a JSONL line on host A" to "the line appears on host B's browser tab" is what makes this feel like a control plane and not a polling dashboard.&lt;/p&gt;

&lt;p&gt;We get there by replacing the original 30-minute polling loop with an event-driven pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;watchdog&lt;/code&gt;'s inotify backend on each host watches &lt;code&gt;~/.claude/projects/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A small Python service detects the JSONL append, ships the new lines to the central PostgreSQL store&lt;/li&gt;
&lt;li&gt;The Nexus WebSocket server fan-outs the change to every connected browser tab&lt;/li&gt;
&lt;li&gt;The browser updates the affected session card without a refresh&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Latency from write to UI: under one second. The full recipe is in &lt;code&gt;recipes/02-event-driven-sync.md&lt;/code&gt; in the repo, with the &lt;code&gt;claude_sync_watchdog.py&lt;/code&gt; skeleton in &lt;code&gt;examples/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Next.js 15 + React 19 + Tailwind v4 (frontend)&lt;/li&gt;
&lt;li&gt;Node.js custom server (HTTP + WebSocket + SSH proxy on one port)&lt;/li&gt;
&lt;li&gt;FastAPI + PostgreSQL (knowledge backend)&lt;/li&gt;
&lt;li&gt;ssh2 + xterm.js (in-browser terminal)&lt;/li&gt;
&lt;li&gt;watchdog (event-driven sync)&lt;/li&gt;
&lt;li&gt;Proxmox + 8 Ubuntu/Windows/Pi VMs on a single physical box (homelab)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything except the OS is open source. No SaaS. No telemetry. No vendor lock-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the repo actually is
&lt;/h2&gt;

&lt;p&gt;It's a &lt;strong&gt;blueprint, not a turnkey app&lt;/strong&gt;. Reading it should let you build your own version that fits the shape of your fleet, not deploy ours unchanged. Inside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full README walkthrough (English + 繁體中文)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/&lt;/code&gt; — architecture, design decisions, roadmap&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;recipes/&lt;/code&gt; — 7 deep-dive recipes (fleet topology, event-driven sync, WS fan-in, cross-device resume, prompt patterns, repo dashboard)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;examples/&lt;/code&gt; — runnable skeletons (chat server, claude-sync watchdog, resume lock, WS fan-in)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;screenshots/&lt;/code&gt; — every page captured live, plus a tour GIF&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/henryopen/claude-nexus" rel="noopener noreferrer"&gt;https://github.com/henryopen/claude-nexus&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/henryopen/claude-nexus/blob/main/README.zh-TW.md" rel="noopener noreferrer"&gt;繁體中文 README&lt;/a&gt; is also there.&lt;/p&gt;

&lt;p&gt;If your team runs Claude Code on more than one machine and you've felt the same pain, a star on the repo helps other teams find it.&lt;/p&gt;

&lt;p&gt;What's working for your team that we should steal? Open an issue or drop a comment — we read everything.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>opensource</category>
      <category>ai</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
