# Claude Code Debugger

Debugging memory that stores incidents and extracts patterns so you never fix the same bug twice.

Status: active

## Install

```bash
claude plugin marketplace add tyroneross/RossLabs-AI-Toolkit
claude plugin install claude-code-debugger@rosslabs-ai-toolkit
```

## The Problem

Claude Code resets to zero knowledge every session. A database timeout in week one takes the same four hours to diagnose in week three because nothing carries over: not the root cause, not the fix, not the verification path. The debugging intelligence is ephemeral, and difficult bugs consume disproportionate time when every encounter is the first encounter.

## What I Built

Claude Code Debugger stores debugging incidents and extracts reusable patterns from them, then surfaces relevant prior work the moment a similar symptom appears. The behavior is now formalized as the `debugging-memory` skill: a memory-first workflow that runs before any investigation, returns a verdict, and decides whether to apply a known fix, adapt a similar one, or start fresh.

It also serves as a supporting plugin for [Build Loop](/projects/build-loop). Build Loop's debugger phase calls into the bridges this plugin exposes; when no full debugger plugin is reachable, the debugging-memory skill is the standalone fallback.

## Architecture

Claude Code Debugger is a deterministic TypeScript package — no LLM API calls anywhere in the codebase (`package.json` dependencies are `commander` and `prompts` only; no `openai`, `@anthropic-ai`, or model SDK). It ships as an MCP server (`src/mcp/server.ts`) exposing 8 tools — `search`, `store`, `detail`, `status`, `list`, `patterns`, `outcome`, `read_logs` — plus a CLI (`coding-debugger` / `claude-code-debugger`) and 7 Claude Code agent definitions. All reasoning about symptoms and root causes happens in the host session (Claude Code or Codex) that calls these tools; the package itself only does retrieval, scoring, and file I/O.

```mermaid
flowchart LR
  A["Symptom text"] --> B["MCP search tool"]
  B --> C["Pattern match<br/>(signature + tag overlap)"]
  C -->|hit, conf ≥0.8| D["KNOWN_FIX"]
  C -->|miss| E["Incident search<br/>60% Jaccard keyword + 40% tag<br/>+ 1.2x recency boost (90d)"]
  E -->|conf ≥0.5| F["LIKELY_MATCH"]
  E -->|conf 0.3-0.5| G["WEAK_SIGNAL"]
  E -->|conf <0.3| H["NO_MATCH"]
  D & F & G & H --> I["debug-loop skill<br/>(host session, model: inherit)"]
  I --> J["root-cause-investigator agent<br/>causal-tree search"]
  I -.vague/cross-layer.-> K["assessment-orchestrator<br/>keyword domain routing"]
  K --> K1[database-assessor]
  K --> K2[frontend-assessor]
  K --> K3[api-assessor]
  K --> K4[performance-assessor]
  J --> L["fix-critique agent<br/>APPROVED / CHALLENGED"]
  L --> M["MCP store tool"]
  M --> N[("incidents.jsonl +<br/>INC_*.json + index.json +<br/>keyword-index.json")]
  N -->|3+ similar, tag-overlap ≥0.7| O["Pattern extractor<br/>PTN_*.json"]
  M --> P["outcome tool<br/>worked/failed/modified"]
  P -.feeds back.-> N
```

**End-to-end flow:**

1. A symptom string enters via the MCP `search` tool (or `/debugger` command). `checkMemoryWithVerdict()` is the entry point.
2. Patterns are checked first: symptom keywords are matched against each pattern's `detection_signature` and `tags` (70%/30% weighted). A pattern hit with confidence ≥0.8 and a verified pattern (success rate ≥0.7) returns `KNOWN_FIX` immediately — no further search.
3. If no pattern matches, incidents are searched: Jaccard similarity on extracted keywords (stop-words removed) against each incident's symptom text (60% weight) blended with bidirectional tag substring matching (40% weight), then a 1.2x boost for incidents inside a 90-day window. Score thresholds classify the result as `LIKELY_MATCH` (≥0.5), `WEAK_SIGNAL` (0.3–0.5), or `NO_MATCH` (<0.3).
4. Anything other than `KNOWN_FIX` escalates to the `debug-loop` skill in the host session. For focused bugs, the `root-cause-investigator` agent builds a causal tree (multiple candidate causes explored in parallel, not a single 5-whys chain) using Read/Grep/Bash/WebSearch. For vague or cross-layer symptoms ("app broken", "slow and wrong"), `assessment-orchestrator` first does deterministic keyword matching against domain word lists (database/frontend/api/performance) and dispatches the matching `*-assessor` agents in parallel.
5. Before a fix is accepted, the `fix-critique` agent pressure-tests it (root cause vs. symptom, regression risk, evidence gaps) and returns `APPROVED` or `CHALLENGED`.
6. The MCP `store` tool writes the incident to `incidents.jsonl` (append-only), an individual `INC_*.json`, and updates `index.json` and `keyword-index.json`.
7. `pattern-extractor.ts` groups incidents by root-cause category and computes a commonality score from tag overlap (70% weight), shared changed files (15%), and incident count (15%) — not TF-IDF/clustering. Once ≥3 incidents in a category clear a 0.7 commonality threshold, a `PTN_*` pattern is synthesized (best-detailed fix approach, union of detection keywords, union of common tags) and stored.
8. After a suggested fix is tried, the `outcome` tool records `worked`/`failed`/`modified` per incident; this feeds pattern `success_rate`, which gates future `KNOWN_FIX` verdicts (step 2).

