{"id":29806258,"url":"https://github.com/disler/claude-code-hooks-multi-agent-observability","last_synced_at":"2026-01-22T18:11:51.282Z","repository":{"id":304526279,"uuid":"1019046491","full_name":"disler/claude-code-hooks-multi-agent-observability","owner":"disler","description":"Real-time monitoring for Claude Code agents through simple hook event tracking.","archived":false,"fork":false,"pushed_at":"2025-10-26T15:50:20.000Z","size":4231,"stargazers_count":806,"open_issues_count":15,"forks_count":253,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-12-01T04:47:37.594Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/disler.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-07-13T16:11:17.000Z","updated_at":"2025-11-30T20:16:21.000Z","dependencies_parsed_at":"2025-07-13T18:26:39.801Z","dependency_job_id":"3091f7ca-d22a-4444-a262-b0bfeecf5be8","html_url":"https://github.com/disler/claude-code-hooks-multi-agent-observability","commit_stats":null,"previous_names":["disler/claude-code-hooks-multi-agent-observability"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/disler/claude-code-hooks-multi-agent-observability","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/disler%2Fclaude-code-hooks-multi-agent-observability","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/disler%2Fclaude-code-hooks-multi-agent-observability/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/disler%2Fclaude-code-hooks-multi-agent-observability/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/disler%2Fclaude-code-hooks-multi-agent-observability/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/disler","download_url":"https://codeload.github.com/disler/claude-code-hooks-multi-agent-observability/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/disler%2Fclaude-code-hooks-multi-agent-observability/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28667881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T17:07:18.858Z","status":"ssl_error","status_checked_at":"2026-01-22T17:05:02.040Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-28T14:05:55.165Z","updated_at":"2026-01-22T18:11:51.252Z","avatar_url":"https://github.com/disler.png","language":"Python","readme":"# Multi-Agent Observability System\n\nReal-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).\n\n## 🎯 Overview\n\nThis 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. \n\n\u003cimg src=\"images/app.png\" alt=\"Multi-Agent Observability Dashboard\" style=\"max-width: 800px; width: 100%;\"\u003e\n\n## 🏗️ Architecture\n\n```\nClaude Agents → Hook Scripts → HTTP POST → Bun Server → SQLite → WebSocket → Vue Client\n```\n\n![Agent Data Flow Animation](images/AgentDataFlowV2.gif)\n\n## 📋 Setup Requirements\n\nBefore getting started, ensure you have the following installed:\n\n- **[Claude Code](https://docs.anthropic.com/en/docs/claude-code)** - Anthropic's official CLI for Claude\n- **[Astral uv](https://docs.astral.sh/uv/)** - Fast Python package manager (required for hook scripts)\n- **[Bun](https://bun.sh/)**, **npm**, or **yarn** - For running the server and client\n- **Anthropic API Key** - Set as `ANTHROPIC_API_KEY` environment variable\n- **OpenAI API Key** (optional) - For multi-model support with just-prompt MCP tool\n- **ElevenLabs API Key** (optional) - For audio features\n\n### Configure .claude Directory\n\nTo setup observability in your repo,we need to copy the .claude directory to your project root.\n\nTo integrate the observability hooks into your projects:\n\n1. **Copy the entire `.claude` directory to your project root:**\n   ```bash\n   cp -R .claude /path/to/your/project/\n   ```\n\n2. **Update the `settings.json` configuration:**\n   \n   Open `.claude/settings.json` in your project and modify the `source-app` parameter to identify your project:\n   \n   ```json\n   {\n     \"hooks\": {\n       \"PreToolUse\": [{\n         \"matcher\": \"\",\n         \"hooks\": [\n           {\n             \"type\": \"command\",\n             \"command\": \"uv run .claude/hooks/pre_tool_use.py\"\n           },\n           {\n             \"type\": \"command\",\n             \"command\": \"uv run .claude/hooks/send_event.py --source-app YOUR_PROJECT_NAME --event-type PreToolUse --summarize\"\n           }\n         ]\n       }],\n       \"PostToolUse\": [{\n         \"matcher\": \"\",\n         \"hooks\": [\n           {\n             \"type\": \"command\",\n             \"command\": \"uv run .claude/hooks/post_tool_use.py\"\n           },\n           {\n             \"type\": \"command\",\n             \"command\": \"uv run .claude/hooks/send_event.py --source-app YOUR_PROJECT_NAME --event-type PostToolUse --summarize\"\n           }\n         ]\n       }],\n       \"UserPromptSubmit\": [{\n         \"hooks\": [\n           {\n             \"type\": \"command\",\n             \"command\": \"uv run .claude/hooks/user_prompt_submit.py --log-only\"\n           },\n           {\n             \"type\": \"command\",\n             \"command\": \"uv run .claude/hooks/send_event.py --source-app YOUR_PROJECT_NAME --event-type UserPromptSubmit --summarize\"\n           }\n         ]\n       }]\n       // ... (similar patterns for Notification, Stop, SubagentStop, PreCompact, SessionStart, SessionEnd)\n     }\n   }\n   ```\n   \n   Replace `YOUR_PROJECT_NAME` with a unique identifier for your project (e.g., `my-api-server`, `react-app`, etc.).\n\n3. **Ensure the observability server is running:**\n   ```bash\n   # From the observability project directory (this codebase)\n   ./scripts/start-system.sh\n   ```\n\nNow your project will send events to the observability system whenever Claude Code performs actions.\n\n## 🚀 Quick Start\n\nYou can quickly view how this works by running this repositories .claude setup.\n\n```bash\n# 1. Start both server and client\n./scripts/start-system.sh\n\n# 2. Open http://localhost:5173 in your browser\n\n# 3. Open Claude Code and run the following command:\nRun git ls-files to understand the codebase.\n\n# 4. Watch events stream in the client\n\n# 5. Copy the .claude folder to other projects you want to emit events from.\ncp -R .claude \u003cdirectory of your codebase you want to emit events from\u003e\n```\n\n## 📁 Project Structure\n\n```\nclaude-code-hooks-multi-agent-observability/\n│\n├── apps/                    # Application components\n│   ├── server/             # Bun TypeScript server\n│   │   ├── src/\n│   │   │   ├── index.ts    # Main server with HTTP/WebSocket endpoints\n│   │   │   ├── db.ts       # SQLite database management \u0026 migrations\n│   │   │   └── types.ts    # TypeScript interfaces\n│   │   ├── package.json\n│   │   └── events.db       # SQLite database (gitignored)\n│   │\n│   └── client/             # Vue 3 TypeScript client\n│       ├── src/\n│       │   ├── App.vue     # Main app with theme \u0026 WebSocket management\n│       │   ├── components/\n│       │   │   ├── EventTimeline.vue      # Event list with auto-scroll\n│       │   │   ├── EventRow.vue           # Individual event display\n│       │   │   ├── FilterPanel.vue        # Multi-select filters\n│       │   │   ├── ChatTranscriptModal.vue # Chat history viewer\n│       │   │   ├── StickScrollButton.vue  # Scroll control\n│       │   │   └── LivePulseChart.vue     # Real-time activity chart\n│       │   ├── composables/\n│       │   │   ├── useWebSocket.ts        # WebSocket connection logic\n│       │   │   ├── useEventColors.ts      # Color assignment system\n│       │   │   ├── useChartData.ts        # Chart data aggregation\n│       │   │   └── useEventEmojis.ts      # Event type emoji mapping\n│       │   ├── utils/\n│       │   │   └── chartRenderer.ts       # Canvas chart rendering\n│       │   └── types.ts    # TypeScript interfaces\n│       ├── .env.sample     # Environment configuration template\n│       └── package.json\n│\n├── .claude/                # Claude Code integration\n│   ├── hooks/             # Hook scripts (Python with uv)\n│   │   ├── send_event.py  # Universal event sender\n│   │   ├── pre_tool_use.py    # Tool validation \u0026 blocking\n│   │   ├── post_tool_use.py   # Result logging\n│   │   ├── notification.py    # User interaction events\n│   │   ├── user_prompt_submit.py # User prompt logging \u0026 validation\n│   │   ├── stop.py           # Session completion\n│   │   └── subagent_stop.py  # Subagent completion\n│   │\n│   └── settings.json      # Hook configuration\n│\n├── scripts/               # Utility scripts\n│   ├── start-system.sh   # Launch server \u0026 client\n│   ├── reset-system.sh   # Stop all processes\n│   └── test-system.sh    # System validation\n│\n└── logs/                 # Application logs (gitignored)\n```\n\n## 🔧 Component Details\n\n### 1. Hook System (`.claude/hooks/`)\n\n\u003e If you want to master claude code hooks watch [this video](https://github.com/disler/claude-code-hooks-mastery)\n\nThe hook system intercepts Claude Code lifecycle events:\n\n- **`send_event.py`**: Core script that sends event data to the observability server\n  - Supports `--add-chat` flag for including conversation history\n  - Validates server connectivity before sending\n  - Handles all event types with proper error handling\n\n- **Event-specific hooks**: Each implements validation and data extraction\n  - `pre_tool_use.py`: Blocks dangerous commands, validates tool usage\n  - `post_tool_use.py`: Captures execution results and outputs\n  - `notification.py`: Tracks user interaction points\n  - `user_prompt_submit.py`: Logs user prompts, supports validation (v1.0.54+)\n  - `stop.py`: Records session completion with optional chat history\n  - `subagent_stop.py`: Monitors subagent task completion\n  - `pre_compact.py`: Tracks context compaction operations (manual/auto)\n  - `session_start.py`: Logs session start, can load development context\n  - `session_end.py`: Logs session end, saves session statistics\n\n### 2. Server (`apps/server/`)\n\nBun-powered TypeScript server with real-time capabilities:\n\n- **Database**: SQLite with WAL mode for concurrent access\n- **Endpoints**:\n  - `POST /events` - Receive events from agents\n  - `GET /events/recent` - Paginated event retrieval with filtering\n  - `GET /events/filter-options` - Available filter values\n  - `WS /stream` - Real-time event broadcasting\n- **Features**:\n  - Automatic schema migrations\n  - Event validation\n  - WebSocket broadcast to all clients\n  - Chat transcript storage\n\n### 3. Client (`apps/client/`)\n\nVue 3 application with real-time visualization:\n\n- **Visual Design**:\n  - Dual-color system: App colors (left border) + Session colors (second border)\n  - Gradient indicators for visual distinction\n  - Dark/light theme support\n  - Responsive layout with smooth animations\n\n- **Features**:\n  - Real-time WebSocket updates\n  - Multi-criteria filtering (app, session, event type)\n  - Live pulse chart with session-colored bars and event type indicators\n  - Time range selection (1m, 3m, 5m) with appropriate data aggregation\n  - Chat transcript viewer with syntax highlighting\n  - Auto-scroll with manual override\n  - Event limiting (configurable via `VITE_MAX_EVENTS_TO_DISPLAY`)\n\n- **Live Pulse Chart**:\n  - Canvas-based real-time visualization\n  - Session-specific colors for each bar\n  - Event type emojis displayed on bars\n  - Smooth animations and glow effects\n  - Responsive to filter changes\n\n## 🔄 Data Flow\n\n1. **Event Generation**: Claude Code executes an action (tool use, notification, etc.)\n2. **Hook Activation**: Corresponding hook script runs based on `settings.json` configuration\n3. **Data Collection**: Hook script gathers context (tool name, inputs, outputs, session ID)\n4. **Transmission**: `send_event.py` sends JSON payload to server via HTTP POST\n5. **Server Processing**:\n   - Validates event structure\n   - Stores in SQLite with timestamp\n   - Broadcasts to WebSocket clients\n6. **Client Update**: Vue app receives event and updates timeline in real-time\n\n## 🎨 Event Types \u0026 Visualization\n\n| Event Type       | Emoji | Purpose                | Color Coding  | Special Display                       |\n| ---------------- | ----- | ---------------------- | ------------- | ------------------------------------- |\n| PreToolUse       | 🔧     | Before tool execution  | Session-based | Tool name \u0026 details                   |\n| PostToolUse      | ✅     | After tool completion  | Session-based | Tool name \u0026 results                   |\n| Notification     | 🔔     | User interactions      | Session-based | Notification message                  |\n| Stop             | 🛑     | Response completion    | Session-based | Summary \u0026 chat transcript             |\n| SubagentStop     | 👥     | Subagent finished      | Session-based | Subagent details                      |\n| PreCompact       | 📦     | Context compaction     | Session-based | Compaction details                    |\n| UserPromptSubmit | 💬     | User prompt submission | Session-based | Prompt: _\"user message\"_ (italic)     |\n| SessionStart     | 🚀     | Session started        | Session-based | Session source (startup/resume/clear) |\n| SessionEnd       | 🏁     | Session ended          | Session-based | End reason (clear/logout/exit/other)  |\n\n### UserPromptSubmit Event (v1.0.54+)\n\nThe `UserPromptSubmit` hook captures every user prompt before Claude processes it. In the UI:\n- Displays as `Prompt: \"user's message\"` in italic text\n- Shows the actual prompt content inline (truncated to 100 chars)\n- Summary appears on the right side when AI summarization is enabled\n- Useful for tracking user intentions and conversation flow\n\n## 🔌 Integration\n\n### For New Projects\n\n1. Copy the event sender:\n   ```bash\n   cp .claude/hooks/send_event.py YOUR_PROJECT/.claude/hooks/\n   ```\n\n2. Add to your `.claude/settings.json`:\n   ```json\n   {\n     \"hooks\": {\n       \"PreToolUse\": [{\n         \"matcher\": \".*\",\n         \"hooks\": [{\n           \"type\": \"command\",\n           \"command\": \"uv run .claude/hooks/send_event.py --source-app YOUR_APP --event-type PreToolUse\"\n         }]\n       }]\n     }\n   }\n   ```\n\n### For This Project\n\nAlready integrated! Hooks run both validation and observability:\n```json\n{\n  \"type\": \"command\",\n  \"command\": \"uv run .claude/hooks/pre_tool_use.py\"\n},\n{\n  \"type\": \"command\", \n  \"command\": \"uv run .claude/hooks/send_event.py --source-app cc-hooks-observability --event-type PreToolUse\"\n}\n```\n\n## 🧪 Testing\n\n```bash\n# System validation\n./scripts/test-system.sh\n\n# Manual event test\ncurl -X POST http://localhost:4000/events \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"source_app\": \"test\",\n    \"session_id\": \"test-123\",\n    \"hook_event_type\": \"PreToolUse\",\n    \"payload\": {\"tool_name\": \"Bash\", \"tool_input\": {\"command\": \"ls\"}}\n  }'\n```\n\n## ⚙️ Configuration\n\n### Environment Variables\n\nCopy `.env.sample` to `.env` in the project root and fill in your API keys:\n\n**Application Root** (`.env` file):\n- `ANTHROPIC_API_KEY` – Anthropic Claude API key (required)\n- `ENGINEER_NAME` – Your name (for logging/identification)\n- `GEMINI_API_KEY` – Google Gemini API key (optional)\n- `OPENAI_API_KEY` – OpenAI API key (optional)\n- `ELEVEN_API_KEY` – ElevenLabs API key (optional)\n\n**Client** (`.env` file in `apps/client/.env`):\n- `VITE_MAX_EVENTS_TO_DISPLAY=100` – Maximum events to show (removes oldest when exceeded)\n\n### Server Ports\n\n- Server: `4000` (HTTP/WebSocket)\n- Client: `5173` (Vite dev server)\n\n## 🛡️ Security Features\n\n- Blocks dangerous commands (`rm -rf`, etc.)\n- Prevents access to sensitive files (`.env`, private keys)\n- Validates all inputs before execution\n- No external dependencies for core functionality\n\n## 📊 Technical Stack\n\n- **Server**: Bun, TypeScript, SQLite\n- **Client**: Vue 3, TypeScript, Vite, Tailwind CSS\n- **Hooks**: Python 3.8+, Astral uv, TTS (ElevenLabs or OpenAI), LLMs (Claude or OpenAI)\n- **Communication**: HTTP REST, WebSocket\n\n## 🔧 Troubleshooting\n\n### Hook Scripts Not Working\n\nIf 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.\n\n**Solution**: Use the custom Claude Code slash command to automatically convert all relative paths to absolute paths:\n\n```bash\n# In Claude Code, simply run:\n/convert_paths_absolute\n```\n\nThis command will:\n- Find all relative paths in your hook command scripts\n- Convert them to absolute paths based on your current working directory\n- Create a backup of your original settings.json\n- Show you exactly what changes were made\n\nThis ensures your hooks work correctly regardless of where Claude Code is executed from.\n\n## Master AI **Agentic Coding**\n\u003e And prepare for the future of software engineering\n\nLearn tactical agentic coding patterns with [Tactical Agentic Coding](https://agenticengineer.com/tactical-agentic-coding?y=cchobvwh45)\n\nFollow the [IndyDevDan YouTube channel](https://www.youtube.com/@indydevdan) to improve your agentic coding advantage.\n\n","funding_links":[],"categories":["Monitoring \u0026 Analytics","Tools \u0026 Utilities","Python","HarmonyOS","Productivity Tools"],"sub_categories":["Windows Manager","Monitoring \u0026 Observability"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdisler%2Fclaude-code-hooks-multi-agent-observability","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdisler%2Fclaude-code-hooks-multi-agent-observability","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdisler%2Fclaude-code-hooks-multi-agent-observability/lists"}