root-cause-tracing · secondsky — Claude Code skill: trace bugs to the source
Walks an agent backward through the call stack until it finds the original trigger. Useful when an error surfaces deep in execution, not at the entry point.
npx skills add secondsky/claude-skills --skill root-cause-tracing -a claude-codeWhat root-cause-tracing does
The skill lays out a fixed order of work: observe the symptom, find the code that directly causes it, then ask what called that code, and keep going up until you reach the place where the bad value entered. The worked example is a git init that runs inside the source tree because an empty string was passed as cwd and an empty string resolves to process.cwd(). The real fault sat in a variable read before beforeEach, not in the command itself.
When manual tracing stalls, the skill has you add instrumentation: log the directory, cwd, environment variables and new Error().stack right before the risky call. In tests it insists on console.error() rather than a logger, since loggers can be suppressed. You then capture the run and grep for the debug marker to see which file and line fires the call.
If you don't know which test is polluting things, there's a one-by-one approach: bun test --run --bail 2>&1 | tee test-output.log stops at the first offender. The rule the skill keeps repeating is not to patch where the error appeared. In the documented session, fixing the source plus four layers of defence ended with 1847 passing tests and no pollution.
What it helps with
- find where an empty value entered a function
- identify which test writes files into the wrong directory
- unwind a long call chain back to its trigger
- add stack output before a dangerous operation
- decide between patching the symptom and fixing the source
Example prompts for the agent
- This error shows up deep in the call stack — trace backward and find the original trigger
- Something leaves junk in the project during tests; run them one by one and find the polluter
- Add stack and context logging before this call so we can see who invokes it
How to install root-cause-tracing
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill root-cause-tracing -a claude-code2Manually: put the files in place
~/.claude/skills/root-cause-tracing/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/root-cause-tracing/
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill root-cause-tracing -a codex2Manually: put the files in place
.agents/skills/root-cause-tracing/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill root-cause-tracing -a cursor2Manually: put the files in place
.cursor/skills/root-cause-tracing/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install secondsky/claude-skills root-cause-tracing2Manually: put the files in place
.github/skills/root-cause-tracing/SKILL.md1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill root-cause-tracing -a gemini-cli2Platform CLI
gemini skills install https://github.com/secondsky/claude-skills --path plugins/root-cause-tracing/skills/root-cause-tracingManually: put the files in place
.devin/skills/root-cause-tracing/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill root-cause-tracing -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about root-cause-tracing
How do I install root-cause-tracing in Claude?
Run npx skills add secondsky/claude-skills --skill root-cause-tracing -a claude-code. The skill then lives at ~/.claude/skills/root-cause-tracing/SKILL.md.
What does root-cause-tracing do?
It documents a backward pass through the call stack: from the symptom to the immediate cause and further up until the original trigger turns up. It also covers where to place stack logging and how to isolate a polluting test.
How is this different from debugging at the point of failure?
The skill explicitly rules out fixing where the error surfaced. You locate the source of the bad value first, fix there, and add defence in layers.
Source text
SKILL.md · MIT
---
name: root-cause-tracing
description: Systematically trace bugs backward through call stack to find original trigger. Use when errors occur deep in execution and you need to trace back to find the original trigger.
metadata:
version: "1.1.0"
license: MIT
---
# Root Cause Tracing
## Overview
Bugs often manifest deep in the call stack (git init in wrong directory, file created in wrong location, database opened with wrong path). Your instinct is to fix where the error appears, but that's treating a symptom.
**Core principle:** Trace backward through the call chain until you find the original trigger, then fix at the source.
## When to Use
**Use when:**
- Error happens deep in execution (not at entry point)
- Stack trace shows long call chain
- Unclear where invalid data originated
- Need to find which test/code triggers the problem
## The Tracing Process
### 1. Observe the Symptom
```
Error: git init failed in ~/project/packages/core
```
### 2. Find Immediate Cause
**What code directly causes this?**
```typescript
await execFileAsync('git', ['init'], { cwd: projectDir });
```
### 3. Ask: What Called This?
```typescript
WorktreeManager.createSessionWorktree(projectDir, sessionId)
→ called by Session.initializeWorkspace()
→ called by Session.create()
→ called by test at Project.create()
```
### 4. Keep Tracing Up
**What value was passed?**
- `projectDir = ''` (empty string!)
- Empty string as `cwd` resolves to `process.cwd()`
- That's the source code directory!
### 5. Find Original Trigger
**Where did empty string come from?**
```typescript
const context = setupCoreTest(); // Returns { tempDir: '' }
Project.create('name', context.tempDir); // Accessed before beforeEach!
```
## Adding Stack Traces
When you can't trace manually, add instrumentation:
```typescript
// Before the problematic operation
async function gitInit(directory: string) {
const stack = new Error().stack;
console.error('DEBUG git init:', {
directory,
cwd: process.cwd(),
nodeEnv: process.env.NODE_ENV,
stack,
});
await execFileAsync('git', ['init'], { cwd: directory });
}
```
**Critical:** Use `console.error()` in tests (not logger - may not show)
**Run and capture:**
```bash
bun test 2>&1 | grep 'DEBUG git init'
```
**Analyze stack traces:**
- Look for test file names
- Find the line number triggering the call
- Identify the pattern (same test? same parameter?)
## Finding Which Test Causes Pollution
If something appears during tests but you don't know which test:
Use the bisection script to run tests one-by-one:
```bash
# Example: find which test creates .git in wrong place
bun test --run --bail 2>&1 | tee test-output.log
```
Runs tests one-by-one, stops at first polluter.
## Real Example: Empty projectDir
**Symptom:** `.git` created in `packages/core/` (source code)
**Trace chain:**
1. `git init` runs in `process.cwd()` ← empty cwd parameter
2. WorktreeManager called with empty projectDir
3. Session.create() passed empty string
4. Test accessed `context.tempDir` before beforeEach
5. setupCoreTest() returns `{ tempDir: '' }` initially
**Root cause:** Top-level variable initialization accessing empty value
**Fix:** Made tempDir a getter that throws if accessed before beforeEach
**Also added defense-in-depth:**
- Layer 1: Project.create() validates directory
- Layer 2: WorkspaceManager validates not empty
- Layer 3: NODE_ENV guard refuses git init outside tmpdir
- Layer 4: Stack trace logging before git init
## Key Principle
**NEVER fix just where the error appears.** Trace back to find the original trigger.
## Stack Trace Tips
**In tests:** Use `console.error()` not logger - logger may be suppressed
**Before operation:** Log before the dangerous operation, not after it fails
**Include context:** Directory, cwd, environment variables, timestamps
**Capture stack:** `new Error().stack` shows complete call chain
## Real-World Impact
From debugging session:
- Found root cause through 5-level trace
- Fixed at source (getter validation)
- Added 4 layers of defense
- 1847 tests passed, zero pollution
© secondsky · MIT · secondsky/claude-skills
Similar skills
All skills for Agent setup: memory, context, orchestration →root-cause-tracing by other authors comes first.