claude-code-dashboard
Health Warn
- No license — Repository has no license file
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 11 GitHub stars
Code Fail
- process.env — Environment variable access in lib/auth.js
- os.homedir — User home directory access in lib/discovery.js
- fs module — File system access in lib/discovery.js
- os.homedir — User home directory access in lib/files.js
- fs module — File system access in lib/files.js
- network request — Outbound network request in lib/notify.js
- fs.rmSync — Destructive file system operation in lib/ptylink.js
- os.homedir — User home directory access in lib/ptylink.js
- fs module — File system access in lib/ptylink.js
- exec() — Shell command execution in lib/search.js
- fs module — File system access in lib/search.js
- exec() — Shell command execution in lib/sessions.js
- process.env — Environment variable access in lib/sessions.js
- os.homedir — User home directory access in lib/statusline.js
- fs module — File system access in lib/statusline.js
- fs module — File system access in lib/transcript.js
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Self-hosted control room for Claude Code and Codex — persistent sessions you can drive from your phone, Chromebook, or any browser.
Claude Dashboard
Run Claude Code (and Codex) from your phone. Or your Chromebook. Or any browser.
Your PC does the work; you just drive.
This is a self-hosted control room for AI coding agents. The session engine runs on
your Windows PC and the UI opens anywhere — start a task from your desktop, check on
it from your phone on the couch, approve a permission prompt from a coffee shop. The
agents keep running when you close the tab; reattach from any device and the terminal
replays exactly where things stand.
No cloud middleman, no per-token API bills. It drives the Claude Code and Codex CLIs
directly, on your existing subscriptions.
Why it's nice to use
- 📱 Genuinely roamable. One PC, every screen. Sessions are owned by the server,
not by a browser tab, so nothing dies when a device sleeps or drops off Wi-Fi.
Reconnect and the full scrollback is there. - 💬 Chat view or raw console, per session. Read the conversation as clean chat
bubbles — italics, fenced code with a copy button on every block, multi-choice
prompts rendered as real options — or flip to the actual terminal for TUI menus.
One tap between them. - 🤖 Two agents, one brain. Run Claude Code and OpenAI Codex side by side.
With the optional claude-mem plugin they
share a single memory store — what one learns, the other can recall. - 🚦 It tells you what it's doing. A phase pill — Plan, Research, Exec, Debug,
Verify, Done, Blocked — rides above the composer and on every session card, next to
a live context-window gauge. You can see which sessions are thinking and which are
stuck without opening one. (Powered by the bundled status line; see below.) - 🔔 It taps you when it needs you. Push notifications fire when a session
finishes or hits an approval prompt — but only while you're not looking at the
dashboard. Tap the notification and it opens that exact session.
Pushover if you configure it, ntfy
otherwise. - 🟦 See who's waiting at a glance. A session stuck on a question glows in the
sidebar and floats to the top; a working one waves its three dots. - 🎚️ Steer mid-session. Dropdowns in the composer switch a session's permission
mode and its model live — loosen one session for a trusted task, keep another on
a tight leash, bump one to a bigger model — without restarting anything. - 📎 Attach files from the PC, not just the phone. The attach button browses your
actual machine (newest first, thumbnails on) so you can hand a session a screenshot
that never left the desktop. Anything the browser uploads lands in Downloads with a
clean, deduped name. - 🖼️ Artifacts gallery + file browser. Everything a session produced, as
thumbnails — PDFs rendered inline, images, the lot — alongside a real directory
tree with an editor. Upload into the folder you're browsing; download the open
file to whatever device you're reading on. - 🔎 Search that behaves. Full text across every past conversation, with word
matching that folds endings,"quoted phrases"for exact,word*for prefixes,
and/projectto scope a search to one repo. - 📝 Notes that stick to the work. A dated log per session card, plus a general
notes sheet with titles — for the thread you'll pick up tomorrow. - ✅ One-tap commit and push, right next to Send.
- 🖥️ PowerShell sessions too. Same persistent-terminal engine, for when you just
need a shell on the box. - ♻️ Survives restarts. A watchdog auto-restarts a dead server and (optionally)
pushes you if it can't. Sessions resume viaclaude --resume. Rename a session and
the name follows the conversation even when Claude moves it to a new transcript. - 📊 Optional deploy/build badges. Point it at a Netlify site and any GitHub
Actions workflows and the header carries a live dot for each, with a button that
dispatches a fresh build. Entirely opt-in — configure nothing and the row isn't
there. - 🎨 Light, dark, or follow the device. Installable PWA. Material-3 UI that
installs to your home screen and behaves like a native app, split-view on desktop,
pull-to-refresh on mobile.
No build step, no framework, no database — server.js, a handful of files in lib/,
and vanilla JS in public/. It's small enough to read in an afternoon.
How it works
- The PC is the "tmux". Each session is a persistent Windows ConPTY running
claude.exe,codex, or PowerShell, owned byserver.js— not by any browser tab. - Transcripts are the memory.
lib/discovery.jsscans Claude Code's native~/.claude/projects/**/*.jsonlstore (head/tail chunks only — these files get huge)
for the history list, context gauges, model, and branch. The live PTY stream is the
source of truth for status, spinners, and permission prompts. - Sessions say which transcript they're on. A
/clear, a/resume, or a rewind
moves a conversation into a different.jsonlwhile the process and the card stay
put. Rather than guess from timestamps — which gets it wrong, and hands two panes
each other's conversations — every session the dashboard launches reports its own
id back through the status line (lib/ptylink.js). No heuristics, no duplicate
cards. - The frontend is static, served two ways:
- Straight from the PC server (works out of the box, shared-token auth).
- From Netlify with Clerk sign-in, pointing back at the PC over HTTPS — the
roaming setup: one stable URL, real login, no token-in-the-link.
⚠️ Security — read this before you expose it
This dashboard spawns real AI agents with real access to your machine — they read
and write files, run commands, and reach the network. Depending on the permission mode,
they may do so without asking. That is powerful and it is a foot-gun. Treat the URL
to this dashboard as a key to your computer.
Do:
- Keep it on a private network. Tailscale is the intended
setup:tailscale serve --bg 4310gives you an HTTPS URL reachable only from your own
devices. Do not port-forward 4310 to the open internet. - Set a long, random
tokeninconfig.json(or use Clerk, below). If you go the
public-tunnel route, use Clerk withALLOWED_EMAILSandALLOW_TOKEN_AUTH=false— an
auth prompt is then the only thing between the internet and a shell on your PC. - Understand the permission modes.
defaultasks before everything;acceptEdits
lets file edits through but asks before shell commands;auto(the shipped default)
is Claude Code's classifier-gated mode, which waves through what it judges safe and
still stops for the rest;bypassPermissionsasks for nothing. Pick deliberately —
and note that each session's dropdown can change its own.
Know: an AI agent can be steered by text it reads — a poisoned README, a web page, a
dependency. With approvals off and no sandbox, an injected instruction runs immediately.
Keep approvals on for anything you don't fully trust, and don't mount sensitive network
shares you aren't actively working on.
Secrets (config.json, watchdog-config.json, public/env.js) are gitignored and
never committed. Start from the .example.json files.
Quick start (Windows PC)
npm install
copy config.example.json config.json # then edit: set a random "token"
node server.js # or: .\start-dashboard.ps1
Open http://localhost:4310, paste your token once, and you're in. That's the whole
local setup — everything below is optional.
Auto-start on login:
schtasks /create /tn "Claude Dashboard" /sc onlogon /rl limited ^
/tr "powershell -WindowStyle Hidden -File 'C:\path\to\Claude Dashboard\start-dashboard.ps1'"
Prerequisites: Node 18+, Claude Code installed and
signed in. Codex is optional — install and
sign in, and a Codex option appears in New Session automatically.
Roaming setup (optional)
Reach it from anywhere with a real login instead of a token link:
- Expose the PC over HTTPS. Tailscale (private, recommended):
tailscale serve --bg 4310→https://<pc>.<tailnet>.ts.net. The Netlify page is
HTTPS, so the backend must be too (browsers refusews://from an HTTPS page). - Host the frontend on Netlify. Point it at your repo; set
BACKEND_URLto the
HTTPS address above andCLERK_PUBLISHABLE_KEYin Netlify's env vars.netlify.toml
buildspublic/. - Set up Clerk for sign-in — see the table below.
Configuration
Set as environment variables or as camelCase keys in config.json
(see config.example.json):
| var | config.json key | notes |
|---|---|---|
CLERK_SECRET_KEY |
clerkSecretKey |
enables Clerk mode; verifies JWTs (PC only — never on Netlify) |
CLERK_PUBLISHABLE_KEY |
clerkPublishableKey |
must match the Netlify one |
ALLOWED_EMAILS |
allowedEmails |
comma-separated allowlist — set this, or any signed-up Clerk user gets in |
FRONTEND_ORIGIN |
frontendOrigin |
CORS allowlist |
ALLOW_TOKEN_AUTH |
allowTokenAuth |
false locks it to Clerk only |
Also in config.json: port (4310), host, token, model (opus),permissionMode, notify (ntfy topic and/or Pushover keys), pinnedProjects,statusBadges, fileExplorerUrl / fileExplorerPorts. The Claude/Codex binary paths
are auto-detected.
Optional extras
The status line (statusline/)
A two-line status line for Claude Code itself, vendored here because the dashboard
depends on one piece of it: reportPty tells the server which transcript a live
session is actually writing to, which is what keeps a /resume from spawning a
duplicate session card. It's also where the phase pill comes from.
statusline/README.md has the install; node scripts/statusline-sync.js keeps the
copy in ~/.claude/statusline and the one in this repo from drifting apart.
Deploy and build badges (statusBadges)
Opt-in dots in the header, sidebar and mobile session view for whatever you ship:
"statusBadges": {
"netlify": {
"label": "Netlify", "what": "Website deploy",
"siteId": "<API ID from Netlify → Site configuration>",
"url": "https://app.netlify.com/projects/yoursite/deploys"
},
"workflows": [
{ "target": "android", "label": "Android", "what": "Android app build",
"repo": "you/your-repo", "workflow": "build-android.yml", "ref": "main",
"confirm": "Trigger a new Android build on main?" }
]
}
Workflow badges read the latest run through your gh auth login (so private repos
work without handing the dashboard a token), and each badge's ▶ button dispatches a
new run — the workflow must declare workflow_dispatch. The Netlify "last published"
stamp additionally wants the Netlify CLI logged in; without it you get the dot and no
timestamp. Leave netlify null and workflows empty and the whole row disappears.
The watchdog (watchdog.ps1)
Restarts a dead server on a schedule. Copy watchdog-config.example.json towatchdog-config.json to be pushed when a restart isn't sticking; sshHost puts
"how to reach the box" into that alert. With no config file it still restarts, just
silently.
Layout
server.js— Express + WebSocket server, auth, API, session lifecyclelib/sessions.js— persistent PTY manager (scrollback replay, status scraping, permission/model control)lib/discovery.js— transcript scanner (chunked, never loads whole files)lib/transcript.js— incremental chat-message readerlib/ptylink.js— which transcript a live session is on, reported rather than guessedlib/statusline.js— phase + context fill for the chat viewlib/search.js— full-text search across transcripts, with/projectscopinglib/files.js— file browser, editor, uploads and downloadslib/auth.js— Clerk JWT verification + email allowlist, with legacy token fallbacklib/notify.js— presence-gated push (Pushover, ntfy fallback)lib/screen.js— terminal screen model behind the chat viewpublic/— xterm.js + vanilla-JS frontend, installable PWAstatusline/— the vendored Claude Code status line (see above)watchdog.ps1— restarts a dead server, alerts if it can'tscripts/build-static.js— copies vendor files + writesenv.js(postinstall & Netlify build)
Built for personal use and shared in case it's useful. No warranty — you're running
autonomous agents on your own hardware, so read the security section and use good sense.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found