Skip to content

hoangsonww/Claude-Code-Agent-Monitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

354 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Agent Dashboard for Claude Code

Real-time monitoring platform for Claude Code agent activity πŸš€

A professional dashboard to track and visualize your Claude Code agent sessions, tool usage, and subagent orchestration in real-time. Built with Node.js, Express, React, and SQLite, it integrates directly with Claude Code via its native hook system for seamless session tracking and analytics.

Claude Code Claude Code Plugins Node.js Express React TypeScript Javascript Vite Tailwind CSS SQLite WebSocket Model Context Protocol OpenAPI Swagger i18next i18next Language Detector Mermaid better--sqlite3 React Router Lucide D3.js PostCSS Autoprefixer ESLint Python Docker Podman Vitest React Testing Library SSE Terraform Kubernetes Helm Kustomize Prometheus Grafana Nginx Coralogix OpenTelemetry AWS Google Cloud Azure Oracle Cloud GitLab CI Make GitHub Actions VS Code MIT License

Tip

See also: README-CN.md (δΈ­ζ–‡η‰ˆζœ¬) and README-VI.md (PhiΓͺn bαΊ£n tiαΊΏng Việt) for localized documentation with region-specific tips and best practices.


Table of Contents


Overview

Track sessions, monitor agents in real-time, visualize tool usage, and observe subagent orchestration through a professional dark-themed web interface. Integrates directly with Claude Code via its native hook system.

graph LR
    A["Claude Code<br/>Session"] -->|hooks fire on<br/>tool use / stop| B["Hook Handler<br/>(Node.js script)"]
    B -->|HTTP POST| C["Dashboard Server<br/>(Express + SQLite)"]
    C -->|WebSocket<br/>broadcast| D["Dashboard UI<br/>(React + Tailwind)"]
    style A fill:#6366f1,stroke:#818cf8,color:#fff
    style B fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
    style C fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
    style D fill:#10b981,stroke:#34d399,color:#fff
Loading

In addition to the real-time monitoring dashboard, it also includes a local MCP server implementation in mcp/ that exposes a catalog of tools for introspecting and managing the dashboard itself, making it easy to integrate dashboard operations directly into your Claude Code workflows. There is also an agent extension layer, which provides Claude Code plugins, skills, and subagents for dashboard interaction, analytics, and workflow intelligence.

Star History Chart

Internationalization (i18n)

The UI ships with built-in locale switching for English (en), Chinese (zh), and Vietnamese (vi). Language resources are loaded by namespace and persisted through browser storage for stable user preference across refreshes.

flowchart LR
    A["User selects language<br/>en / zh / vi"] --> B["i18next detector<br/>localStorage -> navigator"]
    B --> C["Resolved language<br/>fallback: en"]
    C --> D["Namespace resources<br/>common/nav/dashboard/..."]
    D --> E["React useTranslation hooks"]
    E --> F["Localized UI + accessibility labels"]
Loading

For full architecture and operational guidance, see docs/I18N.md.

User Interface

Comes with a sleek dark theme, responsive design, and intuitive navigation to explore your agent activity:

Dashboard Overview
πŸ“‘ Dashboard Β· Monitor β€” overview stats, active agent cards, and recent activity feed

Dashboard β€” System Health tab
🩺 Dashboard Β· Health β€” composite health score ring, storage engine donut chart, cache hit / error / success gauges, tool invocation bars, subagent effectiveness, model token distribution, and compaction stats β€” all auto-refreshing every 5 s

Kanban Board β€” Agents view
πŸ“‹ Kanban Board (agents) β€” agents grouped by status across 4 columns: Working / Waiting / Completed / Error. The yellow Waiting column surfaces sessions blocked on user input (permission prompts, end-of-turn, or sitting at a fresh prompt). Each card shows model, cost, and current tool at a glance.

Kanban Board β€” Sessions view
πŸ—‚οΈ Kanban Board (sessions) β€” sessions grouped by status across 5 columns: Active / Waiting / Completed / Error / Abandoned, toggleable from the same page. Hover any column header for a tooltip explaining the lifecycle transition.

Sessions Overview
πŸ“‚ Sessions β€” searchable, filterable, server-paginated table of every recorded session with cost, model, agent count, and duration

Session Detail β€” Agents tab
πŸ€– Session Detail Β· Agents β€” real-time overview tiles (events, tool calls, subagents, compactions, errors, duration), top-tool usage bars, subagent type breakdown, token flow, and the agent hierarchy tree

Session Detail β€” Conversation tab
πŸ’¬ Session Detail Β· Conversation β€” live transcript viewer with markdown rendering, syntax-highlighted code blocks (line numbers + copy), and per-tool styled tool calls

Session Detail β€” Timeline tab
πŸ”¬ Session Detail Β· Timeline β€” chronological event timeline with multi-dimension filters, Pre/Post grouping by `tool_use_id`, and tool-aware payload renderers

Activity Feed Overview
πŸ“° Activity Feed β€” real-time event log with pause / resume, grouping, multi-dimension filters, and a "Session β†’" jump button per row

Analytics Overview
πŸ“Š Analytics β€” token usage by model, tool frequency, activity heatmap, and session trends with live / offline indicator

Workflows Overview
πŸ”€ Workflows β€” agent orchestration DAGs, tool execution Sankey diagrams, collaboration networks, and 11 interactive sections of workflow intelligence

Claude Config Explorer
🧰 Claude Config Explorer β€” 12-tab inspector for everything Claude Code knows about: skills, subagents, slash commands, output styles, plugins (with per-plugin contributions), marketplaces, MCP servers, hooks, settings (with secret-key redaction), memory, keybindings, and statusline. Create / edit / delete on low-risk text-file surfaces with mandatory timestamped backups

Run Claude β€” pre-run config
▢️ Run Claude β€” spawn claude subprocesses right inside the dashboard. Pick mode (Conversation / One-shot), source (new session vs resume from your full history), working directory (autocomplete with recent cwds), model, permission mode, and thinking effort. Same-origin guard prevents browser drive-by spawning

Run Claude β€” live streaming output
πŸ’¬ Run Claude Β· live stream β€” chat-style streaming output with real character-by-character rendering via --include-partial-messages. Tool uses, tool results, and thinking blocks all collapsible. Active runs switcher in the header lets you leave a run in the background and re-attach later. "View session β†’" deep-links into the regular Sessions UI as soon as the session ID is known

Settings Overview
βš™οΈ Settings β€” model pricing rules, hook installation status, data management, notification preferences, and system info

The sidebar provides quick access to the Dashboard, Kanban Board, Sessions list, Activity Feed, Analytics, Workflows, and Settings. Each page is designed to give you deep insights into your Claude Code agent activity with real-time updates and rich visualizations.


Features

The dashboard offers a comprehensive set of features to monitor and analyze your Claude Code sessions and agents:

Feature Description
Dashboard Two tabs persisted in localStorage: Monitor β€” overview stats (6 stat cards), active agent cards with collapsible subagent hierarchy, and recent activity feed with dynamic item counts that fill available viewport height via ResizeObserver. Health β€” composite system health score ring (weighted: 0.4 Γ— success rate + 0.25 Γ— cache hit rate + 0.25 Γ— (100 βˆ’ error rate) + 0.1 Γ— (100 βˆ’ heap %)), storage engine donut chart with record distribution, cache performance / error rate / success rate gauges, tool invocation horizontal bar chart (top 8), subagent effectiveness bars, model token distribution, and compaction impact stats. All health metrics auto-refresh every 5 s from /api/settings/info and /api/workflows. Cursor-following tooltips with viewport edge detection on every chart
Kanban Board Two views with a header toggle (persisted in localStorage): Agents β€” 4 columns (Working / Waiting / Completed / Error) β€” and Sessions β€” 5 columns (Active / Waiting / Completed / Error / Abandoned). The Waiting column maps directly to the persisted waiting status on agents β€” set when Claude Code is sitting at a prompt (fresh session, between turns, or blocked on a permission Notification) and transitions to working the moment the user resumes (UserPromptSubmit / PreToolUse). Each column header shows a ? tooltip explaining lifecycle transitions. Cards fetch by persisted status from the server (effectively unlimited per status), then paginate client-side at 10 cards per column with a "Show more" affordance. WS subscription scopes to the active view (agent_* vs session_* frames) so off-view updates don't trigger refetches.
Sessions Searchable, filterable, server-paginated table of every recorded session. Each page click hits /api/sessions?status=&q=&limit=10&offset=…, so cost computation runs only over the visible page β€” independent of how many sessions exist in the database. The search box (q=) does case-insensitive matching across id / name / cwd on the server with a 300 ms debounce, and the response carries a total count for the paginator UI. Status filter, search, and pagination compose.
Session Detail Per-session real-time overview panel with active-agent banner (current tool + task), six tile counters (events with events/min rate, tool calls, subagents, compactions, errors, ticking duration), top-tool usage bars, subagent type breakdown, stacked token-flow strip, and event-type pill cloud β€” all live-refreshed on hook events. Below it: agent hierarchy tree, full event timeline with multi-dimension filters (status, event type, tool, agent, text search, date range), Pre/Post grouping by tool_use_id, human-readable summary block, tool-aware input/response renderers (terminal for Bash, unified diff for Edit, line-numbered code for Read/Write, match list for Grep, key/value card for MCP tools), and a Conversation tab that renders transcripts with markdown (headings, lists, blockquotes, tables, task lists), syntax-highlighted code blocks (js/ts, python, json, bash, html, css, sql, yaml, diff) with line numbers and copy-to-clipboard, and per-tool styled tool calls (Bash β†’ terminal, Edit β†’ side-by-side old/new, Write β†’ file label, Read β†’ path chip, Grep β†’ pattern card)
Activity Feed Real-time streaming event log with pause/resume, multi-dimension filters (same toolbar as Session Detail plus a Session filter), server-driven "Load more" pagination, debounced filter-aware live refresh preserving the loaded page size, grouping toggle, origin prefix showing project β€Ί session β€Ί subagent, and a "Session β†’" button per row
Analytics Token usage, tool frequency, activity heatmap (centered, day-of-week aligned starting Sunday, day-name tooltips), session trends, live/offline connection indicator
Live Updates WebSocket push -- no polling, instant UI updates
Auto-Discovery Sessions and agents are created automatically from hook events
History Import Imports sessions from ~/.claude/ on startup. Enhanced JSONL extraction: API errors (quota/rate/invalid_request), turn durations, entrypoint (cli/sdk-ts), permission modes, thinking block counts, usage extras (service_tier, speed, inference_geo), tool result errors, and subagent JSONL files (subagents/agent-*.jsonl with .meta.json). Backfills existing sessions on re-import. Recent JSONL files (< 10 min) are imported as "active"
Subagent Hierarchy Collapsible parent-child agent tree on Dashboard and Session Detail. Agents with subagents show expand/collapse chevrons; leaf agents show a dot indicator. Auto-expands when subagents are active
Background Agents Correctly tracks backgrounded subagents without premature completion
Subagent Tool Attribution Subagent-internal tool calls (Read, Bash, Edit, Grep, …) live only in per-subagent JSONL files β€” Claude Code emits no hooks for them. On every SubagentStop the dashboard fires a fire-and-forget scanAndImportSubagents pass that parses each subagents/agent-*.jsonl, pairs tool_use blocks with their matching tool_result by tool_use_id, and emits PreToolUse + PostToolUse events under the subagent's own agent_id. Idempotent (data LIKE '%"tool_use_id":"X"%' dedup) and merges into a live hook-created subagent row when one matches by type + start-time within 30 s, so no parallel <sid>-jsonl-* rows are created. The same path runs on npm run setup startup import for full historical backfill β€” sessions that pre-date the dashboard get full per-subagent tool timelines. Activity Feed and Session Detail render the parent chain as main β€Ί coder β€Ί explorer for nested subagents
Cost Tracking Per-model cost estimation with configurable pricing rules and per-session breakdowns. Compaction-aware token accounting preserves totals across context compressions. Transcript reads are cached with incremental byte-offset updates for efficient token extraction
Transcript Cache Real-time extraction from JSONL transcripts: tokens, compactions, API errors (isApiErrorMessage entries stored as APIError events), turn durations (stored as TurnDuration events), thinking block counts, and usage extras (service_tier, speed, inference_geo). Session metadata is enriched with these fields in real-time
Notifications Full Web Push (VAPID) pipeline for reliable delivery. Arrive even when the tab is backgrounded or the browser is closed. Explicitly configured for macOS audio support. Configurable per-event toggles with subscription management
Update Notifier Server periodically runs a non-blocking git fetch and compares the local checkout to origin/master/origin/main/origin/HEAD. When upstream is ahead, the UI surfaces a modal with the exact git pull && npm run setup command and a one-click Copy button; the Sidebar gets a persistent "Check for updates" button with live badge. The dashboard never pulls or restarts itself β€” the user runs the command in a terminal β€” so the mechanism cannot break dev sessions, pm2/systemd/Docker supervision, or leave orphaned processes
Settings System info, hook status, model pricing management, notification preferences, data export, session cleanup. The Model Pricing section exposes an info popover (the i icon next to the title) explaining how rule lookup works (first matching pattern wins), the SQL-style % wildcard syntax with concrete examples (claude-opus-4-7%, claude-%-haiku, exact ids), and that prices must be updated manually when Anthropic publishes new rates β€” already-stored sessions keep the price applied at ingest time. The CLAUDE_HOME box and Import History panel are fully i18n-driven across en/vi/zh
MCP Server (Local) Enterprise-grade local MCP server in mcp/ with three transport modes (stdio, HTTP+SSE, interactive REPL), 25 typed tools across 6 domains, strict input schemas, retry/backoff, localhost-only API enforcement, and tiered mutation/destructive safety gates. HTTP mode serves Streamable HTTP (2025-11-25) and legacy SSE (2024-11-05) on configurable port. REPL mode provides tab-completed interactive tool invocation with colored output
Workflows D3.js-powered visualization page with 11 interactive sections: agent orchestration DAG, tool execution Sankey diagram, collaboration network, subagent effectiveness (day-of-week sparklines with portal-rendered tooltips that escape the card's overflow:hidden and clamp to the viewport so they never get clipped), detected workflow patterns, model delegation flow, error propagation map (horizontal bars with rate badges, agent type breakdown, API/session error cards), concurrency timeline, session complexity scatter, compaction impact analysis, and per-session drill-in. Rich, i18n-aware tooltips throughout: every chart's section title carries an i icon that opens a structured "What this shows / How to read it / Why it matters" popover; hovering nodes, edges, bars, and bubbles surfaces multi-section tooltips with deterministic, value-dependent interpretations (e.g. share-of-source / share-of-target percentages, success-rate health buckets, family descriptions for Opus / Sonnet / Haiku, timing patterns like front-loaded / mid-session / back-loaded). Each of the six headline stat cards has a bottom-right info popover explaining how the metric is calculated and what its current value means in plain language. Tooltips are DOM-mutated through a single ref per chart with container-level mouseleave fallbacks, so they never lag behind the cursor or stick after re-render. Clicking a row in Detected Workflow Patterns expands an in-place detail panel with the full step sequence, stats grid, a deterministic narrative (loop detection, frequency bucket), and a practical suggestion. Status filter tabs (Active Only / Completed / All) filter all 11 sections. Cross-filtering, JSON export, and real-time WebSocket auto-refresh with 3-second debounce
Compaction Tracking Detects /compact events from JSONL transcripts, creates compaction agents and events. Backfills legacy compactions on startup. A periodic scanner (cadence derived from DASHBOARD_STALE_MINUTES) catches compactions even when no hooks fire. Shares the transcript cache so no duplicate file reads occur
Subsessions/Resumed Sessions Automatically reactivates sessions when new events arrive, correctly handles /resume and orphaned sessions. Periodic sweep (every ΒΌ of DASHBOARD_STALE_MINUTES, clamped to 60 s – 5 min) marks abandoned sessions that slip past event-based detection
Pre-Existing Session Detection Sessions already running when the server starts are imported as "active" (based on recent JSONL file modification). Stop events also reactivate imported completed/abandoned sessions, so the first hook from an in-progress session always surfaces it on the dashboard
Responsive Design Mobile-friendly layouts with stacking grids, scrollable tables, and collapsible sidebar
UI Localization Built-in language switching with translated UI copy and accessibility labels for English (en), Chinese (zh), and Vietnamese (vi). Coverage now extends end-to-end through the Workflows tooltips: stat-card calculations and value-bucket interpretations, per-chart "What / How to read / Why" popovers, every graph's hover tooltip (orchestration, tool flow, pipeline, model delegation, concurrency), the Workflow Patterns detail-panel narratives and suggestions, the Settings β†’ Model Pricing info popover, the CLAUDE_HOME panel, and the entire Import History flow
Seed Data Built-in seed script for demos and development
Statusline Color-coded CLI statusline showing model, context usage, git branch, per-direction tokens, and session cost (USD)
Model Name Formatting Human-friendly model names throughout the UI: raw identifiers like claude-opus-4-7-20260101 or claude-opus-4-7[1m] display as "Claude Opus 4.7" or "Claude Opus 4.7 (1M)". Handles Claude, GPT, and Gemini families with automatic version dot-joining, date/latest suffix stripping, provider prefix removal, and context-window tag formatting. Settings page retains raw names for pricing rule configuration
Plugin Marketplace Official Claude Code plugin marketplace with 5 plugins (ccam-analytics, ccam-productivity, ccam-devtools, ccam-insights, ccam-dashboard). 18 skills, 4 agents, 3 CLI tools, 2 hook configs. All grounded in actual data model β€” token baselines, pricing engine, workflow intelligence (11 datasets), session metadata. Install via claude plugin marketplace add
Run Claude Spawn claude subprocesses directly from the dashboard with a chat-style streaming UI. Two modes: Conversation (multi-turn β€” stdin stays open, follow-up turns are piped as stream-json envelopes) and One-shot (headless, single prompt β†’ single response). Conversation mode also supports resuming any existing session via claude --resume <id> β€” pick from your full sessions history with a searchable picker. The unified active-runs / history modal also offers two zero-config jump buttons: Resume on any past conversation row spawns claude --resume <id> immediately and seeds the chat with the prior transcript so you land in the live view with full context (no need to retype a prompt β€” the spawn idles on stdin until you send a follow-up); View on any past one-shot row loads the captured transcript inline into the run viewer as read-only (no spawn β€” same panel, no Stop/follow-up controls). Active runs switcher in the header lets you leave a run in the background, start another, and re-attach later. Re-attach is durable: the client reconciles the spawner's in-memory envelope log (?envelopes=1) with the session's on-disk JSONL transcript and prefers whichever has more user/assistant messages, so navigating away from a resumed run and coming back keeps the full prior history visible (the spawner only sees post-spawn turns; the transcript file has prior + current). Model dropdown (Opus 4.7 / 1M / Sonnet 4.6 / Haiku 4.5 / custom), permission-mode picker with explicit bypassPermissions warning, thinking-effort field (low / medium / high β€” wired to --effort), cwd autocomplete pre-filled with the dashboard's own cwd plus recent session cwds. Real character-by-character streaming via --include-partial-messages, plus a client-side typewriter smoothing layer that drips each text_delta / thinking_delta through requestAnimationFrame so even short replies (where claude bundles the whole answer into one or two chunks) appear to type in. The merge code keeps the _streaming flag and the delta-accumulated content array intact when claude's canonical assistant envelope arrives mid-stream, so thinking blocks aren't dropped at completion. WebSocket dispatch wraps each envelope in flushSync so React 18's auto-batching doesn't collapse bursts of deltas into a single render. TUI parity (Tier 1): a collapsible limitations banner that minimizes to a slim pill (never disappears) explaining what stream-json mode can and can't do vs. the terminal TUI; a prompt editor with slash-command autocomplete with tiered scoring (exact name β†’ starts-with β†’ word-boundary β†’ contains β†’ subsequence β†’ description-contains) that lists user / project / plugin commands (executed client-side via template expansion before send) and surfaces built-in CLI commands like /clear, /model, /config with a "CLI only β€” won't run from here" badge; @-file references with debounced fuzzy-search across the run's cwd (skipping node_modules, .git, dist, build, etc.); a live context-window / token meter showing input + output + cache-read tokens and running cost, computed from stream_event and result.usage envelopes during live streaming and from finalized assistant usage blocks (input / output / cache-read / cache-creation) when seeded from a transcript on resume / view / re-attach, so the meter populates immediately instead of sitting at 0/200k. Progress bar goes indigo β†’ amber β†’ red at 80% / 95% of the model's context cap; a status header with the active model, effort, permission mode, cwd, session ID, envelope count, and elapsed time. Autocomplete dropdowns open upward so they don't collide with the cwd picker below. Live / Offline indicator next to the title. Same-origin guard on the route prevents browser drive-by spawning. Concurrency is effectively uncapped by default (sanity ceiling of 10000 to prevent fork-bomb footguns from a buggy client; the terminal TUI has no cap and neither do we). Set RUN_MAX_CONCURRENT if you want a real ceiling. Spawned sessions fire the same hooks any claude process does, so they show up automatically in Sessions / Analytics / Kanban / Workflows β€” and Sessions / SessionDetail surface a green β–Ά Run badge / banner that links back to the Run page for any session that's currently being driven from there
Claude Config Explorer A 12-tab inspector at /cc-config for everything Claude Code knows about: skills, subagents, slash commands, output styles, plugins (with per-plugin contributions count + author/license/homepage from plugin.json), marketplaces (with plugin counts read from each marketplace.json), MCP servers, hooks (with ~/.claude/hooks/ script listing), settings (structured key-value view + raw JSON toggle, secret-key redaction), memory (CLAUDE.md files), keybindings (grouped by context with <kbd> chips), and statusline (config + script content). For low-risk text-file surfaces (skills / agents / commands / output styles / memory) the page supports create / edit / delete with mandatory timestamped backups atomically written outside the directories Claude Code scans, plus a Backups modal with auto-built mv restore commands. Plugins, MCP, hooks-in-settings, and settings.json files stay read-only with explainer banners + copy-able CLI commands so the user knows the exact command to run themselves. Live updates: a cc-watcher running on the server uses fs.watch on ~/.claude/ (recursive where the platform supports it) plus ~/.claude.json, debounced at 500 ms, to broadcast a cc_config_changed WebSocket message whenever Claude Code config changes β€” either via dashboard mutations or external tools (CLI installing a plugin, manually editing settings.json, dropping a new skill). The page subscribes and refetches automatically; a Live / Offline pill next to the title shows WebSocket status
Progressive Web App (PWA) Three independent PWAs β€” dashboard, landing page, and wiki β€” each with its own Web App Manifest and Service Worker. Install any of them to your home screen / dock for a standalone, chrome-less experience. The dashboard SW caches the app shell and static assets (cache-first), serves navigation network-first, and preserves the existing VAPID push-notification pipeline. The landing-page and wiki SWs precache their respective shells and lazy-cache images on first visit, enabling offline access after a single load. All manifests use SVG icons (favicon.svg) with sizes="any" for modern browsers, and include apple-mobile-web-app-capable + apple-touch-icon meta tags for iOS standalone mode

Quick Start

Prerequisites

  • Node.js >= 18.0.0 (22+ recommended)
  • npm >= 9.0.0

1. Install

git clone https://github.com/hoangsonww/Claude-Code-Agent-Monitor.git
cd Claude-Code-Agent-Monitor
npm run setup

2. Configure Claude Code Hooks

npm run install-hooks

This adds hook entries to ~/.claude/settings.json that forward events to the dashboard. Existing hooks are preserved.

3. Start

# Development (hot reload on both server and client)
npm run dev

# Production (single process, built client)
npm run build && npm start

Tip

Makefile alternative β€” all commands are also available via make if you have it installed on your system. Run make help to see every target, or use shortcuts like make dev, make build, make test, etc.

4. Open

Mode URL
Development http://localhost:5173
Production http://localhost:4820

5. Optional: Build and run the local MCP server

npm run mcp:install
npm run mcp:build
npm run mcp:start              # stdio (default β€” for MCP host integration)
npm run mcp:start:http         # HTTP + SSE server on port 8819
npm run mcp:start:repl         # interactive CLI with tab completion

For stdio mode, configure your MCP host (Claude Code / Claude Desktop / other MCP clients):

  • command: node
  • args: ["<ABSOLUTE_PATH>/mcp/build/index.js"]

For HTTP mode, point remote MCP clients at http://127.0.0.1:8819/mcp (Streamable HTTP) or http://127.0.0.1:8819/sse (legacy SSE).

See mcp/README.md for full host configuration, transport details, safety flags, and tool catalog.

Optional: Seed Demo Data

npm run seed

Creates 8 sample sessions, 23 agents, and 106 events so you can explore the UI immediately.

Alternative: Docker / Podman

A Dockerfile and docker-compose.yml are included. Both Docker and Podman are supported.

With Docker Compose:

docker compose up -d --build

With Podman Compose:

CLAUDE_HOME="$HOME/.claude" podman compose up -d --build

With plain Docker or Podman (no Compose):

# Docker
docker build -t agent-monitor .
docker run -d --name agent-monitor \
  -p 4820:4820 \
  -v "$HOME/.claude:/root/.claude:ro" \
  -v agent-monitor-data:/app/data \
  agent-monitor

# Podman
podman build -t agent-monitor .
podman run -d --name agent-monitor \
  -p 4820:4820 \
  -v "$HOME/.claude:/root/.claude:ro" \
  -v agent-monitor-data:/app/data \
  agent-monitor

The dashboard is then available at http://localhost:4820.

Volume mounts:

Mount Purpose
~/.claude:/root/.claude:ro Read legacy session history for import
agent-monitor-data:/app/data Persist the SQLite database across restarts

Important

Note: Claude Code hooks must still point to a running hook-handler process on the host. The container itself does not receive hooks β€” run npm run install-hooks on the host to configure hooks that POST to http://localhost:4820.


How It Works

The dashboard integrates with Claude Code via its native hook system to provide real-time monitoring of agent activity. Here's an overview of the architecture and data flow:

sequenceDiagram
    participant CC as Claude Code
    participant HH as Hook Handler
    participant API as Express Server
    participant DB as SQLite
    participant WS as WebSocket
    participant UI as React Client

    CC->>HH: stdin (JSON event)
    HH->>API: POST /api/hooks/event
    API->>DB: Insert/update records
    API->>WS: Broadcast update
    WS->>UI: Push message
    UI->>UI: Re-render component

    Note over CC,HH: Hooks fire on SessionStart,<br/>PreToolUse, PostToolUse,<br/>Stop, SubagentStop,<br/>SessionEnd, Notification.<br/>Compaction detected from JSONL
    Note over API,DB: Transactional writes<br/>with auto session/agent creation
    Note over WS,UI: ~0ms latency,<br/>no polling
Loading

Important

See ARCHITECTURE.md for a deep dive into the server architecture, database schema, API routes, WebSocket design, client routing, hook handler flow, deployment modes, and detailed lifecycle diagrams for sessions and agents.

Hook Lifecycle

  1. Claude Code fires a hook on session start, tool use, turn end, subagent completion, and session exit
  2. Hook Handler (scripts/hook-handler.js) reads the JSON event from stdin and POSTs it to the API. Fails silently with a 5s timeout so it never blocks Claude Code
  3. Server processes the event inside a SQLite transaction:
    • Auto-creates sessions and main agents on first contact
    • Detects Agent tool calls to track subagent creation
    • On SessionStart, stamps the session and main agent's awaiting_input_since so a fresh CLI sitting at the prompt lands in Waiting immediately
    • On UserPromptSubmit (user hits enter), clears the waiting flag and promotes the main agent to working β€” the only reliable signal that text-only assistant turns have started, since they emit no PreToolUse
    • Sets agent to "working" on PreToolUse (also clears the waiting flag), keeps it working through PostToolUse
    • On Stop (Claude finishes responding), main agent goes to "waiting" β€” Claude finished its turn, ball is in the user's court. Background subagents continue running. Session stays active. Stop with stop_reason=error marks the agent error and the session error
    • On a permission Notification (matched by message pattern: permission, waiting for input, needs your approval, …), sets the agent to waiting and stamps awaiting_input_since
    • SubagentStop deliberately does NOT clear the waiting flag (a backgrounded subagent finishing tells us nothing about the human)
    • Marks subagents completed individually via SubagentStop. After res.json() returns, fires a fire-and-forget scanAndImportSubagents pass that walks the session's subagents/agent-*.jsonl files, pairs tool_use ↔ tool_result blocks by tool_use_id, and emits PreToolUse + PostToolUse events under each subagent's own agent_id β€” closing the gap where subagent-internal tool calls would otherwise be invisible to the dashboard
    • On SessionEnd (CLI process exits), drops the waiting flag. If the session is in error, the error state is preserved; otherwise marks all agents + the session as completed
    • On SessionStart, any other active session with no activity for DASHBOARD_STALE_MINUTES (default 180 = 3 h, env-overridable) is automatically marked "abandoned" with its agents completed. This handles /resume inside a session, Ctrl+C, and other scenarios where a session is orphaned without a clean SessionEnd
    • Reactivates completed/error/abandoned sessions when new work events arrive (session resumed). Stop and SubagentStop events also reactivate completed/abandoned sessions β€” this handles pre-existing sessions imported before the server started, where the first hook event may be a Stop
    • Error recovery: only UserPromptSubmit and PreToolUse can recover a session from error back to active β€” indicating the user actively retried
    • Detects conversation compaction (isCompactSummary entries in the JSONL transcript) and creates Compaction agents + events. Token baselines are preserved across compactions so no usage is lost. Transcript reads use a shared stat-based cache with incremental byte-offset reads β€” only new bytes appended since the last read are parsed, giving ~50x speedup for long sessions
    • Extracts API errors (isApiErrorMessage entries: quota limits, rate limits, invalid_request) and raw type: "error" responses from JSONL transcripts, stored as APIError events. Turn durations (system subtype turn_duration) are stored as TurnDuration events. Tool result errors (toolUseResult.is_error) are tracked as ToolError events
    • Error detection watchdog β€” a background timer runs every 15 seconds, scanning active sessions with no recent hook events (>10 s stale). It re-reads their transcript files looking for API errors (auth failures, rate limits, quota exhaustion), derives transcript paths from session cwd for imported sessions without transcript_path in event data, and marks sessions/agents as error when API errors are found. This catches cases where the Claude CLI does not fire a hook after an API error (e.g., 401 auth failures where the CLI shows the error and waits)
    • A periodic server sweep catches abandoned sessions and new compactions that slipped past event-based detection (e.g., /compact fires no hook, /resume within seconds of session creation). Cadence is derived from DASHBOARD_STALE_MINUTES (ΒΌ of the threshold, clamped to 60 s – 5 min). The sweep shares the transcript cache with the hook handler, avoiding duplicate I/O. Abandoned session cleanup also evicts the transcript cache entry to bound memory
  4. WebSocket broadcasts the change to all connected clients
  5. UI receives the update and re-renders the affected components in real-time with no polling.

Agent State Machine

Persisted statuses: working | waiting | completed | error. The awaiting_input_since column is supplementary β€” it tracks when the agent started waiting and is used for duration display, but waiting is now a real persisted status.

stateDiagram-v2
    [*] --> waiting: ensureSession (first hook)
    waiting --> working: PreToolUse / UserPromptSubmit
    working --> working: PostToolUse (tool completed)
    working --> waiting: Stop, non-error
    working --> waiting: Notification (input prompt)
    waiting --> error: Stop with error
    working --> error: Stop with error
    waiting --> error: API error detected (watchdog)
    working --> error: API error detected (watchdog)
    error --> working: UserPromptSubmit / PreToolUse (recovery)
    working --> completed: SessionEnd
    waiting --> completed: SessionEnd

    note right of waiting
        Agent is between turns or
        awaiting user input
    end note
Loading

Session State Machine

Persisted statuses: active | completed | error | abandoned. The Waiting session state is a UI overlay (status=active with awaiting_input_since set).

stateDiagram-v2
    [*] --> waiting: SessionStart (status=active + flag)
    waiting --> active: UserPromptSubmit / PreToolUse / PostToolUse
    active --> waiting: Stop, non-error (flag re-stamped)
    active --> waiting: Permission Notification (agent β†’ waiting)
    active --> error: Stop, stop_reason=error
    active --> error: API error detected (watchdog)
    waiting --> error: API error detected (watchdog)
    error --> active: UserPromptSubmit / PreToolUse (recovery)
    waiting --> completed: SessionEnd (CLI exited)
    active --> completed: SessionEnd (CLI exited)
    error --> error: SessionEnd (preserves error)
    waiting --> abandoned: Stale > DASHBOARD_STALE_MINUTES (default 180)
    active --> abandoned: Stale > DASHBOARD_STALE_MINUTES
    completed --> active: Session resumed (new work event)
    error --> active: Session resumed (new work event)
    abandoned --> active: Session resumed (new work event)
    completed --> [*]
    error --> [*]
    abandoned --> [*]
Loading

Cost Calculation Flow

flowchart LR
    TU["token_usage rows<br/>(per session Γ— model)"] --> GROUP["Group by model"]
    PR["model_pricing rules<br/>(pattern-based)"] --> SORT["Sort by specificity<br/>(longest pattern first)"]
    GROUP --> MATCH{"Match model<br/>to pricing rule"}
    SORT --> MATCH
    MATCH --> CALC["cost = Ξ£ (tokens / 1M) Γ— rate<br/>for input, output, cache_read, cache_write"]
    CALC --> RESULT["{ total_cost, breakdown[] }"]
    style TU fill:#003B57,stroke:#005f8a,color:#fff
    style PR fill:#6366f1,stroke:#818cf8,color:#fff
    style RESULT fill:#10b981,stroke:#34d399,color:#fff
Loading

Important

The cost calculation flow is based on token usage and model pricing rules. Ensure your pricing rules are up-to-date to reflect accurate costs. Update the model pricing table via the Settings page to maintain accurate cost tracking - the dashboard does not automatically fetch pricing updates from external sources. Once you set the pricing rules, the dashboard applies them retroactively to all sessions for consistent cost reporting.


Configuration

Environment Variable Default Description
DASHBOARD_PORT 4820 Port for the Express server
CLAUDE_DASHBOARD_PORT 4820 Port used by hook handler to reach the server
NODE_ENV development Set to production to serve the built client
DASHBOARD_UPDATE_CHECK (enabled) Set to 0 / false / off to disable periodic git upstream checks
DASHBOARD_UPDATE_CHECK_INTERVAL_MS 300000 (5 min) Interval between automatic checks; floor 60 000 ms. Users can also click Check now in the update modal or in the sidebar to run one on demand.

For git clones, the server periodically git fetches origin and compares your checkout to origin/master, origin/main, or origin/HEAD. When you are behind, a message appears in the server terminal and a modal appears in the UI with the exact command to run. The dashboard never pulls or restarts itself β€” you copy the command, run it in a terminal, then restart the server the same way you started it.


npm Scripts

Command Description
npm run setup Install server and client dependencies
npm run update:pull-setup git pull --ff-only then npm run setup (manual upgrade)
npm run dev Start server (watch mode) + client (Vite HMR) concurrently
npm run dev:server Start only the Express server with --watch
npm run dev:client Start only the Vite dev server
npm run build Build the React client to client/dist/
npm start Start production server (serves built client)
npm run install-hooks Configure Claude Code hooks in ~/.claude/settings.json
npm run seed Populate database with sample data
npm run import-history Import legacy sessions from ~/.claude/ (also runs on startup)
npm run clear-data Delete all sessions, agents, events, and token usage
npm run mcp:install Install dependencies for local MCP package (mcp/)
npm run mcp:build Build MCP server TypeScript into mcp/build/
npm run mcp:start Start MCP server (stdio transport β€” for MCP hosts)
npm run mcp:start:http Start MCP server (HTTP + SSE transport on port 8819)
npm run mcp:start:repl Start MCP server (interactive REPL with tab completion)
npm run mcp:dev Run MCP server in dev mode (tsx, stdio)
npm run mcp:dev:http Run MCP server in dev mode (tsx, HTTP + SSE)
npm run mcp:dev:repl Run MCP server in dev mode (tsx, interactive REPL)
npm run mcp:typecheck Type-check MCP source without emitting build output
npm run mcp:docker:build Build MCP container image with Docker (agent-dashboard-mcp:local)
npm run mcp:podman:build Build MCP container image with Podman (localhost/agent-dashboard-mcp:local)

Agent Extensions

This repository includes a comprehensive extension layer for both Claude Code and Codex:

  • Claude Code: CLAUDE.md, .claude/rules/, .claude/skills/
  • Claude subagents: .claude/agents/
  • Codex: AGENTS.md, .codex/rules/, .codex/agents/, .codex/skills/

Extension Architecture

graph TD
    USER["Developer"]
    CLAUDE["Claude Code"]
    CODEX["Codex"]
    MEMORY["CLAUDE.md + .claude/rules/*"]
    C_SKILLS[".claude/skills/*"]
    AGENTS_MD["AGENTS.md"]
    X_RULES[".codex/rules/*.rules"]
    X_AGENTS[".codex/agents/*.toml"]
    X_SKILLS[".codex/skills/*"]

    USER --> CLAUDE
    USER --> CODEX
    CLAUDE --> MEMORY
    CLAUDE --> C_SKILLS
    CODEX --> AGENTS_MD
    CODEX --> X_RULES
    CODEX --> X_AGENTS
    CODEX --> X_SKILLS
Loading

Claude Code Layer

Codex Layer


MCP Integration

This project includes a local, production-grade MCP server at mcp/ that exposes dashboard operations as tools for AI agents. It supports three transport modes to suit different integration scenarios.

MCP Transport Modes

flowchart LR
    subgraph Transports["Transport Modes"]
        STDIO["stdio\n(default)"]
        HTTP["HTTP + SSE\n(port 8819)"]
        REPL["Interactive REPL\n(terminal CLI)"]
    end

    subgraph Protocols["Wire Protocols"]
        P1["JSON-RPC\nstdin/stdout"]
        P2["Streamable HTTP (2025-11-25)\nLegacy SSE (2024-11-05)"]
        P3["Direct invocation\ntab completion + colored output"]
    end

    STDIO --> P1
    HTTP --> P2
    REPL --> P3

    style STDIO fill:#6366f1,stroke:#818cf8,color:#fff
    style HTTP fill:#f59e0b,stroke:#fbbf24,color:#000
    style REPL fill:#a855f7,stroke:#c084fc,color:#fff
Loading
Mode Command Use Case
stdio npm run mcp:start Claude Code, Claude Desktop, IDE MCP hosts
HTTP npm run mcp:start:http Remote MCP clients, web integrations, multi-session
REPL npm run mcp:start:repl Ops debugging, manual tool invocation, local admin

MCP REPL

MCP Architecture

graph LR
    HOST["MCP Host<br/>(Claude Code / Claude Desktop)"]
    HTTP_CLIENT["Remote MCP Client"]
    OPERATOR["Operator CLI"]

    MCP_STDIO["MCP Server<br/>stdio"]
    MCP_HTTP["MCP Server<br/>HTTP :8819"]
    MCP_REPL["MCP Server<br/>REPL"]

    API["Dashboard API<br/>Express /api/*"]
    DB["SQLite<br/>data/dashboard.db"]

    HOST -->|"stdin/stdout"| MCP_STDIO
    HTTP_CLIENT -->|"POST /mcp Β· GET /sse"| MCP_HTTP
    OPERATOR -->|"interactive CLI"| MCP_REPL

    MCP_STDIO --> API
    MCP_HTTP --> API
    MCP_REPL --> API
    API --> DB

    style HOST fill:#6366f1,stroke:#818cf8,color:#fff
    style HTTP_CLIENT fill:#f59e0b,stroke:#fbbf24,color:#000
    style OPERATOR fill:#a855f7,stroke:#c084fc,color:#fff
    style MCP_STDIO fill:#0f766e,stroke:#14b8a6,color:#fff
    style MCP_HTTP fill:#0f766e,stroke:#14b8a6,color:#fff
    style MCP_REPL fill:#0f766e,stroke:#14b8a6,color:#fff
    style API fill:#339933,stroke:#5cb85c,color:#fff
    style DB fill:#003B57,stroke:#005f8a,color:#fff
Loading

MCP Tool Surface

graph TD
    ROOT["MCP Tools"]
    OBS["Observability<br/>health, stats, analytics,<br/>system info, export, snapshot"]
    SES["Sessions<br/>list/get/create/update"]
    AGT["Agents<br/>list/get/create/update"]
    EVT["Events & Hooks<br/>list events, ingest hook events"]
    PRC["Pricing & Cost<br/>rules CRUD, total/session cost, reset defaults"]
    MNT["Maintenance<br/>cleanup, reimport, reinstall hooks, clear-all (guarded)"]

    ROOT --> OBS
    ROOT --> SES
    ROOT --> AGT
    ROOT --> EVT
    ROOT --> PRC
    ROOT --> MNT
Loading

MCP Safety Model

flowchart TD
    CALL["tools/call"] --> VALIDATE["zod input validation"]
    VALIDATE --> TYPE{"Tool type?"}
    TYPE -->|Read-only| EXEC["Execute"]
    TYPE -->|Mutation| M_FLAG{"ALLOW_MUTATIONS?"}
    M_FLAG -->|No| DENY1["❌ Reject"]
    M_FLAG -->|Yes| DEST{"Destructive?"}
    DEST -->|No| EXEC
    DEST -->|Yes| D_FLAG{"ALLOW_DESTRUCTIVE?"}
    D_FLAG -->|No| DENY2["❌ Reject"]
    D_FLAG -->|Yes| TOKEN{"confirmation_token?"}
    TOKEN -->|Invalid| DENY3["❌ Reject"]
    TOKEN -->|Valid| EXEC
    EXEC --> RESULT["Return tool result"]

    style EXEC fill:#339933,stroke:#5cb85c,color:#fff
    style DENY1 fill:#dc2626,stroke:#f87171,color:#fff
    style DENY2 fill:#dc2626,stroke:#f87171,color:#fff
    style DENY3 fill:#dc2626,stroke:#f87171,color:#fff
Loading

MCP Operational Modes

  • Read-only mode (default): MCP_DASHBOARD_ALLOW_MUTATIONS=false
  • Admin mode: MCP_DASHBOARD_ALLOW_MUTATIONS=true
  • Destructive mode: requires both:
    • MCP_DASHBOARD_ALLOW_MUTATIONS=true
    • MCP_DASHBOARD_ALLOW_DESTRUCTIVE=true
    • tool input confirmation_token: "CLEAR_ALL_DATA"

Full details: mcp/README.md


API Reference

All endpoints return JSON. Error responses follow the shape { error: { code, message } }.

OpenAPI / Swagger

Method Path Description
GET /api/openapi.json Raw OpenAPI 3.0 spec
GET /api/docs Interactive Swagger UI documentation

The OpenAPI document is generated from server/openapi.js, and Swagger UI is served directly by the backend.

Swagger UI

Health

Method Path Description
GET /api/health Returns { status: "ok", timestamp }

Sessions

Method Path Query Params Description
GET /api/sessions status, q, limit, offset List sessions with agent counts and per-session cost. q does case-insensitive search across id / name / cwd. limit defaults to 50, max 10000. Response includes total for paginators.
GET /api/sessions/:id -- Session detail with agents and events
GET /api/sessions/:id/stats -- Aggregated counts powering the Session Detail overview panel: events, events-by-type, top tool usage, error count, agent type/status counts, subagent type breakdown, token totals, time range
GET /api/sessions/:id/transcripts -- List available JSONL transcripts for the session (main + subagents + compactions)
GET /api/sessions/:id/transcript agent_id, limit, offset, after, before Stream messages from a specific transcript with cursor-based pagination. Assistant usage includes input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens so the Run page meter can hydrate fully on resume / re-attach
POST /api/sessions -- Create session (idempotent on id)
PATCH /api/sessions/:id -- Update session status/metadata

Agents

Method Path Query Params Description
GET /api/agents status, session_id, limit, offset List agents with filters
GET /api/agents/:id -- Single agent detail
POST /api/agents -- Create agent
PATCH /api/agents/:id -- Update agent status/task/tool

Events

Method Path Query Params Description
GET /api/events session_id, limit, offset List events (newest first)

Stats

Method Path Description
GET /api/stats Aggregate counts, status distributions, WS connections

Analytics

Method Path Description
GET /api/analytics Token/tool/session aggregates for charts and trend views

Hooks

Method Path Description
POST /api/hooks/event Receive and process a Claude Code hook event

Hook event payload:

{
  "hook_type": "PreToolUse",
  "data": {
    "session_id": "abc-123",
    "tool_name": "Bash",
    "tool_input": { "command": "ls -la" }
  }
}

Pricing

Method Path Description
GET /api/pricing List all pricing rules
PUT /api/pricing Create or update a pricing rule
DELETE /api/pricing/:pattern Delete a pricing rule
GET /api/pricing/cost Total cost across all sessions
GET /api/pricing/cost/:id Cost breakdown for a specific session

Workflows

Method Path Description
GET /api/workflows Aggregate workflow data (orchestration, tools, patterns). Optional ?status=active|completed query param filters all 11 data sections by session status
GET /api/workflows/session/:id Per-session drill-in (agent tree, tool timeline, events)

Settings

Method Path Description
GET /api/settings/info System info, DB stats, hook status
POST /api/settings/clear-data Delete all sessions, agents, events, token usage
POST /api/settings/reimport Re-import legacy sessions from ~/.claude/
POST /api/settings/reinstall-hooks Reinstall Claude Code hooks
POST /api/settings/reset-pricing Reset pricing to defaults
GET /api/settings/export Export all data as JSON download
POST /api/settings/cleanup Abandon stale sessions, purge old data

Claude Config Explorer (/api/cc-config)

Read-only inspection of every Claude Code configuration surface, plus carefully-gated mutations for low-risk text-file artifacts. All write paths create timestamped backups under <root>/cc-config-backups/<type>/ before mutating.

Method Path Description
GET /api/cc-config/overview Roots (claude home, project .claude, project root, ~/.claude.json) + counts for every surface
GET /api/cc-config/skills Skills under <scope>/.claude/skills/<name>/SKILL.md with parsed frontmatter; ?scope=user|project|all
GET /api/cc-config/agents Subagents <scope>/.claude/agents/*.md
GET /api/cc-config/commands Slash commands <scope>/.claude/commands/*.md
GET /api/cc-config/output-styles Output styles <scope>/.claude/output-styles/*.md
GET /api/cc-config/plugins Installed plugins from ~/.claude/plugins/installed_plugins.json, joined with enabledPlugins from settings; each entry includes contributes (count of skills/agents/commands/hooks/output-styles inside the plugin's install dir) plus plugin.json metadata
GET /api/cc-config/marketplaces Registered marketplaces from known_marketplaces.json, enriched with each marketplace's own marketplace.json (plugin count, owner, description)
GET /api/cc-config/mcp MCP servers from ~/.claude.json (top-level + per-project) and settings.json
GET /api/cc-config/hooks Hooks aggregated across user / project / project-local settings.json files
GET /api/cc-config/hook-scripts Files in ~/.claude/hooks/ (the helper scripts referenced by hooks.<event>.command)
GET /api/cc-config/keybindings ~/.claude/keybindings.json parsed into context-grouped key/action pairs
GET /api/cc-config/statusline settings.json.statusLine config + the actual statusline.py / statusline-command.sh content if present
GET /api/cc-config/settings User / project / project-local settings JSON, with secret-like keys (matching /token|secret|password|api[_-]?key|auth/i) replaced by "<redacted>"
GET /api/cc-config/memory CLAUDE.md files at user + project scope
GET /api/cc-config/file?path=… Body of a single file (path-contained to CLAUDE_HOME / project .claude / project CLAUDE.md)
GET /api/cc-config/backups Listing of all timestamped backups, optionally filtered ?scope=&type=
PUT /api/cc-config/file Create or overwrite a text-file artifact. Body: { scope, type, name?, content }. Auto-backs-up if file exists. Atomic temp + rename. 256 KB content cap, strict name regex
DELETE /api/cc-config/file Backup-then-delete a text-file artifact. Skill dirs are backed up whole (preserving bundled assets) before recursive removal

Run Claude (/api/run)

HTTP surface for spawning and supervising claude subprocesses from the dashboard. Same-origin guard on every route β€” browser requests must come from a localhost origin; missing-Origin (CLI/curl) requests pass.

Method Path Description
GET /api/run List all in-memory run handles (live + recently finished); also returns maxConcurrent and activeCount
GET /api/run/binary Probe whether claude is on PATH and where it lives β€” used by the UI to surface a clear error before spawning
GET /api/run/cwds Suggested working directories: dashboard server cwd, $HOME, and recent cwds from the sessions table
GET /api/run/files?cwd=…&q=… Fuzzy file search inside cwd for the Run page's @-file autocomplete. Skips node_modules, .git, dist, build, .next, .cache, coverage, etc. Cwd is required and must exist; results are capped and ranked by basename match
POST /api/run Spawn a new run. Body: { prompt, mode: "headless"|"conversation", cwd?, model?, permissionMode?, resumeSessionId?, effort? }. Headless puts prompt in argv via -p and closes stdin. Conversation pipes the prompt over stdin as a stream-json envelope and keeps stdin open for follow-ups. resumeSessionId (conversation only) adds --resume <id>; when set, prompt may be empty β€” the spawner skips the initial stdin write and claude idles on the resumed conversation until the user posts a follow-up via POST /api/run/:id/message. effort (low / medium / high) maps to --effort. The spawner always passes --output-format stream-json --verbose --include-partial-messages so the UI can render character-by-character deltas. Concurrency is effectively uncapped (default ceiling 10000 β€” override with RUN_MAX_CONCURRENT)
GET /api/run/:id Current handle state. ?envelopes=1 includes the in-memory envelope log so the UI can replay history when re-attaching
POST /api/run/:id/message Send a follow-up turn to a running conversation (conversation mode only). Body: { text }
DELETE /api/run/:id Stop a run. SIGTERM, escalating to SIGKILL after 5 s

Output streams over the existing dashboard WebSocket as three message types: run_stream (parsed stream-json envelope, including stream_event deltas from --include-partial-messages), run_status (status transitions), run_input_ack (stdin write confirmed). The Config Explorer page subscribes to a fourth message β€” cc_config_changed β€” broadcast by server/lib/cc-watcher.js (via fs.watch on ~/.claude/) and by routes/cc-config.js after every successful PUT/DELETE, with payload { source: "dashboard"|"fs", action?, scope?, type?, name?, paths? }. The Sessions list and SessionDetail page poll /api/run (and listen for run_status) to badge any session currently being driven by an in-flight Run with a clickable β–Ά Run indicator that links back to /run.

Import History

Bring existing Claude Code sessions into the dashboard from three different sources, all funneled through the same parser the server uses for live ingestion so imported tokens, per-model cost, compactions, subagents, tool use, and turn durations match real-time capture bit-for-bit. Re-imports are idempotent: sessions are keyed by ID and compaction baselines preserve pre-compaction token totals, so running the importer twice never double-counts usage or cost.

flowchart LR
    subgraph Sources
      A1["Default folder<br/>~/.claude/projects"]
      A2["Custom folder<br/>any absolute path"]
      A3["Uploaded files<br/>.jsonl / .meta.json /<br/>.zip / .tar(.gz) / .gz"]
    end

    A1 -->|POST /api/import/rescan| R["server/routes/import.js"]
    A2 -->|POST /api/import/scan-path| R
    A3 -->|POST /api/import/upload<br/>multipart| R

    R -->|archive extract<br/>+ path-traversal guard<br/>+ zip-bomb cap| X["server/lib/archive.js"]
    R -->|walks recursively| I["importFromDirectory<br/>(scripts/import-history.js)"]
    X --> I
    I -->|same pipeline as live<br/>hook ingestion| P["parseSessionFile +<br/>importSession"]
    P -->|prepared statements,<br/>in one transaction| D[("SQLite<br/>sessions / agents / events /<br/>token_usage")]
    I -.->|import.progress<br/>throttled| W["WebSocket /ws"]
    W -.-> U["Settings β†’ Import History<br/>progress bar + result card"]

    style A1 fill:#6366f1,stroke:#818cf8,color:#fff
    style A2 fill:#6366f1,stroke:#818cf8,color:#fff
    style A3 fill:#6366f1,stroke:#818cf8,color:#fff
    style R fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
    style X fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
    style I fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
    style P fill:#f59e0b,stroke:#fbbf24,color:#000
    style D fill:#10b981,stroke:#34d399,color:#fff
    style U fill:#a855f7,stroke:#c084fc,color:#fff
Loading

Routes

Method Path Description
GET /api/import/guide OS-aware paths, archive command, supported extensions, step instructions
POST /api/import/rescan Rescan the default ~/.claude/projects directory
POST /api/import/scan-path Scan an absolute directory (body { path }); walks recursively
POST /api/import/upload Multipart upload of .jsonl, .meta.json, .zip, .tar(.gz), .gz

Supported inputs. Loose JSONL (.jsonl) session transcripts, their companion .meta.json sidecars, and archives (.zip, .tar, .tar.gz/.tgz, plain .gz) containing any nested directory layout. Both canonical Claude Code layouts are recognized automatically: <project>/<sessionId>/subagents/agent-*.jsonl (default) and <project>/subagents/<sessionId>/agent-*.jsonl (alternative).

Accuracy guarantees. Sessions are deduplicated by UUID; re-running the importer is always safe. The compaction baseline_input / baseline_output / baseline_cache_read / baseline_cache_write columns preserve token counts from before a transcript was compacted, so re-ingesting a post-compaction JSONL never erases historical cost.

Safety. Archive extraction validates every entry against path traversal (absolute paths and .. segments are rejected). A configurable extraction cap (CCAM_IMPORT_MAX_EXTRACT_BYTES, default 4 GB) stops zip/tar/gzip bombs. Upload size is capped per file (CCAM_IMPORT_MAX_BYTES, default 1 GB) and per request (CCAM_IMPORT_MAX_FILES, default 2000). All staging directories are per-request and reclaimed in finally, including when multer rejects all files up front.

Progress. Import activity is broadcast over the existing WebSocket as import.progress messages (phase: start / scan / extract / parse / complete / error), throttled to avoid flooding the channel on large imports.

UI. Use the Settings β†’ Import History panel for a guided, drag-and-drop experience with step-by-step instructions, live progress, and a post-import summary showing imported / enriched / skipped / error counts.

Import History UI

WebSocket

Connect to ws://localhost:4820/ws to receive real-time push messages:

{
  "type": "agent_updated",
  "data": { "id": "...", "status": "working", "current_tool": "Edit" },
  "timestamp": "2026-03-05T15:43:01.800Z"
}

Message types: session_created, session_updated, agent_created, agent_updated, new_event

stateDiagram-v2
    [*] --> Connecting: Component mounts
    Connecting --> Connected: onopen
    Connected --> Closed: onclose / onerror
    Closed --> Connecting: setTimeout(2000ms)
    Connected --> [*]: Component unmounts
    Closed --> [*]: Component unmounts
Loading

Hook Events

The dashboard processes these Claude Code hook types:

Hook Type Trigger Dashboard Action
SessionStart Claude Code session begins Creates session and main agent. Stamps awaiting_input_since so a fresh session lands in Waiting. Reactivates resumed sessions. Abandons orphaned sessions with no activity for DASHBOARD_STALE_MINUTES (default 180)
UserPromptSubmit User hits enter on a prompt Clears the waiting flag and promotes the main agent to working β€” the only signal that text-only assistant turns have started, since they emit no PreToolUse
PreToolUse Agent starts using a tool Clears the waiting flag, sets agent to working, sets current_tool. If tool is Agent, creates a subagent record
PostToolUse Tool execution completed Clears the waiting flag (handles permission-prompt approvals where the Notification stamped it mid-tool). Clears current_tool. Agent stays working
Stop Claude finishes responding Non-error: main agent β†’ waiting β€” Claude finished its turn, ball is in the user's court. stop_reason=error: marks the agent and session error. Background subagents keep running
SubagentStop Background agent finished Matches and completes the subagent by description, type, or task. Deliberately does NOT clear the waiting flag β€” a subagent finishing tells us nothing about the human. Triggers a fire-and-forget JSONL scan (scanAndImportSubagents) that emits per-tool PreToolUse + PostToolUse events under the subagent's own agent_id so the Timeline shows every tool the subagent ran, not just the spawn marker
Notification Agent notification Logs event. Permission/input-prompt messages set the agent to waiting and stamp awaiting_input_since (matched by pattern: permission, waiting for input, needs your approval, …). Compaction notifications are tagged as Compaction events. Triggers a browser notification if enabled
SessionEnd Claude Code CLI process exits Drops the waiting flag. If the session is already in error, the error state is preserved; otherwise marks all agents and the session as completed
Compaction /compact detected in JSONL Creates a compaction subagent (type compaction) and Compaction event. Detected via isCompactSummary entries in the transcript JSONL. Also detected by periodic scanner for active sessions
APIError API error in JSONL transcript Extracted from isApiErrorMessage entries (quota, rate limit, invalid_request) and raw type: "error" responses. Now immediately marks the session and agent as error β€” previously recorded as events without changing status. Stored as event with error details
TurnDuration Turn timing in JSONL transcript Extracted from system subtype turn_duration messages with durationMs. Stored as event for turn-level timing analysis
ToolError Tool result error in JSONL Extracted from toolUseResult.is_error entries. Tracks tool-level failures for error propagation analysis

Browser Notifications

The dashboard supports persistent browser notifications via Web Push (VAPID) for real-time alerts even when the dashboard tab is not focused or the browser is backgrounded.

How It Works

  1. Enable notifications in the Settings page via the master toggle
  2. Grant browser permission when prompted β€” this registers a Service Worker and creates a push subscription
  3. Configure which events trigger notifications:
Event Default Description
New session starts On Fires when a new Claude Code session is created
Claude finished responding Off Fires on Stop events when Claude finishes a response turn
Session closed Off Fires on SessionEnd when the CLI process exits
Session errors On Fires when a session ends with an error
Subagent spawned Off Fires when a background subagent is created

Additionally, any Notification hook event from Claude Code triggers a browser notification regardless of the per-event toggles (as long as the master toggle is enabled).

Notifications Architecture

  • VAPID Pipeline: Uses web-push on the server for secure message delivery. VAPID keys are auto-generated and stored in data/vapid-keys.json.
  • Service Worker: A dedicated worker (client/public/sw.js) handles incoming push events and displays notifications with silent: false to ensure audio playback on macOS.
  • Subscriptions: Browser-specific endpoints are stored in the push_subscriptions table in SQLite.
  • Persistence: Notifications arrive even if the browser is closed, as the Service Worker operates in the background.
  • Test notification: button in Settings lets you verify the VAPID pipeline and audio playback.

PWA & Offline Support

The project ships three independent Progressive Web Apps β€” one each for the dashboard, landing page, and wiki. Each has its own manifest.json and Service Worker so the browser treats them as separate installable applications.

Surface Manifest Service Worker Caching Strategy
Dashboard (client/) client/public/manifest.json client/public/sw.js Precaches app shell (/, manifest, favicon). Static assets (JS/CSS bundles) are cached on first load (cache-first). Navigation requests are network-first with offline fallback to cached /. API (/api/*), WebSocket (/ws), and Vite HMR requests are never cached. Push notification handlers are preserved alongside the caching logic.
Landing page (root) manifest.json sw.js Precaches the HTML shell, favicon, and OG image. Screenshot PNGs are lazy-cached on first view (cache-first) to avoid a heavy initial precache. Navigation is network-first with offline fallback.
Wiki (wiki/) wiki/manifest.json wiki/sw.js Precaches index.html, style.css, script.js, manifest, and favicon. Fully offline-capable after one visit. Network-first HTML, cache-first for CSS/JS.

Cache lifecycle: All three SWs call skipWaiting() on install and delete stale caches on activate (keyed by version strings like dashboard-v1, landing-v1, wiki-v1). Bumping the version constant forces a clean refresh.

iOS support: All three HTML files include <meta name="apple-mobile-web-app-capable" content="yes"> and <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> for standalone home-screen mode on Safari.

Icons: Manifests reference favicon.svg with sizes="any" and type="image/svg+xml" β€” supported in Chrome 107+, Firefox 110+, Edge 107+. Apple touch icons also use the SVG favicon.


Update Notifier

The dashboard watches its own git checkout and surfaces a modal whenever the canonical default branch has commits ahead of HEAD. Branch- and fork-aware: if you have an upstream remote (the standard convention for forks), it's preferred over origin; the chosen remote's master/main/HEAD is the comparison ref. The manual_command adapts to your situation β€” git pull --ff-only only when your branch actually tracks the canonical ref, otherwise a git fetch (and a fast-forward merge in the fork case) so the command never lies. Users get the exact command to run in a terminal β€” the server never pulls or restarts itself, which keeps the mechanism portable across dev sessions, pm2/systemd/launchd/Docker supervision, and remote deployments.

Dashboard update modal with copy-to-clipboard command

How It Works

flowchart LR
    S["Server startup"] --> SCHED["Update scheduler<br/>poll every 5 min"]
    SCHED --> PICK["Pick canonical remote<br/>upstream then origin"]
    PICK --> FETCH["git fetch remote prune<br/>execFile 120s timeout"]
    FETCH --> CMP["rev-list HEAD vs<br/>remote master main HEAD"]
    CMP --> FP["Fingerprint changed?"]
    FP -->|yes| WS["broadcast<br/>update_status"]
    FP -->|no| IDLE["skip broadcast"]
    WS --> CLIENT["UpdateNotifier<br/>+ Sidebar badge"]

    CHECK["POST updates check"] --> FETCH
    STATUS["GET updates status"] -.-> CMP

    style WS fill:#6366f1,stroke:#818cf8,color:#fff
    style CLIENT fill:#10b981,stroke:#34d399,color:#fff
Loading

A single check is cheap (git fetch <remote> --prune against the canonical remote β€” upstream if configured, else origin), wrapped with execFile (no shell) and a 120s timeout. Failures β€” offline network, non-git install, no remotes configured, unresolvable upstream ref β€” all return soft payloads (e.g. fetch_error: "...") rather than throwing, so a flaky remote never blocks the dashboard.

UI Surfaces

Surface Behavior
Modal (client/src/components/UpdateNotifier.tsx) Appears when update_available === true and the user hasn't already dismissed this specific remote_sha. Shows commits-behind, the tracked ref, an optional situation_note (when on a feature branch / fork the note explains why the command differs), the copy-pastable command, and three buttons: Copy command (primary), Check now, Dismiss. ESC and backdrop clicks dismiss. Keyed by remote_sha in localStorage, so a newer upstream commit re-opens the modal automatically.
Sidebar button (client/src/components/Sidebar.tsx) Always-visible "Check for updates" button in the footer. Emerald border + green badge dot when behind, amber when the last check hit a fetch error. Clicking it clears any prior dismissal, then fires POST /api/updates/check.
Server terminal When the scheduler transitions from "up to date" to "behind," it prints a framed block to stdout with the command so users running headless still see it.

API Surface

Endpoint Purpose
GET /api/updates/status Read-only check: runs git fetch against the canonical remote, compares HEAD to its default branch, returns the payload.
POST /api/updates/check Same check, but also broadcasts update_status over WebSocket so all connected clients update at once.

Both endpoints return the same payload shape:

{
  "git_repo": true,
  "update_available": true,
  "repo_root": "/Users/you/Claude-Code-Agent-Monitor",
  "remote_ref": "upstream/master",
  "canonical_remote": "upstream",
  "current_branch": "master",
  "tracking_upstream": "origin/master",
  "tracks_canonical": false,
  "situation": "fork_or_diverged_tracking",
  "local_sha": "abc1234...",
  "remote_sha": "def5678...",
  "commits_behind": 3,
  "manual_command": "cd \"/...\" && git fetch upstream && git merge --ff-only upstream/master && npm run setup",
  "situation_note": "You're on 'master' tracking 'origin/master'. This command fast-forwards your branch from upstream/master (the canonical default).",
  "message": "3 commit(s) on upstream/master not in your checkout."
}

situation is one of tracking_canonical (typical clone on the default branch β€” git pull --ff-only works), fork_or_diverged_tracking (local branch name matches canonical, but tracks a different remote β€” git fetch <remote> && git merge --ff-only <ref>), feature_branch (off the default branch β€” fetch only, integration left to the user), or detached_head.

What's Intentionally Not Here

There is no POST /api/updates/apply and no self-restart helper, by design. Self-updating a process from inside itself is unreliable without an external supervisor β€” npm run dev (concurrently), npm start, pm2, systemd, launchd, and Docker each need different restart logic, and git pull / npm install failures on a dying server have no clean rollback path. Detection-only keeps behaviour predictable across every supervisor, every OS, and every branch state, while still closing the "when do I need to pull?" information gap; the user owns the actual update in their own shell.

Configuration

Env Var Default Notes
DASHBOARD_UPDATE_CHECK enabled Set to 0 / false / off to disable the scheduler entirely.
DASHBOARD_UPDATE_CHECK_INTERVAL_MS 300000 (5 min) Interval between automatic checks. Floor is 60 000 ms β€” values below are clamped.

VS Code Extension

The Claude Code Agent Monitor is available as a first-class VS Code extension, allowing you to monitor your AI agents without leaving your editor.

VS Code Extension Screenshot

πŸš€ Key Features

  • Live Sidebar: Dedicated Activity Bar view showing real-time Agent Health (Working, Waiting, Completed, etc.).
  • Usage Analytics: Track total tokens, live USD costs, and event counts directly in the sidebar.
  • Status Bar Integration: Quick-glance pulse monitor in the bottom bar showing active sessions and agents.
  • Deep Navigation: One-click access to specific dashboard views (Kanban, Analytics, Settings) or recent sessions.
  • Integrated Tab: Opens the full monitoring dashboard as a native VS Code webview tab.

πŸ“¦ Installation & Setup

  1. Open the vscode-extension directory.
  2. Install the Marketplace extension or package it yourself using vsce package.
  3. Ensure your local dashboard server is running (npm run dev).
  4. Click the Radar icon in the VS Code Activity Bar to get started.

For detailed developer configuration, see the .vscode and vscode-extension directories.

Tip

Extension on VS Code Marketplace: Claude Code Agent Monitor


Data Storage

  • Engine: SQLite 3 via better-sqlite3 (optional) or Node.js built-in node:sqlite
  • Location: data/dashboard.db
  • Journal mode: WAL (concurrent reads during writes)
  • Reset: Delete data/dashboard.db to clear all data

Entity Relationship Diagram

erDiagram
    sessions ||--o{ agents : has
    sessions ||--o{ events : has
    sessions ||--o{ token_usage : tracks
    agents ||--o{ events : generates
    agents ||--o{ agents : spawns

    sessions {
        TEXT id PK "UUID"
        TEXT name "Human-readable label"
        TEXT status "active|completed|error|abandoned"
        TEXT cwd "Working directory"
        TEXT model "Claude model ID"
        TEXT started_at "ISO 8601"
        TEXT ended_at "ISO 8601 or NULL"
        TEXT metadata "JSON blob"
        TEXT awaiting_input_since "ISO 8601 or NULL β€” set when Waiting"
    }

    agents {
        TEXT id PK "UUID or session_id-main"
        TEXT session_id FK
        TEXT name "Main Agent β€” {session name} or subagent description"
        TEXT type "main|subagent"
        TEXT status "working|waiting|completed|error"
        TEXT current_tool "Active tool or NULL"
        TEXT awaiting_input_since "ISO 8601 or NULL β€” supplementary wait timestamp"
    }

    events {
        INTEGER id PK "Auto-increment"
        TEXT session_id FK
        TEXT agent_id FK
        TEXT event_type "PreToolUse|PostToolUse|Stop|etc"
        TEXT tool_name "Tool that fired the event"
        TEXT created_at "ISO 8601"
    }

    token_usage {
        TEXT session_id PK "Composite PK with model"
        TEXT model PK "Model identifier"
        INTEGER input_tokens
        INTEGER output_tokens
        INTEGER cache_read_tokens
        INTEGER cache_write_tokens
    }

    model_pricing {
        TEXT model_pattern PK "SQL LIKE pattern"
        TEXT display_name "Human-readable name"
        REAL input_per_mtok "USD per M input tokens"
        REAL output_per_mtok "USD per M output tokens"
        REAL cache_read_per_mtok "USD per M cache reads"
        REAL cache_write_per_mtok "USD per M cache writes"
    }
Loading

Plugin Marketplace

Extend Claude Code with official Agent Monitor plugins β€” analytics, productivity tools, developer utilities, AI-powered insights, and dashboard connectivity.

Add the marketplace

claude plugin marketplace add hoangsonww/Claude-Code-Agent-Monitor

Available plugins

Plugin Install command Skills
ccam-analytics claude plugin install ccam-analytics@hoangsonww-claude-code-agent-monitor session-report, cost-breakdown, usage-trends, productivity-score
ccam-productivity claude plugin install ccam-productivity@hoangsonww-claude-code-agent-monitor daily-standup, weekly-report, sprint-summary, workflow-optimizer
ccam-devtools claude plugin install ccam-devtools@hoangsonww-claude-code-agent-monitor session-debug, hook-diagnostics, data-export, health-check
ccam-insights claude plugin install ccam-insights@hoangsonww-claude-code-agent-monitor pattern-detect, anomaly-alert, optimization-suggest, session-compare
ccam-dashboard claude plugin install ccam-dashboard@hoangsonww-claude-code-agent-monitor dashboard-status, quick-stats + MCP server

CLI tools included

  • ccam-stats β€” Terminal dashboard (sessions, costs, tokens with compaction baselines)
  • ccam-doctor β€” System diagnostics (API, database, hooks, data freshness)
  • ccam-export β€” Data export (JSON, CSV) for sessions, events, analytics, costs

Example usage

# In Claude Code, after installing a plugin:
/ccam-analytics:session-report latest
/ccam-analytics:cost-breakdown this week
/ccam-productivity:daily-standup today
/ccam-insights:pattern-detect tools
/ccam-dashboard:quick-stats

πŸ“– Full documentation: docs/plugins.md


Statusline

A standalone CLI statusline utility for Claude Code that displays model name, user, working directory, git branch, context window usage bar, per-direction token counts, and session cost -- all color-coded with ANSI escape sequences.

nguyens6@host ~/agent-dashboard/client | Sonnet 4.6 | main | β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘ 79% | 3↑ 2↓ 156586c | $0.4231
Segment Color Example
Model Cyan Sonnet 4.6
User Green nguyens6
CWD Yellow ~/agent-dashboard
Git branch Magenta main
Context bar Green / Yellow / Red β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘ 79%
Tokens Green / Cyan / Dim 3↑ 2↓ 156586c (green ↑ in, cyan ↓ out, dim c cache)
Cost (USD) Green / Yellow / Red $0.4231 (session total β€” shown on API and subscription plans)

Cost color thresholds: green under $5, yellow $5–$20, red $20+.

See statusline/README.md for installation instructions.

Statusline Demo


Server Architecture

graph TD
    INDEX["server/index.js<br/>Express app + HTTP server"]
    DB["server/db.js<br/>SQLite + prepared statements"]
    WS["server/websocket.js<br/>WS server + broadcast"]
    HOOKS["routes/hooks.js<br/>Hook event processing"]
    SESSIONS["routes/sessions.js"]
    AGENTS["routes/agents.js"]
    EVENTS["routes/events.js"]
    STATS["routes/stats.js"]
    ANALYTICS["routes/analytics.js"]
    PRICING["routes/pricing.js<br/>Cost calculation"]
    SETTINGS["routes/settings.js<br/>System management"]
    WORKFLOWS["routes/workflows.js<br/>Workflow visualizations"]

    INDEX --> DB & WS
    INDEX --> HOOKS & SESSIONS & AGENTS & EVENTS & STATS & ANALYTICS & PRICING & SETTINGS & WORKFLOWS
    HOOKS --> DB & WS
    SESSIONS --> DB & WS
    AGENTS --> DB & WS
    EVENTS --> DB
    STATS --> DB
    ANALYTICS --> DB
    PRICING --> DB
    SETTINGS --> DB
    WORKFLOWS --> DB

    style INDEX fill:#6366f1,stroke:#818cf8,color:#fff
    style DB fill:#003B57,stroke:#005f8a,color:#fff
    style WS fill:#10b981,stroke:#34d399,color:#fff
Loading

Client Routing

graph LR
    ROOT["/ (index)"] --> DASH["Dashboard<br/>stats + agents + events"]
    K["/kanban"] --> KANBAN["KanbanBoard<br/>agents/sessions toggle"]
    S["/sessions"] --> SESS["Sessions<br/>server-paginated table"]
    D["/sessions/:id"] --> DETAIL["SessionDetail<br/>agents + timeline + cost"]
    A["/activity"] --> ACT["ActivityFeed<br/>streaming event log"]
    AN["/analytics"] --> ANALYTICS["Analytics<br/>tokens + heatmap + trends"]
    WF["/workflows"] --> WORKFLOWS["Workflows<br/>D3 visualizations + drill-in"]
    CC["/cc-config"] --> CCCONFIG["CcConfig<br/>12-tab Claude Code config inspector + editor"]
    RUN["/run"] --> RUNPAGE["Run<br/>spawn / resume / stream Claude subprocess"]
    ST["/settings"] --> SETTINGS["Settings<br/>pricing + notifications + hooks + export"]
    NF["/*"] --> NOTFOUND["NotFound<br/>404 catch-all"]

    ALL["All routes"] --> LAYOUT["Layout wrapper<br/>(Sidebar + Outlet)"]

    style ALL fill:#6366f1,stroke:#818cf8,color:#fff
    style LAYOUT fill:#1a1a28,stroke:#2a2a3d,color:#e4e4ed
Loading

Hook Handler Flow

flowchart TD
    START["Claude Code fires hook"] --> STDIN["Read stdin to EOF"]
    STDIN --> PARSE{"Parse JSON?"}
    PARSE -->|Success| POST["POST to 127.0.0.1:4820<br/>/api/hooks/event"]
    PARSE -->|Failure| WRAP["Wrap raw input as JSON"]
    WRAP --> POST
    POST --> RESP{"Response?"}
    RESP -->|200 OK| EXIT0["exit(0)"]
    RESP -->|Error| EXIT0
    RESP -->|Timeout 3s| DESTROY["Destroy request"] --> EXIT0
    SAFETY["Safety net: setTimeout 5s"] --> EXIT0

    style EXIT0 fill:#10b981,stroke:#34d399,color:#fff
    style START fill:#6366f1,stroke:#818cf8,color:#fff
Loading

Deployment Modes

We support both development and production deployment modes with different process architectures:

graph LR
    subgraph dev["Development β€” 2 processes"]
        D_CMD["npm run dev"] --> D_SRV["Express :4820<br/>node --watch"]
        D_CMD --> D_VITE["Vite :5173<br/>HMR"]
        D_BROWSER["Browser"] --> D_VITE
        D_VITE -->|"proxy /api + /ws"| D_SRV
    end

    subgraph prod["Production β€” 1 process"]
        P_BUILD["npm run build"] --> P_DIST["client/dist/"]
        P_START["npm start"] --> P_SRV["Express :4820<br/>serves static + API"]
        P_BROWSER["Browser"] --> P_SRV
    end

    style D_VITE fill:#646CFF,stroke:#818cf8,color:#fff
    style D_SRV fill:#339933,stroke:#5cb85c,color:#fff
    style P_SRV fill:#339933,stroke:#5cb85c,color:#fff
    style P_DIST fill:#646CFF,stroke:#818cf8,color:#fff
Loading

Optional local MCP sidecar (supports stdio, HTTP+SSE, and REPL transports):

graph LR
    subgraph "MCP Transport Options"
        M_STDIO["MCP Server (stdio)<br/>npm run mcp:start"]
        M_HTTP["MCP Server (HTTP)<br/>npm run mcp:start:http<br/>:8819"]
        M_REPL["MCP Server (REPL)<br/>npm run mcp:start:repl"]
    end

    H["MCP Host"] -->|"stdin/stdout"| M_STDIO
    RC["Remote Client"] -->|"POST /mcp Β· GET /sse"| M_HTTP
    OP["Operator"] -->|"interactive CLI"| M_REPL

    M_STDIO --> D["Dashboard Server<br/>:4820"]
    M_HTTP --> D
    M_REPL --> D

    style M_STDIO fill:#0f766e,stroke:#14b8a6,color:#fff
    style M_HTTP fill:#0f766e,stroke:#14b8a6,color:#fff
    style M_REPL fill:#0f766e,stroke:#14b8a6,color:#fff
Loading

Cloud Deployment

The deployments/ directory provides cloud-agnostic, enterprise-grade infrastructure for deploying the dashboard to production. Supports Helm, Kustomize, and Terraform across AWS, GCP, Azure, and OCI with blue-green, canary, and rolling release strategies.

graph TB
  subgraph "Deployment Methods"
    HELM["⎈ Helm Chart<br/>Parameterized installs"]
    KUST["πŸ“¦ Kustomize<br/>Overlay-based patching"]
    TF["πŸ—οΈ Terraform<br/>Full cloud provisioning"]
  end

  subgraph "Cloud Providers"
    AWS["☁️ AWS<br/>ECS Fargate + ALB"]
    GCP["☁️ GCP<br/>Cloud Run + GCLB"]
    AZ["☁️ Azure<br/>ACI + App Gateway"]
    OCI["☁️ OCI<br/>OKE + LBaaS"]
  end

  subgraph "Release Strategies"
    ROLL["Rolling Update"]
    BG["Blue-Green"]
    CAN["Canary + Analysis"]
  end

  subgraph "Observability"
    PROM["πŸ“Š Prometheus + Grafana"]
    CX["πŸ“‘ Coralogix<br/>Logs Β· Metrics Β· Traces Β· SLOs"]
  end

  HELM & KUST --> ROLL & BG & CAN
  TF --> AWS & GCP & AZ & OCI
  ROLL & BG & CAN --> PROM & CX

  style HELM fill:#0f1689,color:#fff
  style KUST fill:#326ce5,color:#fff
  style TF fill:#7b42bc,color:#fff
  style AWS fill:#ff9900,color:#fff
  style GCP fill:#4285f4,color:#fff
  style AZ fill:#0078d4,color:#fff
  style OCI fill:#f80000,color:#fff
  style PROM fill:#e6522c,color:#fff
  style CX fill:#1a1a2e,color:#fff
Loading
# Helm (recommended for Kubernetes)
helm install agent-monitor deployments/helm/agent-monitor \
  -f deployments/helm/agent-monitor/values-production.yaml \
  -n agent-monitor --create-namespace

# Kustomize
kubectl apply -k deployments/kubernetes/overlays/production

# Terraform (full infra + app)
cd deployments/terraform/providers/aws
terraform init && terraform apply -var-file=../../environments/production/terraform.tfvars

# Script orchestrator
./deployments/scripts/deploy.sh --env production --method helm --strategy blue-green

The deployment stack includes CI/CD pipelines (GitHub Actions + GitLab CI), comprehensive monitoring (Prometheus, Grafana, Alertmanager with 13 alert rules, Coralogix full-stack observability with OpenTelemetry Collector for logs, metrics, traces, and SLO tracking), operational scripts (deploy, rollback, blue-green switch, backup/restore, teardown), and a full security posture (Restricted Pod Security Standard, TLS 1.3, network policies, Trivy scanning).

Note

πŸ“˜ Full deployment guide: See DEPLOYMENT.md for step-by-step instructions, architecture diagrams, and operational workflows.


Project Structure

agent-dashboard/
|-- CLAUDE.md                   # Claude Code project memory and working agreements
|-- AGENTS.md                   # Codex project instructions
|-- package.json                # Root scripts (dashboard + MCP helpers) + server dependencies
|-- .claude/
|   +-- rules/                  # Path-scoped Claude rules
|   +-- skills/                 # Claude reusable project skills
|   +-- agents/                 # Claude custom subagents
|-- .claude-plugin/
|   +-- marketplace.json        # Plugin marketplace manifest (5 plugins)
|-- plugins/
|   |-- ccam-analytics/         # Analytics: session reports, cost breakdown, usage trends, productivity score
|   |   |-- .claude-plugin/plugin.json
|   |   |-- skills/ (4)         # session-report, cost-breakdown, usage-trends, productivity-score
|   |   |-- agents/             # analytics-advisor (Sonnet model)
|   |   |-- hooks/hooks.json    # Stop + SubagentStop event logging
|   |   +-- bin/ccam-stats      # Terminal dashboard CLI
|   |-- ccam-productivity/      # Productivity: standups, reports, sprints, workflow optimizer
|   |-- ccam-devtools/          # DevTools: debug, diagnostics, export, health checks
|   |   +-- bin/                # ccam-doctor + ccam-export CLIs
|   |-- ccam-insights/          # Insights: patterns, anomalies, optimization, comparison
|   +-- ccam-dashboard/         # Dashboard connector: status, quick stats, MCP integration
|       +-- .mcp.json           # MCP server configuration
|-- server/
|   |-- index.js                 # Express app, HTTP server, static serving
|   |-- db.js                    # SQLite schema, migrations, prepared statements
|   |-- websocket.js             # WebSocket server with heartbeat
|   +-- routes/
|       |-- hooks.js             # Hook event processing (transactional)
|       |-- sessions.js          # Session CRUD
|       |-- agents.js            # Agent CRUD
|       |-- events.js            # Event listing
|       |-- stats.js             # Aggregate statistics
|       |-- analytics.js         # Token, tool, and trend analytics
|       |-- workflows.js         # Aggregate workflow data and per-session drill-in
|       |-- pricing.js           # Model pricing CRUD and cost calculation
|       +-- settings.js          # System info, data management, export, cleanup
|   +-- lib/
|       +-- transcript-cache.js  # Stat-based JSONL transcript cache with incremental reads. Extracts tokens, compactions, API errors, turn durations, thinking blocks, and usage extras (service_tier, speed, inference_geo)
|   +-- compat-sqlite.js         # node:sqlite compatibility wrapper (fallback for better-sqlite3)
|-- client/
|   |-- package.json             # Client dependencies
|   |-- index.html               # HTML entry point
|   |-- vite.config.ts           # Vite + proxy config
|   |-- tailwind.config.js       # Custom dark theme
|   |-- tsconfig.json            # Strict TypeScript
|   +-- src/
|       |-- main.tsx             # React entry
|       |-- App.tsx              # Router + WebSocket provider
|       |-- index.css            # Tailwind + custom utilities
|       |-- lib/
|       |   |-- types.ts         # Shared TypeScript interfaces
|       |   |-- api.ts           # Typed fetch client
|       |   |-- format.ts        # Date/time formatting utilities
|       |   +-- eventBus.ts      # Pub/sub for WebSocket distribution
|       |-- hooks/
|       |   |-- useWebSocket.ts      # Auto-reconnecting WebSocket hook
|       |   +-- useNotifications.ts  # Browser notification triggers from WebSocket events
|       |-- components/
|       |   |-- Layout.tsx       # Shell with sidebar + outlet
|       |   |-- Sidebar.tsx      # Navigation + connection indicator
|       |   |-- AgentCard.tsx    # Agent info card with status
|       |   |-- StatCard.tsx     # Metric card
|       |   |-- StatusBadge.tsx  # Color-coded status pills
|       |   |-- EmptyState.tsx   # Placeholder for empty lists
|       |   +-- workflows/       # D3.js workflow visualization components
|       |       |-- OrchestrationDAG.tsx            # Horizontal DAG of agent spawning patterns
|       |       |-- ToolExecutionFlow.tsx           # d3-sankey diagram of tool-to-tool transitions
|       |       |-- AgentCollaborationNetwork.tsx   # Force-directed agent pipeline graph
|       |       |-- SubagentEffectiveness.tsx       # Scorecard grid with SVG success rings
|       |       |-- WorkflowPatterns.tsx            # Auto-detected orchestration sequences
|       |       |-- ModelDelegationFlow.tsx         # Model routing through agent hierarchies
|       |       |-- ErrorPropagationMap.tsx         # Error clustering by hierarchy depth
|       |       |-- ConcurrencyTimeline.tsx         # Swim-lane parallel agent execution
|       |       |-- SessionComplexityScatter.tsx    # D3 bubble chart (duration vs agents vs tokens)
|       |       |-- CompactionImpact.tsx            # Token compression events and recovery
|       |       |-- WorkflowStats.tsx               # Aggregate workflow statistics
|       |       +-- SessionDrillIn.tsx              # Per-session agent tree, tool timeline, events
|       +-- pages/
|           |-- Dashboard.tsx      # Overview page
|           |-- KanbanBoard.tsx    # Agents/Sessions toggle, status columns
|           |-- Sessions.tsx       # Server-paginated sessions table
|           |-- SessionDetail.tsx  # Single session deep dive
|           |-- ActivityFeed.tsx   # Real-time event stream
|           |-- Analytics.tsx      # Token usage, heatmap, trends
|           |-- Workflows.tsx      # D3.js workflow visualizations and session drill-in
|           |-- Settings.tsx       # Model pricing, notifications, hooks, export, cleanup
|           +-- NotFound.tsx       # 404 catch-all page
|-- scripts/
|   |-- hook-handler.js          # Lightweight stdin-to-HTTP forwarder
|   |-- install-hooks.js         # Auto-configures ~/.claude/settings.json
|   |-- import-history.js        # Imports sessions from ~/.claude/ with enhanced JSONL extraction (API errors, turn durations, entrypoint, permission modes, thinking blocks, usage extras, tool errors, subagent JSONL files)
|   +-- seed.js                  # Sample data generator
|-- mcp/
|   |-- package.json             # MCP package scripts + dependencies
|   |-- README.md                # MCP setup, host config, tool catalog, safety model
|   |-- src/
|   |   |-- index.ts             # MCP runtime entrypoint (transport router)
|   |   |-- server.ts            # MCP server assembly
|   |   |-- clients/             # Dashboard API client with retry/backoff
|   |   |-- config/              # Environment/CLI config parsing
|   |   |-- core/                # Logger, tool registry, result helpers
|   |   |-- policy/              # Mutation/destructive guards
|   |   |-- tools/               # Domain-specific tool modules (6 domains)
|   |   |-- transports/          # HTTP+SSE server, REPL, tool collector
|   |   |-- ui/                  # ANSI banner, colors, formatter, tables
|   |   +-- types/               # Shared MCP type definitions
|   +-- build/                   # Built MCP runtime output
|-- deployments/
|   |-- README.md                # Deployment infrastructure reference
|   |-- terraform/               # Cloud provisioning (AWS, GCP, Azure, OCI)
|   |   |-- modules/             # Reusable modules (networking, compute, db, lb, monitoring)
|   |   |-- providers/           # Cloud-specific implementations
|   |   +-- environments/        # Per-env tfvars (dev, staging, production)
|   |-- kubernetes/              # Kustomize manifests
|   |   |-- base/                # 11 base resources (deployment, service, ingress, hpa, etc.)
|   |   |-- overlays/            # Environment overlays (dev, staging, production)
|   |   |-- components/          # Optional add-ons (mcp-sidecar, monitoring)
|   |   +-- strategies/          # Blue-green and canary deployment strategies
|   |-- helm/agent-monitor/      # Helm chart with 12 templates and 4 value sets
|   |-- scripts/                 # Operational scripts (deploy, rollback, backup, teardown)
|   |-- monitoring/              # Prometheus, Grafana, Alertmanager, Coralogix (OTel Collector)
|   +-- ci/                      # CI/CD pipelines (GitHub Actions, GitLab CI)
|-- .codex/
|   |-- config.toml              # Codex runtime configuration
|   |-- README.md                # Codex setup guide for agents and skills
|   |-- rules/                   # Codex execution policy rules
|   |-- agents/                  # Codex custom agent templates
|   +-- skills/                  # Codex project skills
|-- statusline/
|   |-- README.md                # Statusline installation & usage guide
|   |-- statusline.py            # Python script that renders the statusline
|   +-- statusline-command.sh    # Shell wrapper for Claude Code's statusLine config
+-- data/
    +-- dashboard.db             # SQLite database (gitignored)

Troubleshooting

Problem Solution
better-sqlite3 fails to install This is non-fatal β€” the server falls back to Node.js built-in node:sqlite automatically (Node 22+). On older Node versions, install Python 3 and C++ build tools, then run npm rebuild better-sqlite3
Hooks not firing Run npm run install-hooks and restart Claude Code. Verify hooks exist in ~/.claude/settings.json
Dashboard shows no data Ensure the server is running (npm run dev) before starting a Claude Code session. Check http://localhost:4820/api/health
WebSocket disconnected The client auto-reconnects every 2 seconds. Check that port 4820 is not blocked by a firewall
Stale data after restart The database persists across restarts. Run npm run seed for fresh demo data, or delete data/dashboard.db to reset
MCP tools fail to connect Confirm dashboard API is up on MCP_DASHBOARD_BASE_URL and rebuild/start MCP (npm run mcp:build, npm run mcp:start)

License

MIT. See LICENSE for details.

About

πŸš€ A real-time monitoring dashboard for Claude Code agents, built with SQLite3, Node.js, Express, React, Vite, TailwindCSS, and WebSockets. It tracks sessions, agent activity, tool usage, and subagent orchestration through Claude Code hooks, providing live analytics, a Kanban status board, status notifications, and an interactive web interface.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors