Back to projects
Active Started Oct 2025

Claude Code Debugger

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

TypeScript MCP (Model Context Protocol) Commander Jaccard / Jaro-Winkler similarity

Install

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

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

ComponentChoiceWhy
RuntimeNode.js ≥18, TypeScript, tsc buildMatches Claude Code’s own runtime; no bundler needed for a CLI+MCP package
InterfaceMCP stdio server (src/mcp/server.ts) + CLI (commander) + slash commandsMCP tools are what the host agent calls directly; CLI covers manual/scripted use
StorageFlat 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
SimilarityCustom 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 ingestionAdapters 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
HooksStop hook (hooks/hooks.json, auto-wired by configureHooks()) runs mine --days 1 --storeConfirmed 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
Distributionnpm (@tyroneross/claude-code-debugger) with publishConfig.provenance: true, and the Claude Code plugin marketplaceProvenance 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:

VerdictAction
KNOWN_FIXApply the documented fix directly, adapting for current context. Skip the loop.
LIKELY_MATCHPast incidents exist but need verification. Enter debug-loop.
WEAK_SIGNALLoosely related. Enter debug-loop with prior context as a starting point.
NO_MATCHNo 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:

AssessorExpertise
database-assessorPrisma, PostgreSQL, queries, migrations, connection pools
frontend-assessorReact, hooks, rendering, state, hydration, SSR
api-assessorEndpoints, REST/GraphQL, auth, middleware, CORS
performance-assessorLatency, 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) — 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:

LayerPurpose
MEMORY_SUMMARY.mdCompressed context (<150 lines) for LLM cold starts
index.jsonO(1) lookups by category, tag, file, quality tier
keyword-index.jsonInverted keyword → incident ID map
incidents.jsonlAppend-only log for fast full-text search
incidents/INC_*.jsonFull incident details, loaded on demand
outcomes.jsonlVerdict 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.