Skip to content

PreistlyPython/claude-code-hooks-multi-agent-observability

Β 
Β 

Repository files navigation

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.

🎯 Overview

This system provides complete observability into Claude Code agent behavior by capturing, storing, and visualizing Claude Code Hook events 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

πŸ“‹ Setup Requirements

Before getting started, ensure you have the following installed:

  • Claude Code - Anthropic's official CLI for Claude
  • Astral uv - Fast Python package manager (required for hook scripts)
  • Bun, 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:

    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:

    {
      "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"
            }
          ]
        }],
        // ... (mirror the above for other event types)
      }
    }

    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:

    # 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.

# 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 <directory of your codebase you want to emit events from>

πŸ“ 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
β”‚   β”‚   β”œβ”€β”€ 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

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
    • stop.py: Records session completion with optional chat history
    • subagent_stop.py: Monitors subagent task completion

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
PreToolUse πŸ”§ Before tool execution Session-based
PostToolUse βœ… After tool completion Session-based
Notification πŸ”” User interactions Session-based
Stop πŸ›‘ Response completion Session-based
SubagentStop πŸ‘₯ Subagent finished Session-based
PreCompact πŸ“¦ Context compaction Session-based

πŸ”Œ Integration

For New Projects

  1. Copy the event sender:

    cp .claude/hooks/send_event.py YOUR_PROJECT/.claude/hooks/
  2. Add to your .claude/settings.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:

{
  "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

# 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:

# 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 Coding

And prepare for Agentic Engineering

Learn to code with AI with foundational Principles of AI Coding

Follow the IndyDevDan youtube channel for more AI coding tips and tricks.

About

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

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Vue 50.5%
  • TypeScript 28.3%
  • Python 16.1%
  • CSS 2.6%
  • Shell 1.7%
  • JavaScript 0.7%
  • HTML 0.1%