An open API service indexing awesome lists of open source software.

https://github.com/disler/claude-code-hooks-multi-agent-observability

Real-time monitoring for Claude Code agents through simple hook event tracking.
https://github.com/disler/claude-code-hooks-multi-agent-observability

Last synced: 21 days ago
JSON representation

Real-time monitoring for Claude Code agents through simple hook event tracking.

Awesome Lists containing this project

README

          

# Multi-Agent Observability System

Real-time monitoring and visualization for Claude Code agents through comprehensive hook event tracking. You can watch the [full breakdown here](https://youtu.be/9ijnN985O_c) and watch the latest enhancement where we compare Haiku 4.5 and Sonnet 4.5 [here](https://youtu.be/aA9KP7QIQvM).

## ๐ŸŽฏ Overview

This system provides complete observability into Claude Code agent behavior by capturing, storing, and visualizing Claude Code [Hook events](https://docs.anthropic.com/en/docs/claude-code/hooks) in real-time. It enables monitoring of multiple concurrent agents with session tracking, event filtering, and live updates.

Multi-Agent Observability Dashboard

## ๐Ÿ—๏ธ Architecture

```
Claude Agents โ†’ Hook Scripts โ†’ HTTP POST โ†’ Bun Server โ†’ SQLite โ†’ WebSocket โ†’ Vue Client
```

![Agent Data Flow Animation](images/AgentDataFlowV2.gif)

## ๐Ÿ“‹ Setup Requirements

Before getting started, ensure you have the following installed:

- **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** - Anthropic's official CLI for Claude
- **[Astral uv](https://docs.astral.sh/uv/)** - Fast Python package manager (required for hook scripts)
- **[Bun](https://bun.sh/)**, **npm**, or **yarn** - For running the server and client
- **Anthropic API Key** - Set as `ANTHROPIC_API_KEY` environment variable
- **OpenAI API Key** (optional) - For multi-model support with just-prompt MCP tool
- **ElevenLabs API Key** (optional) - For audio features

### Configure .claude Directory

To setup observability in your repo,we need to copy the .claude directory to your project root.

To integrate the observability hooks into your projects:

1. **Copy the entire `.claude` directory to your project root:**
```bash
cp -R .claude /path/to/your/project/
```

2. **Update the `settings.json` configuration:**

Open `.claude/settings.json` in your project and modify the `source-app` parameter to identify your project:

```json
{
"hooks": {
"PreToolUse": [{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "uv run .claude/hooks/pre_tool_use.py"
},
{
"type": "command",
"command": "uv run .claude/hooks/send_event.py --source-app YOUR_PROJECT_NAME --event-type PreToolUse --summarize"
}
]
}],
"PostToolUse": [{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "uv run .claude/hooks/post_tool_use.py"
},
{
"type": "command",
"command": "uv run .claude/hooks/send_event.py --source-app YOUR_PROJECT_NAME --event-type PostToolUse --summarize"
}
]
}],
"UserPromptSubmit": [{
"hooks": [
{
"type": "command",
"command": "uv run .claude/hooks/user_prompt_submit.py --log-only"
},
{
"type": "command",
"command": "uv run .claude/hooks/send_event.py --source-app YOUR_PROJECT_NAME --event-type UserPromptSubmit --summarize"
}
]
}]
// ... (similar patterns for Notification, Stop, SubagentStop, PreCompact, SessionStart, SessionEnd)
}
}
```

Replace `YOUR_PROJECT_NAME` with a unique identifier for your project (e.g., `my-api-server`, `react-app`, etc.).

3. **Ensure the observability server is running:**
```bash
# From the observability project directory (this codebase)
./scripts/start-system.sh
```

Now your project will send events to the observability system whenever Claude Code performs actions.

## ๐Ÿš€ Quick Start

You can quickly view how this works by running this repositories .claude setup.

```bash
# 1. Start both server and client
./scripts/start-system.sh

# 2. Open http://localhost:5173 in your browser

# 3. Open Claude Code and run the following command:
Run git ls-files to understand the codebase.

# 4. Watch events stream in the client

# 5. Copy the .claude folder to other projects you want to emit events from.
cp -R .claude
```

## ๐Ÿ“ Project Structure

```
claude-code-hooks-multi-agent-observability/
โ”‚
โ”œโ”€โ”€ apps/ # Application components
โ”‚ โ”œโ”€โ”€ server/ # Bun TypeScript server
โ”‚ โ”‚ โ”œโ”€โ”€ src/
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ index.ts # Main server with HTTP/WebSocket endpoints
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ db.ts # SQLite database management & migrations
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ types.ts # TypeScript interfaces
โ”‚ โ”‚ โ”œโ”€โ”€ package.json
โ”‚ โ”‚ โ””โ”€โ”€ events.db # SQLite database (gitignored)
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€ client/ # Vue 3 TypeScript client
โ”‚ โ”œโ”€โ”€ src/
โ”‚ โ”‚ โ”œโ”€โ”€ App.vue # Main app with theme & WebSocket management
โ”‚ โ”‚ โ”œโ”€โ”€ components/
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ EventTimeline.vue # Event list with auto-scroll
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ EventRow.vue # Individual event display
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ FilterPanel.vue # Multi-select filters
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ ChatTranscriptModal.vue # Chat history viewer
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ StickScrollButton.vue # Scroll control
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ LivePulseChart.vue # Real-time activity chart
โ”‚ โ”‚ โ”œโ”€โ”€ composables/
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ useWebSocket.ts # WebSocket connection logic
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ useEventColors.ts # Color assignment system
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ useChartData.ts # Chart data aggregation
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ useEventEmojis.ts # Event type emoji mapping
โ”‚ โ”‚ โ”œโ”€โ”€ utils/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ chartRenderer.ts # Canvas chart rendering
โ”‚ โ”‚ โ””โ”€โ”€ types.ts # TypeScript interfaces
โ”‚ โ”œโ”€โ”€ .env.sample # Environment configuration template
โ”‚ โ””โ”€โ”€ package.json
โ”‚
โ”œโ”€โ”€ .claude/ # Claude Code integration
โ”‚ โ”œโ”€โ”€ hooks/ # Hook scripts (Python with uv)
โ”‚ โ”‚ โ”œโ”€โ”€ send_event.py # Universal event sender
โ”‚ โ”‚ โ”œโ”€โ”€ pre_tool_use.py # Tool validation & blocking
โ”‚ โ”‚ โ”œโ”€โ”€ post_tool_use.py # Result logging
โ”‚ โ”‚ โ”œโ”€โ”€ notification.py # User interaction events
โ”‚ โ”‚ โ”œโ”€โ”€ user_prompt_submit.py # User prompt logging & validation
โ”‚ โ”‚ โ”œโ”€โ”€ stop.py # Session completion
โ”‚ โ”‚ โ””โ”€โ”€ subagent_stop.py # Subagent completion
โ”‚ โ”‚
โ”‚ โ””โ”€โ”€ settings.json # Hook configuration
โ”‚
โ”œโ”€โ”€ scripts/ # Utility scripts
โ”‚ โ”œโ”€โ”€ start-system.sh # Launch server & client
โ”‚ โ”œโ”€โ”€ reset-system.sh # Stop all processes
โ”‚ โ””โ”€โ”€ test-system.sh # System validation
โ”‚
โ””โ”€โ”€ logs/ # Application logs (gitignored)
```

## ๐Ÿ”ง Component Details

### 1. Hook System (`.claude/hooks/`)

> If you want to master claude code hooks watch [this video](https://github.com/disler/claude-code-hooks-mastery)

The hook system intercepts Claude Code lifecycle events:

- **`send_event.py`**: Core script that sends event data to the observability server
- Supports `--add-chat` flag for including conversation history
- Validates server connectivity before sending
- Handles all event types with proper error handling

- **Event-specific hooks**: Each implements validation and data extraction
- `pre_tool_use.py`: Blocks dangerous commands, validates tool usage
- `post_tool_use.py`: Captures execution results and outputs
- `notification.py`: Tracks user interaction points
- `user_prompt_submit.py`: Logs user prompts, supports validation (v1.0.54+)
- `stop.py`: Records session completion with optional chat history
- `subagent_stop.py`: Monitors subagent task completion
- `pre_compact.py`: Tracks context compaction operations (manual/auto)
- `session_start.py`: Logs session start, can load development context
- `session_end.py`: Logs session end, saves session statistics

### 2. Server (`apps/server/`)

Bun-powered TypeScript server with real-time capabilities:

- **Database**: SQLite with WAL mode for concurrent access
- **Endpoints**:
- `POST /events` - Receive events from agents
- `GET /events/recent` - Paginated event retrieval with filtering
- `GET /events/filter-options` - Available filter values
- `WS /stream` - Real-time event broadcasting
- **Features**:
- Automatic schema migrations
- Event validation
- WebSocket broadcast to all clients
- Chat transcript storage

### 3. Client (`apps/client/`)

Vue 3 application with real-time visualization:

- **Visual Design**:
- Dual-color system: App colors (left border) + Session colors (second border)
- Gradient indicators for visual distinction
- Dark/light theme support
- Responsive layout with smooth animations

- **Features**:
- Real-time WebSocket updates
- Multi-criteria filtering (app, session, event type)
- Live pulse chart with session-colored bars and event type indicators
- Time range selection (1m, 3m, 5m) with appropriate data aggregation
- Chat transcript viewer with syntax highlighting
- Auto-scroll with manual override
- Event limiting (configurable via `VITE_MAX_EVENTS_TO_DISPLAY`)

- **Live Pulse Chart**:
- Canvas-based real-time visualization
- Session-specific colors for each bar
- Event type emojis displayed on bars
- Smooth animations and glow effects
- Responsive to filter changes

## ๐Ÿ”„ Data Flow

1. **Event Generation**: Claude Code executes an action (tool use, notification, etc.)
2. **Hook Activation**: Corresponding hook script runs based on `settings.json` configuration
3. **Data Collection**: Hook script gathers context (tool name, inputs, outputs, session ID)
4. **Transmission**: `send_event.py` sends JSON payload to server via HTTP POST
5. **Server Processing**:
- Validates event structure
- Stores in SQLite with timestamp
- Broadcasts to WebSocket clients
6. **Client Update**: Vue app receives event and updates timeline in real-time

## ๐ŸŽจ Event Types & Visualization

| Event Type | Emoji | Purpose | Color Coding | Special Display |
| ---------------- | ----- | ---------------------- | ------------- | ------------------------------------- |
| PreToolUse | ๐Ÿ”ง | Before tool execution | Session-based | Tool name & details |
| PostToolUse | โœ… | After tool completion | Session-based | Tool name & results |
| Notification | ๐Ÿ”” | User interactions | Session-based | Notification message |
| Stop | ๐Ÿ›‘ | Response completion | Session-based | Summary & chat transcript |
| SubagentStop | ๐Ÿ‘ฅ | Subagent finished | Session-based | Subagent details |
| PreCompact | ๐Ÿ“ฆ | Context compaction | Session-based | Compaction details |
| UserPromptSubmit | ๐Ÿ’ฌ | User prompt submission | Session-based | Prompt: _"user message"_ (italic) |
| SessionStart | ๐Ÿš€ | Session started | Session-based | Session source (startup/resume/clear) |
| SessionEnd | ๐Ÿ | Session ended | Session-based | End reason (clear/logout/exit/other) |

### UserPromptSubmit Event (v1.0.54+)

The `UserPromptSubmit` hook captures every user prompt before Claude processes it. In the UI:
- Displays as `Prompt: "user's message"` in italic text
- Shows the actual prompt content inline (truncated to 100 chars)
- Summary appears on the right side when AI summarization is enabled
- Useful for tracking user intentions and conversation flow

## ๐Ÿ”Œ Integration

### For New Projects

1. Copy the event sender:
```bash
cp .claude/hooks/send_event.py YOUR_PROJECT/.claude/hooks/
```

2. Add to your `.claude/settings.json`:
```json
{
"hooks": {
"PreToolUse": [{
"matcher": ".*",
"hooks": [{
"type": "command",
"command": "uv run .claude/hooks/send_event.py --source-app YOUR_APP --event-type PreToolUse"
}]
}]
}
}
```

### For This Project

Already integrated! Hooks run both validation and observability:
```json
{
"type": "command",
"command": "uv run .claude/hooks/pre_tool_use.py"
},
{
"type": "command",
"command": "uv run .claude/hooks/send_event.py --source-app cc-hooks-observability --event-type PreToolUse"
}
```

## ๐Ÿงช Testing

```bash
# System validation
./scripts/test-system.sh

# Manual event test
curl -X POST http://localhost:4000/events \
-H "Content-Type: application/json" \
-d '{
"source_app": "test",
"session_id": "test-123",
"hook_event_type": "PreToolUse",
"payload": {"tool_name": "Bash", "tool_input": {"command": "ls"}}
}'
```

## โš™๏ธ Configuration

### Environment Variables

Copy `.env.sample` to `.env` in the project root and fill in your API keys:

**Application Root** (`.env` file):
- `ANTHROPIC_API_KEY` โ€“ Anthropic Claude API key (required)
- `ENGINEER_NAME` โ€“ Your name (for logging/identification)
- `GEMINI_API_KEY` โ€“ Google Gemini API key (optional)
- `OPENAI_API_KEY` โ€“ OpenAI API key (optional)
- `ELEVEN_API_KEY` โ€“ ElevenLabs API key (optional)

**Client** (`.env` file in `apps/client/.env`):
- `VITE_MAX_EVENTS_TO_DISPLAY=100` โ€“ Maximum events to show (removes oldest when exceeded)

### Server Ports

- Server: `4000` (HTTP/WebSocket)
- Client: `5173` (Vite dev server)

## ๐Ÿ›ก๏ธ Security Features

- Blocks dangerous commands (`rm -rf`, etc.)
- Prevents access to sensitive files (`.env`, private keys)
- Validates all inputs before execution
- No external dependencies for core functionality

## ๐Ÿ“Š Technical Stack

- **Server**: Bun, TypeScript, SQLite
- **Client**: Vue 3, TypeScript, Vite, Tailwind CSS
- **Hooks**: Python 3.8+, Astral uv, TTS (ElevenLabs or OpenAI), LLMs (Claude or OpenAI)
- **Communication**: HTTP REST, WebSocket

## ๐Ÿ”ง Troubleshooting

### Hook Scripts Not Working

If your hook scripts aren't executing properly, it might be due to relative paths in your `.claude/settings.json`. Claude Code documentation recommends using absolute paths for command scripts.

**Solution**: Use the custom Claude Code slash command to automatically convert all relative paths to absolute paths:

```bash
# In Claude Code, simply run:
/convert_paths_absolute
```

This command will:
- Find all relative paths in your hook command scripts
- Convert them to absolute paths based on your current working directory
- Create a backup of your original settings.json
- Show you exactly what changes were made

This ensures your hooks work correctly regardless of where Claude Code is executed from.

## Master AI **Agentic Coding**
> And prepare for the future of software engineering

Learn tactical agentic coding patterns with [Tactical Agentic Coding](https://agenticengineer.com/tactical-agentic-coding?y=cchobvwh45)

Follow the [IndyDevDan YouTube channel](https://www.youtube.com/@indydevdan) to improve your agentic coding advantage.