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.
- Overview
- Features
- Quick Start
- How It Works
- Configuration
- npm Scripts
- Plugin Marketplace
- Agent Extensions
- MCP Integration
- API Reference
- Hook Events
- Browser Notifications
- Data Storage
- Statusline
- Server Architecture
- Client Routing
- Hook Handler Flow
- Deployment Modes
- Project Structure
- Troubleshooting
- License
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
Comes with a sleek dark theme, responsive design, and intuitive navigation to explore your agent activity:
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.
The dashboard offers a comprehensive set of features to monitor and analyze your Claude Code sessions and agents:
| Feature | Description |
|---|---|
| Dashboard | Overview stats, active agent cards with collapsible subagent hierarchy, recent activity feed |
| Kanban Board | 5-column agent status board with paginated columns, per-status fetching (no artificial limits) |
| Sessions | Searchable, filterable, paginated table of all Claude Code sessions |
| Session Detail | Per-session agent hierarchy tree (parent/child) and full event timeline |
| Activity Feed | Real-time streaming event log with pause/resume and pagination |
| 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 |
| 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 | Browser notifications for session starts, completions, errors, and subagent spawns. Configurable per-event toggles with permission management |
| Settings | System info, hook status, model pricing management, notification preferences, data export, session cleanup |
| 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 charts with rich tooltips), 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. 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. Periodic scanner catches compactions within 2 minutes 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 2 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 |
| Seed Data | Built-in seed script for demos and development |
| Statusline | Color-coded CLI statusline showing model, context usage, git branch, tokens |
| 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 |
- Node.js >= 18.0.0 (22+ recommended)
- npm >= 9.0.0
git clone https://github.com/hoangsonww/Claude-Code-Agent-Monitor.git
cd Claude-Code-Agent-Monitor
npm run setupnpm run install-hooksThis adds hook entries to ~/.claude/settings.json that forward events to the dashboard. Existing hooks are preserved.
# Development (hot reload on both server and client)
npm run dev
# Production (single process, built client)
npm run build && npm startTip
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.
| Mode | URL |
|---|---|
| Development | http://localhost:5173 |
| Production | http://localhost:4820 |
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 completionFor 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.
npm run seedCreates 8 sample sessions, 23 agents, and 106 events so you can explore the UI immediately.
A Dockerfile and docker-compose.yml are included. Both Docker and Podman are supported.
With Docker Compose:
docker compose up -d --buildWith Podman Compose:
CLAUDE_HOME="$HOME/.claude" podman compose up -d --buildWith 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-monitorThe 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.
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
- Claude Code fires a hook on session start, tool use, turn end, subagent completion, and session exit
- 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 - Server processes the event inside a SQLite transaction:
- Auto-creates sessions and main agents on first contact
- Detects
Agenttool calls to track subagent creation - Sets agent to "working" on
PreToolUse, keeps it working throughPostToolUse - On
Stop(Claude finishes responding), main agent goes to "idle" — even on non-tool turns where Claude responds without invoking any tools, ensuring timestamps and activity logs stay accurate. Background subagents continue running. Session staysactive— the user can send more messages - Marks subagents completed individually via
SubagentStop - On
SessionEnd(CLI process exits), marks all agents and the session ascompleted - On
SessionStart, any other active session with no activity for 5+ minutes is automatically marked "abandoned" with its agents completed. This handles/resumeinside a session, Ctrl+C, and other scenarios where a session is orphaned without a cleanSessionEnd - 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
- Detects conversation compaction (
isCompactSummaryentries in the JSONL transcript) and createsCompactionagents + 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 (
isApiErrorMessageentries: quota limits, rate limits, invalid_request) and rawtype: "error"responses from JSONL transcripts, stored asAPIErrorevents. Turn durations (systemsubtypeturn_duration) are stored asTurnDurationevents. Tool result errors (toolUseResult.is_error) are tracked asToolErrorevents - A periodic server sweep (every 2 min) catches abandoned sessions and new compactions that slipped past event-based detection (e.g.,
/compactfires no hook,/resumewithin seconds of session creation). 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
- WebSocket broadcasts the change to all connected clients
- UI receives the update and re-renders the affected components
stateDiagram-v2
[*] --> connected: Agent created
connected --> working: PreToolUse
working --> working: PreToolUse (different tool)
working --> idle: Stop (turn ended)
idle --> working: PreToolUse (next turn)
idle --> connected: SessionStart (resume)
working --> completed: SessionEnd
idle --> completed: SessionEnd
connected --> completed: SessionEnd
working --> error: Error occurred
completed --> [*]
error --> [*]
stateDiagram-v2
[*] --> active: First hook event / SessionStart
active --> active: Stop (turn ended, waiting for user)
active --> error: Stop (error stop_reason)
active --> completed: SessionEnd (CLI exited)
active --> abandoned: No activity for 5+ min (SessionStart cleanup)
completed --> active: Session resumed (new work event)
error --> active: Session resumed (new work event)
abandoned --> active: Session resumed (new work event)
completed --> [*]
error --> [*]
abandoned --> [*]
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
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.
| 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 |
| Command | Description |
|---|---|
npm run setup |
Install server and client dependencies |
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) |
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/
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
- Persistent context:
- Path-scoped rules:
- Skills:
repo-onboardingship-featuremcp-operationsdebug-live-issue
- Subagents:
backend-reviewerfrontend-reviewermcp-reviewer
- Persistent context:
- Execution policy:
- Custom subagent templates:
- Skills:
- Setup:
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.
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
| 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 |
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
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
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
- Read-only mode (default):
MCP_DASHBOARD_ALLOW_MUTATIONS=false - Admin mode:
MCP_DASHBOARD_ALLOW_MUTATIONS=true - Destructive mode: requires both:
MCP_DASHBOARD_ALLOW_MUTATIONS=trueMCP_DASHBOARD_ALLOW_DESTRUCTIVE=true- tool input
confirmation_token: "CLEAR_ALL_DATA"
Full details: mcp/README.md
All endpoints return JSON. Error responses follow the shape { error: { code, message } }.
| Method | Path | Description |
|---|---|---|
GET |
/api/health |
Returns { status: "ok", timestamp } |
| Method | Path | Query Params | Description |
|---|---|---|---|
GET |
/api/sessions |
status, limit, offset |
List sessions with agent counts |
GET |
/api/sessions/:id |
-- | Session detail with agents and events |
POST |
/api/sessions |
-- | Create session (idempotent on id) |
PATCH |
/api/sessions/:id |
-- | Update session status/metadata |
| 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 |
| Method | Path | Query Params | Description |
|---|---|---|---|
GET |
/api/events |
session_id, limit, offset |
List events (newest first) |
| Method | Path | Description |
|---|---|---|
GET |
/api/stats |
Aggregate counts, status distributions, WS connections |
| 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" }
}
}| 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 |
| 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) |
| 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/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 |
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
The dashboard processes these Claude Code hook types:
| Hook Type | Trigger | Dashboard Action |
|---|---|---|
SessionStart |
Claude Code session begins | Creates session and main agent. Reactivates resumed sessions. Abandons orphaned sessions with no activity for 5+ minutes |
PreToolUse |
Agent starts using a tool | Sets agent to working, sets current_tool. If tool is Agent, creates subagent record |
PostToolUse |
Tool execution completed | Clears current_tool. Agent stays working (no status change) |
Stop |
Claude finishes responding | Main agent to idle (even on non-tool turns). Background subagents keep running. Session stays active |
SubagentStop |
Background agent finished | Matches and completes the subagent by description, type, or task |
Notification |
Agent notification | Logs event. Compaction-related notifications are tagged as Compaction events. Triggers a browser notification if the user has notifications enabled |
SessionEnd |
Claude Code CLI process exits | 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. 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 |
The dashboard supports native browser notifications for real-time alerts when you're not actively viewing the dashboard tab.
- Enable notifications in the Settings page via the master toggle
- Grant browser permission when prompted (required by the Web Notifications API)
- 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).
- Preferences are stored in
localStorageunder the keyagent-monitor-notifications useNotificationshook subscribes to the WebSocket event bus at the app root level (App.tsx) and firesnew Notification()calls based on the saved preferences- Permission management is handled in the Settings page with visual indicators for granted/denied/prompt states
- Test notification button in Settings lets you verify the setup works
- No server-side component - notifications are entirely client-side, triggered by WebSocket messages
- Engine: SQLite 3 via
better-sqlite3(optional) or Node.js built-innode:sqlite - Location:
data/dashboard.db - Journal mode: WAL (concurrent reads during writes)
- Reset: Delete
data/dashboard.dbto clear all data
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"
}
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 "idle|connected|working|completed|error"
TEXT current_tool "Active tool or NULL"
}
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"
}
Extend Claude Code with official Agent Monitor plugins — analytics, productivity tools, developer utilities, AI-powered insights, and dashboard connectivity.
claude plugin marketplace add hoangsonww/Claude-Code-Agent-Monitor| 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 |
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
# 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
A standalone CLI statusline utility for Claude Code that displays model name, user, working directory, git branch, context window usage bar, and token counts -- all color-coded with ANSI escape sequences.
Sonnet 4.6 | nguyens6 | ~/agent-dashboard/client | main | ████████░░ 79% | 3↑ 2↓ 156586c
| 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 | Dim | 3↑ 2↓ 156586c |
See statusline/README.md for installation instructions.
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
graph LR
ROOT["/ (index)"] --> DASH["Dashboard<br/>stats + agents + events"]
K["/kanban"] --> KANBAN["KanbanBoard<br/>5-column agent board"]
S["/sessions"] --> SESS["Sessions<br/>filterable 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"]
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
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
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
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
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
# 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-greenThe 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.
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 # Agent status columns
| |-- Sessions.tsx # 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)
| 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) |
MIT. See LICENSE for details.