⚠️ Corrects the previous version of this write-up: retrieval uses **Jaccard similarity + Jaro-Winkler fuzzy matching** (`src/string-similarity.ts`, `src/retrieval.ts`), not cosine similarity, and pattern extraction uses **tag/category-overlap scoring**, not TF-IDF vectorization or DBSCAN clustering — neither term appears anywhere in the source.

## Models

No model runs inside the npm package — it is retrieval and scoring code (keyword extraction, Jaccard/Jaro-Winkler similarity, rule-based verdict thresholds, deterministic tag-overlap pattern scoring). All 7 agents in `agents/*.md` (`root-cause-investigator`, `fix-critique`, `assessment-orchestrator`, `database-assessor`, `frontend-assessor`, `api-assessor`, `performance-assessor`) declare `model: inherit` in frontmatter — they run as subagents of whatever model the host Claude Code or Codex session is using, not a model call the package makes itself. This was chosen so the plugin has zero inference cost and no API key to manage; the tradeoff is that verdict classification, similarity scoring, and pattern extraction are bounded by string/statistical heuristics rather than semantic understanding — a known limitation the retrieval design works around with multiple parallel strategies (exact, tag, fuzzy, category) rather than one embedding-based pass.

## Tools & infra

| Component | Choice | Why |
|---|---|---|
| Runtime | Node.js ≥18, TypeScript, `tsc` build | Matches Claude Code's own runtime; no bundler needed for a CLI+MCP package |
| Interface | MCP stdio server (`src/mcp/server.ts`) + CLI (`commander`) + slash commands | MCP tools are what the host agent calls directly; CLI covers manual/scripted use |
| Storage | Flat files under `.claude/memory/` (local) or `~/.claude-code-debugger/` (shared) — `incidents.jsonl`, `INC_*.json`, `index.json`, `keyword-index.json`, `outcomes.jsonl`, `archive/` | No database dependency — the package installs via npm postinstall with zero infra; JSONL gives append-only audit trail and O(log n) keyword lookup without a DB server |
| Similarity | Custom Jaccard (`retrieval.ts`) + Jaro-Winkler (`string-similarity.ts`) | Cheap, dependency-free, deterministic — no embedding model or vector store needed for short symptom/tag matching |
| Trace ingestion | Adapters for OpenTelemetry (OTLP JSON), Sentry (events + breadcrumbs), LangChain/LangSmith (run JSON), Browser (Chrome DevTools/Playwright/HAR/console) — `src/traces/adapters/` | Converts existing observability exports into incident drafts instead of requiring a new instrumentation SDK |
| Hooks | `Stop` hook (`hooks/hooks.json`, auto-wired by `configureHooks()`) runs `mine --days 1 --store` | Confirmed auto-installed. `session-context` and `check-file` CLI commands exist (`context-engine.ts`) for `SessionStart`/`PreToolUse` hooks, but `auto-setup.ts` only wires `Stop` automatically — ⚠️ needs confirmation whether the other two are set up by a separate path or require manual config |
| Distribution | npm (`@tyroneross/claude-code-debugger`) with `publishConfig.provenance: true`, and the Claude Code plugin marketplace | Provenance ties the published package to the GitHub source commit; dual distribution covers both plugin installs and direct npm/CLI use |

## Tech stack

