2026-07-30T22:34:17.432Z
Disler Claude Code Hooks Multi-Agent Observability: Prove Event Delivery
Audit configuration, HTTP delivery, SQLite persistence, WebSocket freshness, waiting, and outcomes before trusting the Disler Claude Code dashboard.
The safe answer is: do not treat a reachable dashboard or a zero hook exit code as proof that Disler’s Claude Code hooks multi agent observability pipeline is healthy. Require a receipt at each boundary—configuration, HTTP delivery, SQLite persistence, WebSocket delivery, and browser freshness—then verify the work outside the monitoring path. That distinction matters because the repository’s own architecture is a chain: Claude agents → hook scripts → HTTP POST → Bun server → SQLite → WebSocket → Vue client. A bright event in the last box proves that one event crossed the chain. A quiet box does not tell you where evidence stopped, and a Stop event does not prove that the requested file, test, deployment, or handoff exists. I audited repository commit 8a6e5cf and replayed nine content free cases. A naive rule that checks only the hook process exit code marked all nine green. The receipt rule classified all nine as expected; only one was healthy. Pin the repository and define the evidence contract Start with the code you actually run. At the pinned commit, .claude/settings.json configures twelve event groups: SessionStart , SessionEnd , UserPromptSubmit , PreToolUse , PostToolUse , PostToolUseFailure , PermissionRequest , Notification , SubagentStart , SubagentStop , Stop , and PreCompact . The current Claude Code hooks reference documents thirty lifecycle events. That larger set includes newer team and failure signals such as TaskCreated , TaskCompleted , TeammateIdle , StopFailure , and PostToolBatch . The comparison does not mean every installation should capture all thirty. It means “all hooks” is a versioned claim: define the minimal events your operating decision requires, pin the Claude Code version, and fail the coverage check when the configuration no longer matches that manifest. For a single agent canary, a reasonable minimum is SessionStart , one paired PreToolUse and PostToolUse , and Stop . For a team run, add the subagent lifecycle and the task or teammate signals that your installed Claude Code version exposes. A missing event is meaningful only after you establish that it was expected and configured. The next boundary is the sender. The pinned send event.py uses a five second HTTP timeout. It returns False and writes to stderr when the request fails, but main() does not use that result: it exits with code zero unconditionally so monitoring cannot block Claude Code. That is a defensible availability choice, but it makes exit code zero an activity signal rather than a delivery receipt. The server provides a stronger receipt. Its POST /events path validates required fields, inserts the event, then returns the saved record and broadcasts it to connected WebSocket clients. Retain the returned database ID for a canary. An HTTP connection without a saved ID is not equivalent evidence. The repository’s just health recipe needs the same interpretation. It requests /health , but the pinned server has no dedicated health branch; unmatched paths receive the generic Multi Agent Observability Server response with HTTP 200. That proves the process answered HTTP. It does not exercise event insertion, SQLite readability, WebSocket delivery, or a current browser view. Use an explicit contract: Receipt Evidence to retain What it does not prove Configuration pinned event manifest and source app value that a hook fired Transport HTTP 200 plus the saved event ID that the browser received it Persistence the same ID visible in recent events that the view is current Presentation WebSocket or reconnect replay contains the ID that all required events arrived Coverage every required event appears before its deadline that work succeeded Outcome deterministic check of the intended deliverable that future runs stay healthy Replay the delivery audit before trusting the view I encoded those boundaries in a fixture without prompts, transcripts, tool inputs, file paths, or secrets. Run it with: The replay produced: The classifier uses precedence. It first checks whether an exit zero hook actually reached the server. It then requires a persistence receipt, checks whether the browser delivery is current, validates the configured manifest, expires stale evidence, preserves a legitimate wait before its deadline, and only then asks whether the intended outcome exists. Fixture Classification Operator decision Sender exits zero after failed POST delivery failed hidden inspect sender stderr and server reachability HTTP accepted but no saved ID persistence unverified do not infer storage from transport SQLite has the event but WebSocket does not dashboard stale reconnect and verify replay before diagnosing the agent Team events are required but not configured manifest drift update or narrow the pinned manifest Configured event never arrives coverage gap inspect matcher, hook process, and version compatibility Permission dependency is before its deadline waiting route the decision to its owner; do not call it stuck Stop arrives without a deliverable receipt false complete verify the external result before clearing the run Only old events remain stale expire green and report evidence as unavailable Every boundary and outcome passes healthy accept this run, not the entire installation forever The waiting branch prevents a common false alarm. If a permission request has a named owner and an unexpired deadline, the absence of a later tool result is expected. After the deadline, or when no owner exists, the same evidence becomes a coverage or progress problem. Time and ownership change the diagnosis; event count alone cannot. The false complete branch prevents the opposite mistake. Claude Code’s official reference defines Stop as the end of a response. The repository can faithfully display that lifecycle fact. Neither system claims that the destination changed. A file task needs the expected path and content check; a code task needs relevant tests; a remote action needs a destination receipt. Keep those checks outside the hook transport so the monitoring system cannot certify itself. There is also a privacy trade off. The repository supports optional chat capture and displays prompt related data. Delivery health does not require either. A canary can use only opaque identifiers such as source app , session id , hook event type , timestamp, and returned event ID. Minimize the envelope before expanding observability. Operate a small canary, then verify the real outcome Adopt the audit in five bounded steps. 1. Pin versions and scope. Record the repository commit, Claude Code version, source app identifier, and the exact lifecycle events required for your decision. Review the official hooks reference when either version changes. 2. Send one unique canary. Use a disposable session identifier and a harmless PreToolUse payload. Require HTTP 200 and parse the returned saved event ID. Do not use hook exit code alone. 3. Prove storage and presentation. Query /events/recent immediately and find that exact ID. Reconnect the Vue client or a test WebSocket to /stream and require the same event in the initial replay or live message. Keep the check inside the replay window; the pinned server sends 300 recent rows when a WebSocket opens. 4. Check coverage and freshness. Run a known lifecycle sequence, compare observed event types with the pinned manifest, and apply per event deadlines. Route owned permission waits as waiting. Expire old evidence instead of keeping stale green. 5. Verify the user’s result separately. Assert the expected file, test result, task state, or external effect. A monitor should report false complete when the lifecycle closes without that receipt. This process has limits. It tests configured delivery through the pinned repository; it does not establish semantic correctness for every payload. Adding every available hook can increase latency, storage, and sensitive data exposure. A minimal, versioned manifest is usually safer than indiscriminate collection. The nine case fixture demonstrates the decision rule, not the prevalence of failures in production. Sidewisp fits this boundary as a health layer, not as another Claude Code runtime or a replacement for the repository. Sidewisp is currently in private preview. The public site and interactive demonstration are live, but a production Claude Code monitoring adapter, live health collector, and automated recovery executor are not shipped. Recovery remains a planned, approval bounded capability; the current honest next step is to join the private preview waitlist if this receipt model matches how you operate agents. For this repository, keep the rule compact: a dashboard event is evidence of observed activity. Declare the run healthy only when the required event manifest is current, the canary has transport, persistence, and presentation receipts, any wait has an owner and deadline, and the intended outcome passes its own deterministic check.