Skill in engineering
systematic-debugging
Debug a bug, test failure, crash, or unexpected behaviour by finding the root cause before changing anything, instead of guessing at fixes. Works in any language or stack. Use when something is broken, a test is failing, behaviour is wrong, or a previous fix didn't hold.
Install
As a plugin
Bundled in the engineering plugin. Add the marketplace once, then install the bundle; it updates with the marketplace.
/plugin marketplace add KhaledSaeed18/dotclaude/plugin install engineering@dotclaudeAs a single item
Run from the project root; the skill lands under .claude/. Copy it to ~/.claude/ to make it global.
npx shadcn@latest add KhaledSaeed18/dotclaude/systematic-debuggingFiles installed
.claude/skills/systematic-debugging/SKILL.md
What it does
Find the root cause before you touch a line of code. A fix that targets a symptom you don't understand either fails or moves the bug somewhere else, and each blind attempt makes the next one harder to reason about. Investigation first is not the slow path; it is the fast one.
The one rule
No fix before you can name the root cause. If you can't say "the bug happens because X", you are still investigating, not fixing. The moment you feel "let me just try changing this and see": stop. That instinct is the thing this skill exists to interrupt.
This holds hardest exactly when it feels most skippable: under time pressure, when the bug "looks simple", when you've already tried two things. Simple bugs have root causes too, and guess-and-check is slower than it feels because every wrong attempt has to be unwound.
Step 1: Investigate the root cause
Do all of this before forming any fix.
- Read the actual error. The full message, the full stack trace, line numbers, error codes. The answer is often already written there. Don't skim past it to the part you assume is the problem.
- Reproduce it reliably. What exact steps trigger it? Every time, or intermittently? If you can't reproduce it, you can't confirm a fix: gather more data rather than guessing.
- Check what changed.
git diff, recent commits, new dependencies, config or environment differences. A bug that just appeared usually has a recent cause. - Instrument the boundaries when the system has multiple layers (request → service → database, CI → build → sign). Log what enters and what leaves each boundary, run once, and read where the data first goes wrong. Find the failing layer with evidence before you reason about why that layer fails.
- Trace the bad value to its origin. When the error surfaces deep in a call stack, work backward: where did this value come from, what passed it in, and up the chain until you reach the true source. Fix it there, not where it happened to blow up.
Step 2: Compare against what works
- Find similar code in the same codebase that does work. What is different between it and the broken path? List every difference, even ones you're sure don't matter, "that can't be it" is where bugs hide.
- If you're following a reference or pattern, read it completely before applying it. Partial understanding produces confident wrong fixes.
Step 3: Form one hypothesis and test it minimally
- State it explicitly: "I think the cause is X, because Y." Write it down. Be specific.
- Make the smallest possible change that would confirm or refute it. One variable at a time; don't bundle three speculative changes and lose track of which one mattered.
- If it confirms, move on. If it doesn't, form a new hypothesis from what you just learned; don't pile another fix on top of the last.
- If you genuinely don't understand something, say so and dig in or ask, rather than pretending and patching.
Step 4: Fix the cause and prove it
- Write a failing test that reproduces the bug first, automated if there's a framework, a throwaway script if not. A fix without a test that once failed doesn't stay fixed. (Use the
test-driven-developmentskill for the red-green discipline here.) - Make one change addressing the root cause. No "while I'm in here" refactors or bundled improvements; they muddy what actually fixed it.
- Verify: the new test passes, the original symptom is gone, and nothing else broke. Don't claim it's fixed off a code change alone: run it. (The
verify-completionskill covers this gate.)
When fixes keep failing
Count your attempts. If three fixes have failed, stop fixing. Three failures, especially when each one reveals a new problem in a different place, or each "fix" needs a larger refactor to work, is not a run of bad luck. It is a sign the underlying design is wrong. Step back and question the architecture itself with the user before attempting a fourth patch. That is a different conversation, not another guess.
Red flags in your own thinking
These thoughts all mean return to Step 1:
- "Quick fix now, understand it later."
- "It's probably X, let me just change that."
- "Let me change a few things and run the tests."
- "I'll skip the test and check it by hand."
- "I don't fully get it, but this might work."
- Listing fixes before you've traced the data flow.
- "One more attempt", after you've already tried two.
If there really is no single root cause
Occasionally thorough investigation shows the issue is genuinely environmental, timing-dependent, or external. Then: document what you ruled out, implement appropriate handling (retry, timeout, a clear error, monitoring), and move on. But reach this conclusion only after the investigation above, most "no root cause" calls are just incomplete ones.
Attribution
Adapted from the systematic-debugging entry of superpowers by Jesse Vincent (MIT). The structure and the core rules are theirs; the wording, the examples, and the integration with this registry's other items are this repository's.
This is the skill as installed, rendered from its source on GitHub. Read it as Markdown.
More in engineering
- adversarial-reviewerReview code through three hostile personas - the Saboteur, the New Hire, and the Security Auditor - each required to find at least one issue. Use when a...
- api-design-reviewReview an API contract (REST or GraphQL) before or while it is implemented, checking resource naming, HTTP semantics, status codes, error shape...
- code-review-responseProcess code-review feedback with technical rigour. Understand each point, check it against the actual codebase, and respond with reasoning or...
- create-agentAuthor a new subagent for this repository end to end by scaffolding it with pnpm new, curating its tool allowlist, setting model, color, and memory in...
- create-commandAuthor a new slash command for this repository end to end by scaffolding it with pnpm new, writing the frontmatter and argument handling, drafting the...
- create-hookAuthor a new Claude Code hook for this repository end to end by scaffolding it with pnpm new, writing the hook script and its settings.json wiring...