When to use this
- A bug has a reliable reproduction and needs its actual cause identified before fixing.
- A quick patch fixed the symptom but the same class of bug keeps recurring elsewhere.
- Not for the initial "is this even reproducible" step -- use bug-reproducer first.
The skill file
Copy this verbatim. It's written in the SKILL.md format (YAML frontmatter + markdown instructions) that Claude Code, and increasingly other agent tools, read directly.
--- name: root-cause-analyzer description: Trace a reproduced bug to its actual root cause by following the real code path and data flow, distinguishing the root cause from downstream symptoms. Use after a bug is reliably reproduced, before writing a fix. --- # Root Cause Analyzer ## Process 1. Start at the point where wrong behavior is observed, and walk backward through the actual call stack / data flow -- not the code you assume is involved, the code that's actually on the path, confirmed by reading it or adding targeted logging/breakpoints. 2. At each step, ask: is this component behaving correctly given its input? If yes, the bug is further upstream; if no, you may have found it, or another upstream cause of this component's bad input. 3. Keep going until you reach the actual point where something first goes wrong -- a wrong value, a missed check, an incorrect assumption in the code -- not just the first point where the *effect* becomes visible. 4. Distinguish root cause from contributing factors: a null-pointer crash might be "caused" by a missing null check, but the actual root cause could be further upstream (why was null even possible there). ## Common failure mode: fixing the symptom Before proposing a fix, check: does this fix address the root cause, or does it just stop the specific symptom from being visible while the underlying wrong state/logic remains? A fix that suppresses an error without addressing why the error condition occurs is a red flag. ## Output The causal chain from root cause to observed symptom, each link justified by code you actually read (not assumed), and a fix recommendation that addresses the root, with a note on any contributing factors worth fixing separately.
Installing it elsewhere
The frontmatter/body split above is Claude Code's convention. Here's how to carry the same instructions into other tools:
Save the file below verbatim (frontmatter included) at that path, project-local or in ~/.claude/skills/ for a user-level skill. Claude Code loads the name/description pair to decide when to pull it in, or you invoke it directly as /root-cause-analyzer.
Convert the YAML frontmatter to Cursor's rule format (description, globs, alwaysApply: false) and keep the markdown body as the rule content. Cursor surfaces it by description match, same idea as Claude Code's auto-load.
Codex CLI (and increasingly other agentic CLIs) read AGENTS.md at the repo root as always-on instructions. Paste the markdown body under a heading like ## {title}; for GitHub Copilot's coding agent, the equivalent file is .github/copilot-instructions.md.
Append the markdown body to .windsurfrules at the repo root. Windsurf treats the whole file as always-on context, so keep only the instructions you want applied on every request.
- Stopping at the first plausible-looking cause instead of confirming it against the actual code.
- Proposing a fix that suppresses the symptom (e.g. adding a null check) without asking why the invalid state was reachable in the first place.
- Assuming the code behaves as documented/named without reading it, especially in unfamiliar or legacy modules.