Diagnose and fix a bug end-to-end with forced primary-source investigation before any code change. Independently reproduces the bug, designs a fix, delegates implementation to build-step, then verifies the original symptom is gone. Built to break the command-paste loop with the user. Invoke as "/user-debug --symptom '...' [flags]".
Scanned 9/3/2026
Install to Claude Code
npx -y skills add aberson/skill-mesh --skill user-debug --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of User Debug?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aberson-user-debug)More formats (shields.io, HTML) on the badges page.
---
name: user-debug
description: Diagnose and fix a bug end-to-end with forced primary-source investigation before any code change. Independently reproduces the bug, designs a fix, delegates implementation to build-step, then verifies the original symptom is gone. Built to break the command-paste loop with the user. Invoke as "/user-debug --symptom '...' [flags]".
user-invocable: true
---
# User Debug
Run a bug report end-to-end: investigate, reproduce, design, fix, verify.
Avoid the command-paste loop with the user.
Run diagnostic commands yourself, read logs yourself, and verify CLI
suggestions against argparse before invoking them.
## When to use
Use `/user-debug` when:
- Something is broken and you want a fix, not just a discussion.
- You have a symptom (log line, error, screenshot) but not a confirmed root
cause.
- You want the LLM to do the triage instead of pasting commands back and
forth.
Use something else when:
- The fix is a one-character typo you can do faster yourself.
- You want to discuss the design before committing — use a regular
conversation.
- The work is forward-feature, not a bug — use `/build-step`.
## Arguments
| Arg | Required | Default | Description |
|---|---|---|---|
| `--symptom` | yes | -- | What's broken. Quote the error, log line, or describe the misbehavior precisely. |
| `--repro` | no | -- | Command or steps to reproduce. If omitted, the skill derives one from the symptom. |
| `--issue` | no | -- | GitHub issue number to link/close. |
| `--triage` | no | `quick` | `quick` (worktree + reviewers) or `investigate-only` (Diagnosis Block then stop). `full` is accepted as a deprecated synonym for `quick` — the prior TDD-driven `full` mode delegated to `/build-step-tdd`, which was archived 2026-05-24 after 0 invocations. |
| `--review` | no | `code` | `none`, `code` (review-gauntlet lean profile), `auto` (gates only). Applies to both quick and full. |
| `--max-iter` | no | 3 | Max developer iterations inside the delegated build skill. |
| `--skip-verify` | no | false | Skip Step 5 (verify-against-original-repro). DANGEROUS — only use when the repro is too expensive or impossible from the skill's environment (multi-hour soak, hardware-bound, live opponent required). The skill prints a loud warning and records the skip in the final report. |
## Steps
### Step 0 — Pre-flight & memory citation
1. **Detect platform.** Check `$env:OS` / `uname` / git config to identify Windows vs Linux/Mac.
State the detected platform in chat output ("Platform: Windows 11" or "Platform: Linux").
Use PowerShell syntax (no `&&`, no `export`, use `$env:VAR`) for user-facing commands on Windows; bash on Linux/Mac.
Note that the skill's own Bash tool calls are unaffected — this is for commands the user might run.
2. **Cite relevant memory.** Read MEMORY.md AND all project_*.md files in the same memory directory BEFORE Step 1 begins.
Do this before any diagnostic commands run.
Do not defer this scan into Step 1; it is a pre-investigation check.
Check each entry against five categories:
(1) **symptom keywords** (the exact error text or its component words),
(2) **file paths** mentioned in the symptom,
(3) **module names** (Python/JS imports referenced),
(4) **command/tool names** (the executable that produced the error), and
(5) **failure-mode patterns** (e.g., `silent`, `encoding`, `corrupt`, `stale path`, `subprocess`, `hang`, `race`).
Add **every matching entry** by `feedback_*.md` filename inline — no paraphrase, cite all as the default.
Apply the runaway-match carve-out when ≥10 entries match across all five categories combined:
cite the most-recent 8 by file mtime plus a one-line footer ``N additional matches truncated, see `grep -l <pattern> <memory-dir>` for full list``.
If none apply, say so explicitly.
3. **Detect project context.** Stack, test command, lint, typecheck,
dependency install. Same detection logic as `/build-step` Step 0.
4. **Stash uncommitted changes** (only if `--triage` is `quick` or `full`):
```bash
git status --porcelain
# If changes exist:
git stash push -m "user-debug pre-run state" --include-untracked
```
### Step 1 — Investigation (forced; output is a Diagnosis Block, not a fix)
Do not skip this step. Output structured diagnosis with primary-source citations.
1. **Read the symptom carefully.** Note that a log line, error message, or file path in the symptom is the entry point.
2. **Pull primary sources directly:**
- Error message → grep for the exact string in source.
- Log line → grep for the format string that would produce it.
- Misbehavior → read the code path that should handle it (don't guess
from name — read it).
- CLI failure → read the script's argparse and confirm the flag/module
path exists. **Never invoke a command without verifying its argparse
first** — covers the rename-trap (e.g., `alpha4gate.runner` →
`bots.v0.runner`).
3. **Run diagnostic commands yourself with the Bash tool.** Do NOT ask the
user to paste output for things you can run.
4. **For commands that must run on the user's interactive terminal** (GUI app, SC2 client, anything platform-bound):
Write the verified PowerShell command.
Use Write-then-`bash <path>` for WSL multi-line scripts (inline `bash -lc 'multi-line'` is unreliable).
Always quote `/mnt/c/...` args from Git Bash inside `bash -lc '...'` to prevent MSYS rewrite.
5. **Reproduce the bug.** Run `--repro` if given; else derive one (the failing test, the failing endpoint, the code path) and run that.
Write the bad output verbatim — Step 5 compares against this exact text.
Use the Diagnosis Block as an **output gate**, not just a template.
Do not mark Step 1 done until all six required fields are filled:
**Symptom**, **Reproduction**, **Primary sources**, **Suspected root
cause**, **Confidence**, and **Memory entries that apply**.
Write after Step 1:
```markdown
## Diagnosis
**Symptom (verbatim from input or observed):**
<exact text>
**Reproduction:**
$ <command>
<observed output, quoted>
**Primary sources:**
- <file:line>: `<code snippet>`
- <log file:line>: `<log line>`
- <argparse line>: `<flag/module>`
**Suspected root cause:**
<paragraph with file:line citations inline>
**Confidence:** high | medium | low
**Ruled out (when applicable):**
- <hypothesis 1> — <why ruled out, with file:line evidence>
- <hypothesis 2> — <why ruled out, with file:line evidence>
**Memory entries that apply:**
- `<feedback_*.md>` — <one-line gloss>
```
Stop on `--triage investigate-only`: hand to user.
**Feature-shaped, not a bug?** If Step 1's investigation concludes the symptom is not a
defect — the code works as designed and the ask is really designed, multi-step work —
that is the routing web's bug→plan direction: follow
[`skill-pipeline.md § Re-route contract`](../_shared/skill-pipeline.md) instead of
forcing a fix. The correct-rail seed is a `/plan-feature` seed built from the Diagnosis
Block; write back to the intake ledger when one exists, per the contract, and stop.
### Step 2 — Independent reproduction (always)
Run an Explore sub-agent in parallel (dispatch with explicit `model: sonnet` —
this is a diagnostic-diversity arm; it must never inherit an escalated session,
or escalation would strengthen the independence check itself) and give it the
symptom and repro instructions, but **NOT** the suspected root cause.
Pass it one job: come to its own conclusion, then we compare:
- Diagnoses match → confidence becomes high, proceed; **but matching
MEDIUM confidence does NOT upgrade to high**.
Mark the combined confidence as medium.
- Diverge → do not proceed to Step 3. First classify the divergence shape,
then present a Diagnosis Comparison block.
Apply one of the four resolution options below.
Never synthesize a hybrid third diagnosis.
Write a Diagnosis Comparison block when diagnoses diverge:
```markdown
## Diagnosis Comparison
**Orchestrator:** <root cause: file:line — mechanism; confidence>
**Independent sub-agent:** <root cause: file:line — mechanism; confidence>
**Divergence type:** <one of the four shapes below>
```
Mark the divergence as one of four shapes before choosing a
resolution:
- **Different file:line** — different root cause at a different code
location.
- **Same location, different mechanism** — same code site, different
theory about why it fails.
- **Same root cause, different confidence** — agreement on what,
disagreement on how sure.
- **One can reproduce, the other cannot** — reproduction divergence is
itself a real diagnostic.
Apply one resolution:
1. **Re-investigate** — run diagnostic commands targeting the divergence point itself.
Re-grep the contested file, re-read the contested code, re-run the repro with extra logging.
Apply when divergence is "different file:line" or "same location, different mechanism" and one extra command might resolve it.
2. **Surface to user** — present both diagnoses side-by-side using the
Diagnosis Comparison block above and ask the user to disambiguate
using domain knowledge the LLMs lack. Best when re-investigation has
not yielded convergence after one extra round, or the divergence
requires domain-specific intuition.
3. **Proceed with confidence marked low/medium** — only when the
divergence is minor (same mechanism, different call site; or same
root cause, different confidence) and the fix design is robust to
either interpretation. The Diagnosis Block's **Confidence** field
must be set to low/medium and the Fix Design's **Risk** field must
explicitly acknowledge the divergence.
4. **Tie-breaker third sub-agent** — only after Option 1 re-investigation
has been tried and the two diagnoses still diverge. Spawn a FRESH
sub-agent (explicit `model: sonnet`, same pin as Step 2's arm) given
only the symptom + repro instructions and NEITHER
prior diagnosis (same constraint as Step 2's original independent
sub-agent). Its independent verdict breaks the tie or confirms the
divergence is genuine (in which case escalate to Option 2 — surface
to user — with all three diagnoses laid out).
### Step 3 — Fix design (no code yet)
Write output:
```markdown
## Fix Design
**Change:** <one paragraph on what changes>
**Files touched:** <list with line ranges>
**Regression test:** <path, what it asserts, how it would fail today>
**Risk:** <what else this could break, why it won't>
**Rollback:** <how to undo>
```
Confirm the design with the user before delegating to Step 4.
### Step 4 — Implement (delegate)
Build a combined problem statement from the Diagnosis Block + Fix Design
Block.
Write the full combined text inline in your chat output before invoking
the delegated skill.
Do NOT collapse the blocks to a placeholder like `<combined problem>` or
`<Diagnosis Block from Step 1>`.
Ensure the actual prose of the Diagnosis and Fix Design blocks appears in
the message so the user sees the prompt the developer agent will receive.
Template:
```markdown
PROBLEM (bug fix):
<Diagnosis Block from Step 1>
<Fix Design Block from Step 3>
REQUIREMENTS:
- Add the regression test described in the Fix Design Block. The test must
fail against the current code (before the fix is applied).
- Implement the fix described in the Fix Design Block.
- Touch only the files listed under "Files touched"; if you need to touch
another file, stop and report why.
- Make surgical edits, not whole-file rewrites: in a multi-step phase,
whole-file rewrites overwrite shared files modified by prior steps and
cause worktree merge conflicts (see `feedback_buildphase_worktree_merge.md`;
rule-file home: `.claude/rules/worktree-hygiene.md § "Shared-file merges across steps"`).
```
Delegate to `/build-step` (both `quick` and the deprecated `full` synonym
route here):
```bash
/build-step --problem "<combined problem>" --reviewers <--review value> --max-iter <--max-iter> [--issue <N>]
```
Stop on `/build-step` BLOCKED: do not proceed to Step 5.
Pass the block to the user with the underlying reason (failing test,
max iterations exhausted, etc.).
### Step 5 — Verify the fix (against the ORIGINAL repro)
Run the **original reproduction from Step 1** again against the fixed code.
```text
**Before (Step 1):**
$ <repro command>
<bad output>
**After (Step 5):**
$ <same repro command>
<output now>
```
Check the two outputs verbatim.
Mark BLOCKED if the after-output still shows the symptom.
Do not merge to main.
Pass the gap to the user with options: re-investigate, accept partial
improvement, or revert.
#### `--skip-verify` (dangerous)
Skip this step but print the following warning when `--skip-verify` was passed:
```text
!!! VERIFY-AGAINST-REPRO SKIPPED (--skip-verify) !!!
The fix passed gates and reviewers, but the original symptom was NOT
re-checked against the fixed code. The bug may persist in a way the
test suite does not capture.
Reason for skip: <user-supplied or "not provided">
```
Document the skip in the final report.
Apply only when the repro is genuinely expensive (multi-hour soak,
hardware-bound, requires live opponent) or impossible from the skill's
environment.
### Step 6 — Merge & report
Continue if verify passed (or was skipped):
1. Confirm changes are in the project tree (the delegated build skill
already merged its worktree).
2. Run gates in main project as a final sanity check.
Always emit the actual command + tail of output in the chat.
Do NOT only state the result line in the final report — the user must
see proof the gates ran. Format:
```bash
$ <typecheck command>
<last 1-3 lines of output>
$ <lint command>
<last 1-3 lines of output>
$ <test command>
<last 1-3 lines of output>
```
3. Restore stash if Step 0.4 created one.
4. Close issue if `--issue` given. Use `gh -R <owner>/<repo>` from inside
the project directory (the workspace `dev/` root resolves to a different
repo per `.claude/rules/windows-shell.md § gh / jq`).
Add a comment containing the fix commit hash + a one-line
"symptom-gone" confirmation from Step 5's verify-against-repro so a
future LLM viewing the closed issue can verify the fix actually shipped.
Use `--body-file` for multi-line comments.
5. Report:
```text
user-debug complete
Triage: quick | investigate-only
Diagnosis confidence: high | medium | low (independently confirmed: yes | no | diverged)
Files changed: N
Regression test: <test path>
Gates: typecheck OK, lint OK, test OK
Delegated to: /build-step
Delegated verdict: PASS (iteration N/M)
Review: PASS | NEEDS WORK | skipped (if --review code)
Repro before/after: SYMPTOM GONE | SKIPPED (--skip-verify)
Issue: #N closed
```
## Write-as-you-go
Bug investigation is the highest-risk scenario for context loss. Hypotheses formed and
ruled out, repro conditions confirmed, root cause narrowed — all of this lives in context,
none of it reaches disk until the fix ships (or at all if compaction fires mid-investigation).
user-debug MUST write to `current.md` at 6 trigger points during execution.
Write at the moment of discovery — NOT at fix completion. The dead ends list IS the
investigation state.
**Path resolution (MUST use git root — never worktree-relative):**
```powershell
$gitRoot = (git rev-parse --show-toplevel).Trim()
$statePath = "$gitRoot/.claude/task-state/current.md"
```
### Trigger points
| # | Trigger | What to write to current.md |
|---|---------|------------------------------|
| 1 | Repro confirmed | MUST overwrite `WIP.Approach`: `"Repro confirmed: [conditions]"` |
| 2 | Any hypothesis formed | MUST append to `WIP`: hypothesis + evidence for it (one line) |
| 3 | Any hypothesis ruled out | MUST append to `Dead Ends`: hypothesis + why ruled out (with evidence) |
| 4 | Root cause identified | MUST overwrite `WIP`: `"Root cause: [description]"` |
| 5 | Fix design agreed | MUST append to `Critical Gotchas`: key constraint the fix must satisfy |
| 6 | Fix complete (build-step returns PASS) | MUST append to `Completed`: bug + root cause + fix commit SHA |
**Trigger 3 is the most critical.** Dead-end writes MUST happen at dismissal time —
immediately when the hypothesis is ruled out — not at the end of investigation.
If compaction fires mid-investigation, the next context reads the dead ends list and
continues from where investigation left off without repeating ruled-out paths.
### Write formats
**Dead Ends** (trigger 3 — MUST append immediately at dismissal):
```
- [hypothesis in 5-10 words]: [why ruled out — specific evidence, file:line if applicable]
```
**WIP.Approach** (triggers 1, 4 — overwrite):
```
**Approach:** Repro confirmed: [exact conditions]
```
or
```
**Approach:** Root cause: [description with file:line]
```
**Completed** (trigger 6 — append):
```
- [<sha>] user-debug [bug description]: [root cause summary] — fixed
```
**Critical Gotchas** (trigger 5 — append):
```
- [fix constraint]: [why violating it would break the fix or cause regression]
```
### Schema reference
Full field definitions, overwrite/append rules, and lifecycle:
`.claude/references/task-state-schema.md` (workspace reference, not published in this mirror)
---
## Constraints
Do not soften rules under pressure.
Note that if the skill's structure feels too verbose mid-task, that's the
bias firing — not a signal to skip steps.
Keep the verbosity; it is the mechanism.
## Stop-and-audit rule
Stop fixing one-at-a-time when you encounter a 3rd instance of the same
bug shape (producer/consumer drift, silent exception fallthrough in a
loop, hardcoded constant mismatch, schema-without-migration).
Grep for siblings.
Land one comprehensive fix.
See `/build-step` SKILL.md for the full rationale and examples.
## Limitations
- Worktree isolation only (no Docker option — use `/build-step --isolation
docker` directly if you need clean-room).
- Step 5 (verify-against-repro) requires a deterministic repro. For flaky
bugs, may need multiple runs to establish baseline rate before/after.
- Delegates to `/build-step`, so inherits its limitations.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!