claude-mission-control 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jon Imms
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # Claude Dashboard
2
+
3
+ A local, zero-dependency dashboard for all your [Claude Code](https://claude.com/claude-code) projects. Live sessions pinned at the top — including whether one is waiting on your input — with a card per project below: recent sessions, git status, a 14-day activity sparkline, and one-click resume commands.
4
+
5
+ Everything is read from local files under `~/.claude`, and it never writes to Claude's data — read-only. No API keys to configure. The only automatic network call is to Anthropic's own usage API for your quota meters, authenticated with the Keychain credentials Claude Code already holds (kept in memory, toggleable in settings). Plain Node.js (which Claude Code already requires), zero npm dependencies, macOS.
6
+
7
+ **Requirements:** macOS or Linux (or Windows, experimental — see below), Node.js ≥ 18, Claude Code.
8
+
9
+ ![Claude Dashboard, dark mode — live sessions, unpushed-work strip, and the daily digest](docs/screenshots/dashboard-dark.png)
10
+
11
+ ## Try it in one command
12
+
13
+ ```bash
14
+ npx claude-mission-control
15
+ ```
16
+
17
+ That downloads nothing permanent, starts the server, and prints the URL. Like it? Install it for real below.
18
+
19
+ Homebrew works too:
20
+
21
+ ```bash
22
+ brew tap jonimmswordpressdev/claude-dashboard
23
+ brew trust jonimmswordpressdev/claude-dashboard # newer brew asks once for third-party taps
24
+ brew install claude-dashboard
25
+ brew services start claude-dashboard # always-on, starts at login
26
+ ```
27
+
28
+ ## Install (always-on)
29
+
30
+ ```bash
31
+ ./install.sh
32
+ ```
33
+
34
+ That registers a LaunchAgent (macOS) or a systemd user service (Linux) so the server runs at login and restarts if it dies. Then open <http://127.0.0.1:4517> — in Safari, use **File → Add to Dock** to get a standalone app-like window with its own Dock icon; in Chrome or Edge, use the install-app button in the address bar (the dashboard is a PWA).
35
+
36
+ Uninstall with `./uninstall.sh`.
37
+
38
+ On Linux: logs are in `journalctl --user -u claude-dashboard`, notifications use `notify-send`, and sessions open in kitty, Alacritty, GNOME Terminal, Konsole, or xterm — whichever is installed.
39
+
40
+ ## Run manually instead
41
+
42
+ ```bash
43
+ node server.js
44
+ ```
45
+
46
+ ## New to the terminal? Step-by-step install
47
+
48
+ Five minutes, no experience needed. You type (or paste) each command into the Terminal app and press Return.
49
+
50
+ 1. **Open Terminal.** Press `⌘ Space`, type `terminal`, press Return. A window appears where you can type commands.
51
+ 2. **Check Node.js.** Type `node --version` and press Return. A number like `v22.1.0` means you're set — anything 18 or higher works. If it says "command not found", install Node from [nodejs.org](https://nodejs.org) (download, run the installer, then close and reopen Terminal and check again). If you already use Claude Code, you almost certainly have it.
52
+ 3. **Get the code.** Paste this and press Return:
53
+
54
+ ```bash
55
+ git clone https://github.com/JonImmsWordpressDev/claude-dashboard.git ~/claude-dashboard
56
+ ```
57
+
58
+ That copies the project into a `claude-dashboard` folder in your home folder. No git? Use the green **Code → Download ZIP** button on the GitHub page and unzip it instead.
59
+ 4. **Move into the folder.** Type `cd ~/claude-dashboard` and press Return.
60
+ 5. **Install.** Type `./install.sh` and press Return. That's the whole setup — the dashboard now starts itself every time you log in.
61
+ 6. **Open it.** Go to <http://127.0.0.1:4517> in your browser and bookmark it. In Safari, **File → Add to Dock** turns it into its own app with a Dock icon.
62
+ 7. **One possible prompt.** The first time, macOS may ask about Keychain access for the usage meters. Click **Always Allow**. That reuses the sign-in Claude Code already has; nothing new to log in to.
63
+
64
+ You should see a dark board listing your projects. If a Claude Code session is running, it appears as a row at the top — and the status cell turns amber with **needs you** when Claude is waiting for your input.
65
+
66
+ **Using it day to day** — three things cover most of it:
67
+
68
+ - **Glance at the top row.** That's what's running right now. Amber **needs you** means go back to that terminal — Claude asked a question.
69
+ - **Click any session title** to read the whole conversation. If it's still running, new messages stream in live.
70
+ - **Click `open ⬈`** next to an old session to pick it up again — it opens a terminal in the right folder with the conversation restored.
71
+
72
+ If something looks off, the log is at `~/Library/Logs/claude-dashboard.log`. To remove everything, run `./uninstall.sh` from the same folder.
73
+
74
+ ## What you're looking at
75
+
76
+ - **Departures** — every live `claude` CLI session as a row on the board: start time, project, current task, model, elapsed time, and a split-flap status cell. The cell flips to an amber **needs you** when a session is waiting on your input — readable from across the room.
77
+ - **Digest** — what happened across every project, grouped by day. Each entry shows the session's recap (Claude's own "away summary" where one exists — click to expand), how many tasks it completed, and an open button. Switch the window between day / 3 days / week; collapses out of the way and remembers your choice.
78
+ - **Project cards** — sorted by last activity. Branch chip, `●n` uncommitted changes, `↑n` unpushed commits. The sparkline is prompts per day for the last two weeks. Each session row has an `open ⬈` button that resumes the session in your terminal (new window, right directory) or imports it into the Claude desktop app when it's installed — the **Open in** selector in the header names whichever terminal you've configured (auto-detected on first run). The `⧉` button copies the `claude --resume` command instead.
79
+ - **Header meters** — your plan and rate-limit tier (Free/Pro/Max/Enterprise/API, detected from Claude Code's local account cache), live session and weekly usage from Anthropic's usage API via your existing Claude Code sign-in, plus extra-usage spend. First run may show one macOS Keychain prompt — click Always Allow.
80
+ ![Transcript viewer live-following a running session — this one shows the session that built the dashboard](docs/screenshots/transcript.png)
81
+
82
+ - **Transcripts** — click any session title (cards, digest, search results, project drawer) to read the conversation: your prompts, Claude's replies rendered as markdown, tool calls as compact one-liners, and away-summaries highlighted. Long sessions show the newest ~1200 events. **Running sessions follow live** — a `● live` badge appears, new turns stream in every few seconds, and the view sticks to the bottom unless you've scrolled up to read.
83
+ - **Search** — the header box searches every prompt you've ever sent plus all session titles (Enter to run, 2+ characters). Narrow with `project:name` or `since:7d` / `since:2026-08-01`. Clicking a prompt result opens the transcript scrolled to the matching turn.
84
+ - **Command palette** — `⌘K` from anywhere: fuzzy-jump to any project or session, watch a live session, start a new one, open settings or stats. Arrow keys + Enter.
85
+ - **Stats** — click the weekly bar chart in the header: a 26-week activity heatmap, your busiest hours, a weekly-rhythm grid (prompts by day of week and hour), estimated spend per day for the last 90 days, and an all-time per-model token/cost breakdown. The daily spend history is computed from your existing transcripts, so it's full from the first run.
86
+ - **Export** — any transcript downloads as clean markdown via the `export ⇩` button.
87
+ - **New session** — the `⊕` button on a project card opens a fresh terminal window in that project running `claude`.
88
+ - **Cost trend** — the small bar chart in the header is estimated cost per week for the last 8 weeks (hover for numbers). Costs include subagent tokens.
89
+ - **Models everywhere** — every session shows which model ran it (live cards, digest, session lists), and the stats view breaks down usage per model and per project.
90
+
91
+ ![Stats view: activity heatmap, busiest hours, weekly rhythm, 90-day spend, and per-model cost breakdowns](docs/screenshots/stats.png)
92
+ - **Project details** — click any project's name for a slide-over with its full session list, rendered CLAUDE.md, per-project memory files, skills/agents/commands from `.claude/`, and settings (permissions, MCP servers, allowed tools). Read-only; also a quick audit of which projects are missing instructions or memory. Esc closes.
93
+ - **Unpushed work strip** — an amber band listing every repo with uncommitted changes (`●n`) or unpushed commits (`↑n`), sorted by recent activity. Disappears when everything's clean.
94
+ - **Dormant** — projects with no activity for 60+ days, tucked away at the bottom.
95
+ - Worktree sessions (`.claude/worktrees/…`) are folded into their parent project and badged `⎇`.
96
+ - **Notifications** — the moment any session flips to "waiting for input", you get a macOS notification (with sound) naming the project. Fires once per wait, never on server restart. Mute a single noisy project from its slide-over (the bell button at the top), or disable everything with `CLAUDE_DASH_NOTIFY=0` in the plist. Notifications arrive via Script Editor/osascript — if you don't see them, allow it under System Settings → Notifications.
97
+ - **Cost estimates** — the header shows the estimated list-price value of the last 7 days across all projects; each project card and digest entry shows its share. Computed from token usage in the transcripts at Anthropic list rates (cache reads at 0.1×, cache writes at 1.25×). On a subscription plan these are relative weights, not billed dollars — use them to see where your usage goes. Subagent tokens are included.
98
+ - **Stuck flag** — a session that's "busy" but has written nothing to its transcript for 10+ minutes gets an amber `quiet Nm` cell; at 20 minutes you get one notification. It's a hint, not a verdict — a session waiting on slow background work can look the same.
99
+
100
+ ![Light mode — the same board, printed on paper](docs/screenshots/dashboard-light.png)
101
+
102
+ ## Menu bar companion
103
+
104
+ A SwiftBar plugin lives in `menubar/claude-dash.15s.sh`. The menu bar shows `❯ N` while sessions run, `❯ N⚠` in amber when one is waiting on you, and `❯ N?` when a busy session has gone quiet. The dropdown lists live sessions, repos with unpushed work, the 7-day estimate, and an "Open dashboard" link.
105
+
106
+ Setup: `brew install --cask swiftbar`, then point SwiftBar's plugin folder at this repo's `menubar/` directory. The plugin refreshes every 15 seconds (rename the file to change the interval).
107
+
108
+ ## Settings
109
+
110
+ The ⚙ gear in the header opens settings — no JSON editing required:
111
+
112
+ - **Notifications** on/off (writes `config.json`); per-project mute lives on each project's slide-over
113
+ - **Terminal** for open/new-session buttons: Ghostty, iTerm2, or Terminal.app, auto-detected (`config.json`)
114
+ - **Rename any project** (writes `names.json`) or **hide it** and its whole subtree (writes `ignore.json`), with an unhide list below
115
+
116
+ Everything saves instantly; the underlying files stay hand-editable. Keyboard: `⌘K` for the palette, `/` for search, `Esc` closes anything.
117
+
118
+ ## Getting started with config
119
+
120
+ `names.json`, `ignore.json`, and `config.json` are your local files (gitignored). Copy the `.example` versions to start, or just use the ⚙ settings panel — it creates them for you.
121
+
122
+ ## Friendly names
123
+
124
+ Edit `names.json` to control how projects are titled:
125
+
126
+ ```json
127
+ { "/Users/you/Local Sites/north-ave": "North Avenue" }
128
+ ```
129
+
130
+ Unlisted projects fall back to a cleaned-up folder name. Changes are picked up automatically — no restart needed.
131
+
132
+ ## Hiding projects
133
+
134
+ Edit `ignore.json` — an array of absolute path prefixes. A project is hidden if its path is, or sits under, any listed prefix, so one line hides a whole tree (e.g. all the plugins/themes inside one site). This only hides them from the dashboard, strip, and menu bar; nothing on disk or in `~/.claude` is touched. Picked up automatically.
135
+
136
+ ## Configuration
137
+
138
+ | Env var | Default | Meaning |
139
+ |---|---|---|
140
+ | `CLAUDE_DASH_PORT` | `4517` | Port (change it in the plist too) |
141
+ | `CLAUDE_DASH_DEV` | unset | `1` = re-read index.html on every request |
142
+ | `CLAUDE_DASH_NOTIFY` | unset | `0` = disable macOS notifications |
143
+ | `CLAUDE_DASH_HOST` | `127.0.0.1` | Bind address — see below before changing |
144
+
145
+ The server binds to `127.0.0.1` only by default.
146
+
147
+ ## Windows (experimental — testers wanted)
148
+
149
+ The core is plain cross-platform Node, and Windows support is wired in: paths handle drive letters, notifications use native toasts, and sessions open in Windows Terminal, PowerShell, or cmd (auto-detected). Install from PowerShell in the repo folder:
150
+
151
+ ```powershell
152
+ .\install.ps1
153
+ ```
154
+
155
+ That registers a logon Scheduled Task ("ClaudeDashboard") running the server hidden. Remove it with `.\uninstall.ps1`. The SwiftBar menu bar companion is macOS-only.
156
+
157
+ **Honest label: this is untested on real Windows** — it was written carefully on a Mac. If you run it on Windows, please [open an issue](https://github.com/JonImmsWordpressDev/claude-dashboard/issues) with what worked and what didn't; the first Windows tester shapes this.
158
+
159
+ ## Access from your phone
160
+
161
+ The recommended path is [Tailscale](https://tailscale.com): install it on the Mac and your phone, then run `tailscale serve --bg 4517`. That publishes the dashboard over HTTPS inside your private tailnet while the server itself stays loopback-only — nothing is exposed to the internet or your LAN. Alternatively set `CLAUDE_DASH_HOST=0.0.0.0` in the plist to bind to all interfaces, but understand what that means: anyone on the same network can view the dashboard **and use the open/new-session endpoints, which launch terminal commands on this Mac**. Don't do that on a network you don't fully control.
162
+
163
+ ## Maintenance
164
+
165
+ - Logs: `~/Library/Logs/claude-dashboard.log`
166
+ - Restart after pulling changes: `launchctl kickstart -k gui/$(id -u)/com.claude-dashboard`
167
+ - Tests: `node --test test/pure-logic.test.js`
168
+
169
+ ## Data sources
170
+
171
+ | What | Where |
172
+ |---|---|
173
+ | Live sessions | `~/.claude/sessions/<pid>.json` (liveness re-checked against the pid) |
174
+ | Project registry | `~/.claude.json` `projects` map |
175
+ | Session titles | `~/.claude/projects/**/**.jsonl` (`ai-title` records, head/tail scan only — never full parses) |
176
+ | Activity | `~/.claude/history.jsonl` |
177
+ | Session todos | `~/.claude/tasks/<sessionId>/` |
178
+ | Usage meters | Anthropic usage API via Claude Code's Keychain sign-in (fallback: `~/.claude/.statusline-usage-cache`) |
179
+
180
+ ## Credits
181
+
182
+ Built by [Jon Imms](https://jonimms.com) — WordPress and Gutenberg developer writing about AI-assisted development — pair-programmed with [Claude Code](https://claude.com/claude-code). The story of how it was built is in [the launch post](https://jonimms.com/blog/claude-code-dashboard/). MIT licensed; issues and PRs welcome.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // npx claude-dashboard / global install entry point. The server starts on
4
+ // require and prints its URL.
5
+ require('../server.js');
@@ -0,0 +1,11 @@
1
+ [Unit]
2
+ Description=Claude Dashboard — local dashboard for Claude Code sessions
3
+ After=default.target
4
+
5
+ [Service]
6
+ ExecStart=__NODE_PATH__ __APP_DIR__/server.js
7
+ Restart=on-failure
8
+ RestartSec=3
9
+
10
+ [Install]
11
+ WantedBy=default.target
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
3
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
4
+ <plist version="1.0"><dict>
5
+ <key>Label</key><string>com.claude-dashboard</string>
6
+ <key>ProgramArguments</key><array>
7
+ <string>__NODE_PATH__</string>
8
+ <string>__APP_DIR__/server.js</string>
9
+ </array>
10
+ <key>RunAtLoad</key><true/>
11
+ <key>KeepAlive</key><true/>
12
+ <key>ThrottleInterval</key><integer>30</integer>
13
+ <key>StandardOutPath</key><string>__HOME__/Library/Logs/claude-dashboard.log</string>
14
+ <key>StandardErrorPath</key><string>__HOME__/Library/Logs/claude-dashboard.log</string>
15
+ <key>EnvironmentVariables</key><dict>
16
+ <key>CLAUDE_DASH_PORT</key><string>4517</string>
17
+ </dict>
18
+ </dict></plist>
@@ -0,0 +1,4 @@
1
+ {
2
+ "terminal": "ghostty",
3
+ "notifications": true
4
+ }
@@ -0,0 +1,3 @@
1
+ [
2
+ "/Users/you/Sites/old-abandoned-site"
3
+ ]
package/install.ps1 ADDED
@@ -0,0 +1,46 @@
1
+ # Install Claude Dashboard on Windows (EXPERIMENTAL — testers wanted).
2
+ # Registers a logon Scheduled Task that runs the server hidden.
3
+ # Run from the repo folder in PowerShell: .\install.ps1
4
+ $ErrorActionPreference = 'Stop'
5
+
6
+ $AppDir = Split-Path -Parent $MyInvocation.MyCommand.Path
7
+ $Port = if ($env:CLAUDE_DASH_PORT) { $env:CLAUDE_DASH_PORT } else { '4517' }
8
+
9
+ $Node = (Get-Command node -ErrorAction SilentlyContinue).Source
10
+ if (-not $Node) {
11
+ Write-Error 'node not found on PATH. Install Node.js 18+ first.'
12
+ exit 1
13
+ }
14
+
15
+ # VBScript wrapper so no console window stays open.
16
+ $Vbs = Join-Path $AppDir 'run-hidden.vbs'
17
+ @"
18
+ Set sh = CreateObject("WScript.Shell")
19
+ sh.CurrentDirectory = "$AppDir"
20
+ sh.Run """$Node"" ""$AppDir\server.js""", 0, False
21
+ "@ | Set-Content -Path $Vbs -Encoding ASCII
22
+
23
+ schtasks /End /TN 'ClaudeDashboard' 2>$null | Out-Null
24
+ schtasks /Delete /TN 'ClaudeDashboard' /F 2>$null | Out-Null
25
+ schtasks /Create /TN 'ClaudeDashboard' /SC ONLOGON /TR "wscript.exe `"$Vbs`"" /F | Out-Null
26
+
27
+ # Start it now without waiting for next logon.
28
+ Start-Process wscript.exe -ArgumentList "`"$Vbs`""
29
+
30
+ Write-Host 'waiting for server' -NoNewline
31
+ for ($i = 0; $i -lt 20; $i++) {
32
+ try {
33
+ $r = Invoke-WebRequest -Uri "http://127.0.0.1:$Port/api/health" -UseBasicParsing -TimeoutSec 2
34
+ if ($r.StatusCode -eq 200) {
35
+ Write-Host ''
36
+ Write-Host "OK: claude-dashboard is running at http://127.0.0.1:$Port"
37
+ Write-Host ' It starts automatically at logon (Scheduled Task "ClaudeDashboard").'
38
+ exit 0
39
+ }
40
+ } catch {}
41
+ Write-Host '.' -NoNewline
42
+ Start-Sleep -Milliseconds 500
43
+ }
44
+ Write-Host ''
45
+ Write-Error "server did not respond on port $Port"
46
+ exit 1
package/install.sh ADDED
@@ -0,0 +1,66 @@
1
+ #!/bin/bash
2
+ # Install the Claude Dashboard as an always-on service that starts at login:
3
+ # a LaunchAgent on macOS, a systemd user unit on Linux.
4
+ set -euo pipefail
5
+
6
+ APP_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ LABEL="com.claude-dashboard"
8
+ PLIST_SRC="$APP_DIR/$LABEL.plist"
9
+ PLIST_DST="$HOME/Library/LaunchAgents/$LABEL.plist"
10
+ PORT="${CLAUDE_DASH_PORT:-4517}"
11
+
12
+ NODE_PATH_BIN="$(command -v node || true)"
13
+ if [ -z "$NODE_PATH_BIN" ]; then
14
+ echo "error: node not found on PATH. Install Node.js first." >&2
15
+ exit 1
16
+ fi
17
+
18
+ wait_for_server() {
19
+ echo -n "waiting for server"
20
+ for _ in $(seq 1 20); do
21
+ if curl -sf "http://127.0.0.1:$PORT/api/health" >/dev/null 2>&1; then
22
+ echo
23
+ echo "✓ claude-dashboard is running at http://127.0.0.1:$PORT"
24
+ return 0
25
+ fi
26
+ echo -n "."
27
+ sleep 0.5
28
+ done
29
+ echo
30
+ return 1
31
+ }
32
+
33
+ if [ "$(uname -s)" = "Linux" ]; then
34
+ UNIT_DIR="$HOME/.config/systemd/user"
35
+ mkdir -p "$UNIT_DIR"
36
+ sed -e "s|__NODE_PATH__|$NODE_PATH_BIN|g" \
37
+ -e "s|__APP_DIR__|$APP_DIR|g" \
38
+ "$APP_DIR/claude-dashboard.service" > "$UNIT_DIR/claude-dashboard.service"
39
+ systemctl --user daemon-reload
40
+ systemctl --user enable --now claude-dashboard.service
41
+ if wait_for_server; then
42
+ echo " Logs: journalctl --user -u claude-dashboard"
43
+ exit 0
44
+ fi
45
+ echo "error: server did not respond on port $PORT. Check: journalctl --user -u claude-dashboard" >&2
46
+ exit 1
47
+ fi
48
+
49
+ mkdir -p "$HOME/Library/LaunchAgents" "$HOME/Library/Logs"
50
+
51
+ # LaunchAgents don't inherit your shell PATH — bake in the absolute node path.
52
+ sed -e "s|__NODE_PATH__|$NODE_PATH_BIN|g" \
53
+ -e "s|__APP_DIR__|$APP_DIR|g" \
54
+ -e "s|__HOME__|$HOME|g" \
55
+ "$PLIST_SRC" > "$PLIST_DST"
56
+
57
+ launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true
58
+ launchctl bootstrap "gui/$(id -u)" "$PLIST_DST"
59
+
60
+ if wait_for_server; then
61
+ echo " Open it in Safari and use File → Add to Dock for an app-like window."
62
+ echo " Logs: ~/Library/Logs/claude-dashboard.log"
63
+ exit 0
64
+ fi
65
+ echo "error: server did not respond on port $PORT. Check ~/Library/Logs/claude-dashboard.log" >&2
66
+ exit 1