TypeScript (Node ≥18), Commander (CLI), MCP stdio server (8 tools), flat-file JSONL/JSON storage (no database), custom Jaccard + Jaro-Winkler similarity (no vector store or embedding model), 7 Claude Code subagents at `model: inherit`.

## The debugging-memory Skill

The skill is the contract. It runs before investigation, calls the debugger `search` MCP tool with the symptom, and returns one of four verdicts:

| Verdict | Action |
|---------|--------|
| `KNOWN_FIX` | Apply the documented fix directly, adapting for current context. Skip the loop. |
| `LIKELY_MATCH` | Past incidents exist but need verification. Enter `debug-loop`. |
| `WEAK_SIGNAL` | Loosely related. Enter `debug-loop` with prior context as a starting point. |
| `NO_MATCH` | No prior knowledge. Enter `debug-loop` for full investigation. |

After resolution, the skill calls `store` with symptom, root cause (with confidence 0–1), fix approach, files changed, and verification status. The next session benefits.

## Root-Cause Investigation

When the verdict isn't `KNOWN_FIX`, the workflow escalates to the `debug-loop` skill. Investigation is structured as a causal tree, not a single chain: the `root-cause-investigator` agent branches on multiple potential causes, traces each, and flags when external research is needed. A `fix-critique` agent pressure-tests the proposed fix before declaring it resolved, checking whether it addresses the root cause rather than a symptom, what regression risk it carries, and where evidence is missing. The loop iterates up to five times, with a scorecard tracking pass/fail per criterion.

Every report uses ✅ Verified / ⚠️ Assumed / ❓ Unknown markers. No overclaiming.

## Multi-Domain Parallel Assessment

For vague symptoms ("app broken") or issues that span layers ("search is slow and returns wrong results"), the workflow dispatches domain assessors in parallel rather than running a single generic pass:

| Assessor | Expertise |
|----------|-----------|
| `database-assessor` | Prisma, PostgreSQL, queries, migrations, connection pools |
| `frontend-assessor` | React, hooks, rendering, state, hydration, SSR |
| `api-assessor` | Endpoints, REST/GraphQL, auth, middleware, CORS |
| `performance-assessor` | Latency, memory, CPU, bottlenecks |

Each returns a JSON assessment with a confidence score, probable causes, recommended actions, and related past incidents. Results are ranked and merged into a unified diagnosis with a prioritized action sequence.

## Memory Architecture

> Part of the verification-gated agent-work pattern (see [/toolkit/patterns/verification-gated-agents](/toolkit/patterns/verification-gated-agents)) — here: fix outcomes (`worked` / `failed` / `modified`) are written back into pattern confidence scores, so a fix is only promoted toward a `KNOWN_FIX` verdict after it has been verified in practice, not merely proposed.

Two storage modes. Local mode (`.claude/memory/`) keeps incidents scoped to a single project, useful for proprietary codebases. Shared mode (`~/.claude-code-debugger/`) pools incidents across projects, useful for framework-specific patterns that recur everywhere.

Storage is tiered, following the pattern proven in IBR and NavGator:

| Layer | Purpose |
|-------|---------|
| `MEMORY_SUMMARY.md` | Compressed context (<150 lines) for LLM cold starts |
| `index.json` | O(1) lookups by category, tag, file, quality tier |
| `keyword-index.json` | Inverted keyword → incident ID map |
| `incidents.jsonl` | Append-only log for fast full-text search |
| `incidents/INC_*.json` | Full incident details, loaded on demand |
| `outcomes.jsonl` | Verdict outcome tracking (worked / failed / modified) |

Compound incident IDs (`INC_CATEGORY_YYYYMMDD_HHMMSS_xxxx`) encode category in the filename, so incidents can be browsed without opening them. Auto-archival moves incidents beyond 200 active or 180 days old into `archive/`.

## Pattern Extraction

When three or more incidents in the same root-cause category accumulate, `pattern-extractor.ts` scores their commonality: tags shared by ≥60% of the incidents (70% weight) + shared changed files (15%) + incident count ≥5 (15%). Above a 0.7 (auto) or 0.6 (suggestion) threshold, a `PTN_*` pattern is created — its detection signature is the union of symptom keywords/tags/category across the group, its solution template is the longest (most detailed) fix approach among them, and its code example comes from the highest-confidence incident. This is tag/category-overlap scoring, not vector clustering — no TF-IDF or DBSCAN runs anywhere in the codebase. Pattern matches return 90% confidence versus 70% for individual incident matches (hardcoded in `retrieval.ts`); outcome tracking feeds back into pattern `success_rate` so the system learns which patterns are reliable.

## Retrieval

Progressive, pattern-first. `checkMemoryScaled()` hits the keyword inverted index first (once ≥10 incidents exist) for near-O(1) candidate lookup instead of loading every incident file; patterns are matched before incidents. Results return as one-liner summaries (~40 tokens each) with verdicts via `checkMemoryProgressive()`; full details load on demand via `detail`. Default token budget is 2,500, split 30% patterns / 60% incidents / 10% metadata (`checkMemoryTiered()`), with the system choosing summary, compact, or full tier based on what fits.

Symptom-to-incident matching blends Jaccard similarity on extracted keywords (60%) with bidirectional tag substring matching (40%). A separate `enhancedSearch()` path runs four strategies in sequence for exploratory search: exact substring (score 1.0), tag match (0.9), Jaro-Winkler fuzzy match (0.7–0.85), then category match (0.6) on the categories of the top 3 hits. No cosine similarity is used anywhere — that claim in an earlier version of this write-up didn't match the source.

## Trace Ingestion

Adapters convert traces from external systems into incident drafts:

- **OpenTelemetry**: error-status spans become drafts with stack trace, operation name, and duration
- **Sentry**: error events with breadcrumbs as tags
- **LangChain / LangSmith**: prompt failures with full input/output
- **Browser**: Chrome DevTools, Playwright, console logs

Traces are summarized to preserve diagnostic information while keeping token cost low.

## Context Engine

Three layers are built to surface memory without manual `/debugger` calls, per `src/context-engine.ts`:

1. **CLAUDE.md dynamic section** (`generateDynamicSection()`) — memory stats, hot files (most past incidents), and trigger instructions, refreshed on `rebuild-index` or session start. ✅ Confirmed generated from `index.json`.
2. **SessionStart hook** — the CLI exposes a `session-context` command (`generateSessionContext()`) to inject ~150 tokens of memory state at session start.
3. **PreToolUse hook** — the CLI exposes a `check-file <filepath>` command (`checkFileContext()`) that surfaces past incident IDs for a file being edited, or `{"ok": true}` with zero noise otherwise.

⚠️ Needs confirmation: `src/setup/configure-hooks.ts` (the installer's automatic hook wiring) only registers the `Stop` hook. The `SessionStart`/`PreToolUse` commands exist and are functional, and `uninstall.ts` cleans up `SessionStart`/`PreToolUse` entries if present, but the current installer does not appear to auto-wire them — they may need manual `.claude/settings.json` configuration, or be set up by a path not found in this pass.

## Outcome Tracking

After a suggested fix is tried, the outcome is recorded as `worked`, `failed`, or `modified`. This feeds back into pattern success rates so verdicts improve over time. A pattern that worked four times and failed once gets ranked above one that's never been verified, even if textual similarity scores match.

## Distribution and Verification

Available via the Claude Code plugin marketplace and as `@tyroneross/claude-code-debugger` on npm with provenance from npm trusted publishing, so the published package matches the GitHub source commit. The package ships 45 end-to-end tests covering incident CRUD, parallel retrieval, pattern extraction, and trace ingestion, plus a 6-dimension benchmark suite that scores retrieval accuracy, verdict precision, context efficiency, pattern quality, scalability, and cold-start quality.

## Results

- **Test coverage**: ✅ 45 end-to-end tests covering incident CRUD, parallel retrieval, pattern extraction, and trace ingestion, gated by npm trusted publishing provenance so the published package matches the GitHub source commit.
- **Match confidence**: ✅ pattern matches return ~90% confidence versus ~70% for individual incident matches (per the retrieval logic described above); outcome tracking (`worked` / `failed` / `modified`) feeds back into those pattern scores over time.
- **6-dimension benchmark suite** (retrieval accuracy, verdict precision, context efficiency, pattern quality, scalability, cold-start quality): the suite exists in the package, but ⚠️ no benchmark published yet — no scored results for these six dimensions are available in this write-up.

## Links

- [HTML project page](https://rosslabs.ai/projects/claude-code-debugger/)
- [Live app](https://www.npmjs.com/package/@tyroneross/claude-code-debugger)
- [Demo](https://rosslabs.ai/images/projects/claude-code-debugger/cli-demo.gif)
- [Source code](https://github.com/tyroneross/claude-code-debugger)
