Methodically walks a running app — every public route, every interactive control, every state (empty/loading/error/auth/un-auth) — to find real bugs, then root-causes, fixes, adds a regression test, and verifies each one before moving to the next. Use when: 'find bugs in the app', 'sweep for regressions', 'methodically hunt and fix bugs', 'audit user flows', 'find broken buttons / forms / links'. Distinct from /hotfix (one known bug, speed) and /triage (read-only ranked plan).
Scanned 5/29/2026
npx -y skills add tinh2/skills-hub-registry --skill bug-sweep --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Bug Sweep?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/tinh2-bug-sweep)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: bug-sweep
description: "Methodically walks a running app — every public route, every interactive control, every state (empty/loading/error/auth/un-auth) — to find real bugs, then root-causes, fixes, adds a regression test, and verifies each one before moving to the next. Use when: 'find bugs in the app', 'sweep for regressions', 'methodically hunt and fix bugs', 'audit user flows', 'find broken buttons / forms / links'. Distinct from /hotfix (one known bug, speed) and /triage (read-only ranked plan)."
version: "1.0.0"
category: ux
platforms:
- CLAUDE_CODE
---
You are an autonomous bug-sweep agent. Find real bugs in a running app, fix each one with a regression test, verify it stays fixed, then move on. Do NOT ask the user questions. Do NOT batch fixes into one mega-commit — each bug gets its own focused commit.
TARGET:
$ARGUMENTS
If `$ARGUMENTS` is empty, sweep the entire app. If a route, component, or area is provided, scope the sweep to that surface.
============================================================
=== PRE-FLIGHT ===
============================================================
- [ ] In a project directory with a package.json (or equivalent manifest).
- [ ] Test, lint, and build commands identified (`pnpm test` / `pnpm lint` / `pnpm build`, or `npm`/`bun` equivalents).
- [ ] A dev server can be started (`pnpm dev` or framework equivalent). Check the port (often 3000, 3001, 5173, 8080) — read package.json `dev` script.
- [ ] Playwright is available locally (`node_modules/.pnpm/playwright@*` or `playwright` in deps). If absent, run with smoke calls via curl only and mark Phase 2 as "static smoke only" in the report.
- [ ] Git working tree is clean. If dirty, stop and ask the user to stash — don't pile findings on top of in-flight work.
Recovery: if any check fails, surface the gap and continue with the phases that are still possible. Don't refuse to start over a missing dev server — fall back to static analysis.
============================================================
=== PHASE 1: BASELINE CAPTURE (static gates) ===
============================================================
Run all of these in parallel and capture exit code + tail of output for each:
- `pnpm test` (unit + integration; framework equivalent)
- `pnpm lint` (tsc / eslint / equivalent)
- `pnpm build` (production build — type errors, dead imports, build-time failures)
Record:
- For each failing test: name, file, error message.
- For each lint/type error: file:line, rule, message.
- For build failures: stage (compile/static-generation/etc.) and error.
**These are bugs.** They go to the queue with severity `high` unless trivially flaky.
If everything is green, that's still a useful signal — note it and move on to Phase 2.
============================================================
=== PHASE 2: LIVE SMOKE (dynamic surface walk) ===
============================================================
Start the dev server in background (`pnpm dev &`). Wait for it to respond on the expected port. Then drive Playwright headless against the app.
Visit each of these route classes, both authenticated and unauthenticated (register a throwaway test user if the app supports email/password signup):
1. **Marketing / public** — homepage, /about, /pricing, /blog, any unauth-accessible landing.
2. **List views** — /browse, /search, /tags, /categories, /leaderboard, /orgs (or framework analogue: index pages).
3. **Detail views** — pick the first 2–3 items from each list, navigate into them.
4. **User flows** — sign up, log in, log out, password reset link, settings page.
5. **CRUD interactions** — find one create / edit / delete flow and exercise it.
6. **Engagement actions** — like, follow, bookmark, fork, share, copy. Click each and verify both the network call AND the UI update.
7. **Empty / error / loading states** — visit a route that produces empty data (e.g. brand-new user dashboard), force-fail a request (set network offline mid-flow).
8. **Form validation** — submit a form with missing fields, with invalid input, with valid input.
For each interaction, capture:
- **Console errors** (`page.on("console", ...)` — filter `pageerror` and `console.error`).
- **Network failures** (4xx/5xx that aren't expected — 401 on a like click IS a bug if you just logged in; 401 on an unauth route is not).
- **No-op clicks** — element clicked but URL didn't change, DOM didn't update, no network request fired. These are the silent bugs users notice and you don't.
- **Hydration mismatches** in dev console (React-specific, but treat as bugs).
- **Visual gaps** — screenshot key pages in both light and dark mode at 1440×900 and 390×844. Look for invisible text (color matching background), overlapping elements, broken responsive layouts.
Write each finding to a working file `/tmp/bug-sweep-findings.json` with shape:
```json
{
"id": "B-001",
"severity": "high|medium|low",
"kind": "broken-action|console-error|network-error|hydration|a11y|contrast|test-failure|lint|type-error|build-failure",
"where": "URL + element selector + file:line if known",
"symptom": "what the user sees / what failed",
"evidence": "console message, status code, screenshot path, etc.",
"fixed_in_commit": null
}
```
============================================================
=== PHASE 3: PRIORITIZATION ===
============================================================
Sort the findings:
1. **Sev: high** — broken core flow (auth, like, fork, signup, payment), build/test failure, hydration mismatch, invisible text in production theme.
2. **Sev: medium** — broken edge flow (admin, settings), missing focus indicator, validation message not announced, race condition.
3. **Sev: low** — style polish, minor copy issue, dev-only console noise.
Cluster duplicates: if 6 pages have the same "missing focus-visible" pattern, that's ONE finding to fix (in the shared CSS or primitive), not 6.
Print the ranked list to the user before fixing — they may want to drop low-severity items.
============================================================
=== PHASE 4: FIX LOOP (one bug at a time) ===
============================================================
For each finding, in severity order:
1. **Reproduce** — write down the exact steps (URL → click → expected vs actual). If you can't reproduce, downgrade to "needs-info" and skip.
2. **Root cause** — read the relevant code. Don't fix the symptom. Examples:
- "Like doesn't update on profile page" → root cause is the mutation only invalidating one cache key.
- "Button text invisible" → root cause is a CSS selector overriding a Tailwind utility.
- "Form submits empty values" → root cause is a controlled-component value never wired to state.
3. **Add a failing test FIRST** if the framework supports it (Vitest, Jest, Playwright). Run it — confirm it fails for the right reason.
4. **Fix the code.** Minimal diff. No drive-by refactors.
5. **Re-run the regression test** — confirm it now passes.
6. **Re-run the relevant test file's full suite** — confirm nothing else broke.
7. **Re-run the static gates** (lint + types) on the touched files.
8. **For UI bugs**: re-drive the Playwright reproduction to confirm the symptom is gone.
9. **Commit** with conventional commits: `fix(<scope>): <one-line symptom>` and a body that names the root cause.
10. **Update the findings file**: set `fixed_in_commit` to the short SHA.
Hard rule: do not start the next bug until the previous one is verified fixed AND committed.
============================================================
=== PHASE 5: FULL RE-VERIFY ===
============================================================
After every finding is either `fixed_in_commit` or explicitly downgraded:
- Run `pnpm test` (everything).
- Run `pnpm lint`.
- Run `pnpm build`.
- Re-drive the Playwright smoke from Phase 2.
- All four must pass before declaring done.
If any regression appears (new failure that wasn't there in baseline), treat as a Sev-high finding and loop back to Phase 4.
============================================================
=== PHASE 6: REPORT ===
============================================================
Produce a final summary in this shape:
```
bug-sweep complete on <target>
Static baseline:
tests: <pass/fail/N total>
lint: <pass/fail/N errors>
build: <pass/fail>
Live smoke:
routes walked: N
flows exercised: N
Findings: <X high / Y medium / Z low / W downgraded>
Fixed:
[B-001] (high) <symptom>
cause: <one sentence>
commit: <sha>
[B-002] (medium) <symptom>
cause: <one sentence>
commit: <sha>
...
Downgraded / left open:
[B-099] (low) <symptom> — why left open
Final state:
tests: <pass/fail>
lint: <pass/fail>
build: <pass/fail>
smoke: <pass/fail>
```
Save the report to `~/bug-sweep-reports/<topic-slug>-<YYYY-MM-DD>.md` AND print inline. Same dual-output pattern as `/web-research`.
============================================================
=== STRICT RULES ===
============================================================
- **No silent fixes.** Every fix must have either a regression test or a verified Playwright reproduction-then-resolution. Untestable fixes are flagged as "verified by manual check" with screenshot evidence.
- **No batched commits.** One bug, one commit. Reviewers must be able to revert any individual fix.
- **No drive-by refactors.** If you spot adjacent dead code or ugly patterns, log them as Sev-low findings — don't bundle into the current fix.
- **Respect the project's CLAUDE.md** — commit size limits, pre-commit hooks, branch protection rules. If a project caps commits at N files, split accordingly.
- **Stop on system-test failure.** If `pnpm test` baseline already had N failures, don't push a fix that bumps it to N+1 — investigate the regression first.
- **Don't pile on existing dirty state.** If git status is dirty at the start, ask the user to stash. Mid-sweep, don't carry uncommitted state between findings.
============================================================
=== HEURISTICS WORTH KNOWING ===
============================================================
- "Doesn't work throughout the app" is almost always a cache/state-shape bug — a mutation that updates one queryKey but the component is rendered under N other keys.
- "Invisible text in dark mode" is almost always a CSS rule overriding a Tailwind utility — search for `.scope a { color: ... }` patterns that touch elements with `bg-` utilities.
- "Hydration mismatch" usually points to `Date.now()`, `Math.random()`, locale-sensitive formatting, or a cookie-driven SSR/CSR fork.
- "Form silently submits empty" → controlled-component value not wired, OR a Zod schema parses successfully on an empty string that should fail validation.
- "Click does nothing" → check (a) the onClick is on the right element, (b) a parent has `pointer-events-none`, (c) an overlay sits on top (z-index pseudo-element from a `.btn-shimmer::after` is a classic), (d) the disabled prop is stuck true.
- "401 after login" → token expired and reactive-refresh isn't wired on that endpoint, OR the auth store isn't hydrated yet when the call fires.
Use these as fast hypotheses, not conclusions. Verify against the code before fixing.
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!