From hyperpowers
Use when encountering bugs or test failures - systematic debugging using debuggers, internet research, and agents to find root cause before fixing
How this skill is triggered — by the user, by Claude, or both
Slash command
/hyperpowers:debugging-with-toolsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<skill_overview>
<skill_overview> Random fixes waste time and create new bugs. Always use tools to understand root cause BEFORE attempting fixes. Symptom fixes are failure. </skill_overview>
<rigidity_level> MEDIUM FREEDOM - Must complete investigation phases (tools → hypothesis → test) before fixing.
Can adapt tool choice to language/context. Never skip investigation or guess at fixes. </rigidity_level>
<quick_reference>
| Phase | Tools to Use | Output |
|---|---|---|
| 1. Investigate | Error messages, internet-researcher agent, debugger, codebase-investigator | Root cause understanding |
| 2. Hypothesize | Form theory based on evidence (not guesses) | Testable hypothesis |
| 3. Test | Validate hypothesis with minimal change | Confirms or rejects theory |
| 4. Fix | Implement proper fix for root cause | Problem solved permanently |
FORBIDDEN: Skip investigation → guess at fix → hope it works REQUIRED: Tools → evidence → hypothesis → test → fix
Key agents:
internet-researcher - Search error messages, known bugs, solutionscodebase-investigator - Understand code structure, find related codetest-runner - Run tests without output pollution</quick_reference>
<when_to_use> Use for ANY technical issue:
ESPECIALLY when:
<the_process>
BEFORE attempting ANY fix, gather evidence with tools:
Dispatch internet-researcher with:
"Search for error: [exact error message]
- Check Stack Overflow solutions
- Look for GitHub issues in [library] version [X]
- Find official documentation explaining this error
- Check if this is a known bug"
What agent should find:
Claude cannot run debuggers directly. Instead:
Option A - Recommend debugger to user:
"Let's use lldb/gdb/DevTools to inspect state at error location.
Please run: [specific commands]
When breakpoint hits: [what to inspect]
Share output with me."
Option B - Add instrumentation Claude can add:
// Add logging
println!("DEBUG: var = {:?}, state = {:?}", var, state);
// Add assertions
assert!(condition, "Expected X but got {:?}", actual);
Dispatch codebase-investigator with:
"Error occurs in function X at line Y.
Find:
- How is X called? What are the callers?
- What does variable Z contain at this point?
- Are there similar functions that work correctly?
- What changed recently in this area?"
Based on evidence (not guesses):
Example:
Known: Error "null pointer" at auth.rs:45 when email is empty
Theory: Empty email bypasses validation, passes null to login()
Prediction: Adding validation before login() will prevent error
Test: Add validation, verify error doesn't occur with empty email
NEVER:
Minimal change to validate theory:
If confirmed: Proceed to Phase 4 If rejected: Return to Phase 1 with new information
After understanding root cause:
The fix should:
</the_process>
Developer encounters test failure, immediately tries "obvious" fix without investigation
Test error:
```
FAIL: test_login_expired_token
AssertionError: Expected Err(TokenExpired), got Ok(User)
```
Developer thinks: "Obviously the token expiration check is wrong"
Makes change without investigation:
// "Fix" - just check if token is expired
if token.expires_at < now() {
return Err(AuthError::TokenExpired);
}
Commits without testing other cases.
<why_it_fails> No investigation:
expires_at containsWhat actually happened: Token expires_at was being parsed incorrectly, always showing future date. The "fix" adds dead code that never runs.
Result: Bug not fixed, new dead code added, time wasted. </why_it_fails>
**Phase 1 - Investigate with tools:**# 1. Read complete error
FAIL: test_login_expired_token at line 45
Expected: Err(TokenExpired)
Got: Ok(User { id: 123 })
Token: { expires_at: "2099-01-01", ... }
Dispatch internet-researcher:
"Search for: token expiration always showing future date
- Check date parsing bugs
- Look for timezone issues
- Find JWT expiration handling"
Add instrumentation:
println!("DEBUG: expires_at = {:?}, now = {:?}, expired = {:?}",
token.expires_at, now(), token.expires_at < now());
Run test again:
DEBUG: expires_at = 2099-01-01T00:00:00Z, now = 2024-01-15T10:30:00Z, expired = false
Phase 2 - Hypothesis:
"Token expires_at is being set to 2099, not actual expiration. Problem is in token creation, not validation."
Phase 3 - Test: Check token creation code:
// Found the bug!
fn create_token() -> Token {
Token {
expires_at: "2099-01-01".parse()?, // HARDCODED!
...
}
}
Phase 4 - Fix root cause:
fn create_token(duration: Duration) -> Token {
Token {
expires_at: now() + duration, // Correct
...
}
}
Result: Root cause fixed, test passes, no dead code.
Developer skips internet search, reinvents solution to known problem
Error:
```
error: linking with `cc` failed: exit status: 1
ld: symbol(s) not found for architecture arm64
```
Developer thinks: "Must be a linking issue, I'll add flags"
Spends 2 hours trying different linker flags:
[target.aarch64-apple-darwin]
rustflags = ["-C", "link-arg=-undefined dynamic_lookup"]
# Doesn't work, tries more flags...
<why_it_fails> Skipped internet search:
Why it happens: Impatience, thinking "I can figure this out faster" </why_it_fails>
**Dispatch internet-researcher FIRST:**"Search for: 'symbol not found for architecture arm64' Rust linking
- Check Stack Overflow solutions
- Look for Xcode/macOS specific fixes
- Find Cargo configuration for Apple Silicon"
Agent returns (30 seconds):
Found on Stack Overflow (2.4k upvotes):
This occurs when Xcode Command Line Tools aren't installed or outdated.
Solution:
xcode-select --install
Or update existing:
softwareupdate --all --install --force
Apply solution:
xcode-select --install
# Wait for installation
cargo build
# Success!
Result: Fixed in 5 minutes, not 2 hours.
Developer fixes symptom without understanding root cause, bug returns different way
Bug: Users can delete other users' posts
Developer notices: DELETE /posts/:id doesn't check ownership
"Fix":
@app.delete("/posts/{post_id}")
def delete_post(post_id: int, user: User):
post = get_post(post_id)
if post.author_id != user.id:
raise Forbidden()
delete(post)
Bug "fixed"... but bug report comes back: "Users can edit other users' posts"
<why_it_fails> Symptom fix:
Root cause: No authorization middleware checking ownership across ALL endpoints.
Result: Whack-a-mole fixing symptoms, not the underlying issue. </why_it_fails>
**Phase 1 - Investigate with codebase-investigator:**"User can delete other users' posts. Investigate:
- What authorization exists across all post endpoints?
- Is there a pattern for ownership checks?
- Which other endpoints access posts?
- Is there middleware handling this?"
Agent reports:
Found:
- DELETE /posts/:id - NO ownership check
- PUT /posts/:id - NO ownership check
- GET /posts/:id - NO ownership check (allows viewing private posts!)
- No authorization middleware found
- Similar pattern in comments, likes endpoints
Phase 2 - Hypothesis: "Missing authorization layer. Need middleware checking resource ownership across ALL endpoints."
Phase 4 - Fix root cause:
# Add authorization middleware
class OwnershipMiddleware:
def check_ownership(self, resource, user):
if resource.author_id != user.id:
raise Forbidden()
# Apply to all endpoints
@app.delete("/posts/{post_id}")
@require_ownership(Post)
def delete_post(...):
...
@app.put("/posts/{post_id}")
@require_ownership(Post)
def update_post(...):
...
Result: Root cause fixed, ALL endpoints secured, not just one symptom.
<critical_rules>
Tools before fixes → Never guess without investigation
Evidence-based hypotheses → Not guesses or hunches
Test hypothesis before fixing → Minimal change to validate
Fix root cause, not symptom → One fix, many symptoms prevented
All of these mean: Stop, use tools to investigate:
</critical_rules>
<verification_checklist>
Before proposing any fix:
Before committing fix:
</verification_checklist>
This skill calls:
Agents used:
Detailed guides:
When stuck:
npx claudepluginhub sqve/hyperpowersCreates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.