From core
Use when investigating bugs, diagnosing issues, or understanding unexpected behavior. Provides systematic approaches to finding root causes.
How this skill is triggered — by the user, by Claude, or both
Slash command
/core:debuggingThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Systematic approaches to investigating and diagnosing bugs.
Systematic approaches to investigating and diagnosing bugs.
Understand before fixing. A proper diagnosis leads to a proper fix.
Gather all the facts:
Evidence to collect:
Based on symptoms, what could cause this?
Common categories:
Prioritize hypotheses:
Design experiment to prove/disprove:
Keep notes:
**Hypothesis:** Database query timeout
**Test:** Add query timing logs
**Result:** Query completes in 50ms
**Conclusion:** Not the database ❌
**Hypothesis:** Network latency
**Test:** Check network tab, add timing
**Result:** API call takes 5 seconds
**Conclusion:** Found the issue ✅
What did you learn?
If root cause found:
If not found:
Most universally useful technique:
// Strategic console.log placement
function processOrder(order) {
console.log('processOrder START:', { orderId: order.id })
const items = order.items
console.log('items:', items.length)
const validated = validate(items)
console.log('validation result:', validated)
if (!validated.success) {
console.log('validation failed:', validated.errors)
throw new Error('Invalid order')
}
const total = calculateTotal(items)
console.log('total calculated:', total)
console.log('processOrder END')
return total
}
Logging guidelines:
Interactive debugging:
// Browser
function buggyFunction(input) {
debugger; // Execution pauses here
const result = transform(input)
debugger; // And here
return result
}
// Node.js
node --inspect app.js
# Then open chrome://inspect in Chrome
Debugger features:
Isolate the problem area:
// 100 lines of code, bug somewhere
// Comment out lines 50-100
// Bug still happens? It's in lines 1-50
// Comment out lines 25-50
// Bug disappears? It's in lines 25-50
// Comment out lines 37-50
// Bug still happens? It's in lines 25-37
// Continue until isolated to specific lines
Explain the problem out loud:
Why this works: Forces you to examine assumptions.
What's different?
Version comparison:
# Find which commit broke it
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
# Git checks out middle commit
npm test
git bisect good/bad
# Repeat until found
Environment comparison:
What changed?
Reduce to minimal reproduction:
// Complex case with bug
processUserOrderWithDiscountsAndShipping(user, cart, promo, address)
// Simplify inputs one at a time
processUserOrderWithDiscountsAndShipping(user, [], null, null)
// Still breaks? Not discount or address
processUserOrderWithDiscountsAndShipping(null, [], null, null)
// Works now? It's the user object
// What about the user object causes it?
Question everything:
// Assumption: API returns array
const users = await api.getUsers()
users.forEach(...) // Crashes
// Check assumption
console.log(typeof users) // "undefined"
console.log(users) // undefined
// Assumption was wrong!
Common wrong assumptions:
Likely causes:
Investigation:
Check differences:
Don't guess - profile:
Frontend:
Backend:
Investigation:
// Take heap snapshot
// Do operation that leaks
// Take another heap snapshot
// Compare - what increased?
Common causes:
Read the stack trace:
Error: Cannot read property 'map' of undefined
at processUsers (app.js:42:15)
at handleRequest (app.js:23:3)
at Server.<anonymous> (server.js:12:5)
Stack trace tells you:
Then:
// Bug
function process(user) {
return user.name.toUpperCase() // Crashes if user is null
}
// Investigation
console.log('user:', user) // undefined - why?
// Trace back to where user comes from
// Bug
for (let i = 0; i <= array.length; i++) { // <= instead of <
process(array[i]) // Crashes on last iteration
}
// Investigation
console.log('i:', i, 'length:', array.length)
// Notice i === array.length causes array[i] === undefined
// Bug
let data
fetchData().then(result => {
data = result
})
console.log(data) // undefined - async not complete
// Investigation
console.log('1. Before fetch')
fetchData().then(result => {
console.log('3. Got result')
data = result
})
console.log('2. After fetch call')
// Output: 1, 2, 3 - async completes later
// Bug
function addItem(cart, item) {
cart.items.push(item) // Mutates input!
return cart
}
const originalCart = { items: [] }
const newCart = addItem(originalCart, item)
// originalCart was modified - unexpected!
// Investigation
console.log('before:', originalCart)
const newCart = addItem(originalCart, item)
console.log('after:', originalCart) // Changed!
// Bug
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100)
}
// Prints: 3, 3, 3 (expected 0, 1, 2)
// Investigation
// var is function-scoped, i is shared
// By time timeout fires, loop is done, i === 3
// Fix: Use let (block-scoped) or capture i
Console:
console.log() - Print valuesconsole.table() - Display arrays/objects as tableconsole.trace() - Print stack traceconsole.time() / console.timeEnd() - Measure durationDebugger:
Network:
Performance:
# Search for text in files
grep -r "error" logs/
# Follow log file
tail -f logs/app.log
# Search with context
grep -B 5 -A 5 "ERROR" logs/app.log
# Find large files
du -sh *
# Check disk space
df -h
# Check memory
free -m
# Check running processes
ps aux | grep node
-- PostgreSQL
EXPLAIN ANALYZE SELECT * FROM users WHERE email = '[email protected]';
-- Show slow queries
SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;
-- Check table size
SELECT pg_size_pretty(pg_total_relation_size('users'));
-- Check indexes
\d users
BAD: "Maybe if I change this... nope, try this... nope, try this..."
GOOD: "Hypothesis: X causes Y. Test: Change X. Result: Y still happens.
Conclusion: X is not the cause."
BAD: "The API must be returning valid data"
GOOD: "Let me log the API response to see what it actually returns"
BAD: "The page is blank. Fixed by adding a null check."
GOOD: "The page is blank because user is null. User is null because
authentication token expired. Root cause: token not being refreshed."
BAD: "Let me add console.log to production to see..."
GOOD: "Let me reproduce locally and debug there, or use proper logging"
BAD: "It crashed once, let me guess why"
GOOD: "Let me find reliable way to reproduce it first"
Debugging is detective work. Be methodical, not random.
npx claudepluginhub thedotmack/han --plugin coreGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.