Help us improve
Share bugs, ideas, or general feedback.
From bug-prospector
Mine for hidden bugs that pattern-based auditors miss. 7 analysis lenses: assumptions, state machines, boundary conditions, data lifecycle, error paths, time-dependent behavior, and platform divergence. Triggers: "prospect for bugs", "find hidden bugs", "assumption audit", "what could go wrong", "bug prospector".
npx claudepluginhub terryc21/bug-prospector --plugin bug-prospectorHow this skill is triggered โ by the user, by Claude, or both
Slash command
/bug-prospector:bug-prospectorThis skill is limited to the following tools:
The summary Claude sees in its skill listing โ used to decide when to auto-load this skill
> **Quick Ref:** Find bugs that pattern-based scanners miss by analyzing *intent*, not syntax. Output: `.agents/research/YYYY-MM-DD-bug-prospector-*.md`
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Migrates code, prompts, and API calls from Claude Sonnet 4.0/4.5 or Opus 4.1 to Opus 4.5, updating model strings on Anthropic, AWS, GCP, Azure platforms.
Breaks plans, specs, or PRDs into thin vertical-slice issues on the project issue tracker using tracer bullets. Useful for converting high-level work into grabbable implementation tickets.
Share bugs, ideas, or general feedback.
Quick Ref: Find bugs that pattern-based scanners miss by analyzing intent, not syntax. Output:
.agents/research/YYYY-MM-DD-bug-prospector-*.md
YOU MUST EXECUTE THIS WORKFLOW. Do not just describe it.
Required output: Every BUG finding MUST include Urgency, Risk, ROI, and Blast Radius ratings using the Issue Rating Table format. Do not omit these ratings.
Philosophy: Auditing tools find what's syntactically wrong. Bug Prospector finds what's semantically fragile โ the gap between "the code compiles" and "the code handles every real-world scenario."
git status --short
If uncommitted changes exist:
AskUserQuestion with questions:
[
{
"question": "You have uncommitted changes. Commit before proceeding?",
"header": "Git",
"options": [
{"label": "Commit first (Recommended)", "description": "Save current work so you can revert if this skill modifies files"},
{"label": "Continue without committing", "description": "Proceed โ I accept the risk"}
],
"multiSelect": false
}
]
If "Commit first": Ask for a commit message, stage changed files, and commit. Then proceed.
Base all findings on current source code only. Do not read or reference files in .agents/, scratch/, or prior audit reports. Ignore cached findings from auto-memory or previous sessions. Every finding must come from scanning the actual codebase as it exists now.
Before any lens runs, establish whether the codebase targets a single platform or multiple platforms. This is non-negotiable: every lens needs to know which #if os(...) blocks count as "live code" and which to skip.
AskUserQuestion with questions:
[
{
"question": "What platforms does this project ship to?",
"header": "Platform",
"options": [
{"label": "iOS only", "description": "Skip findings inside #if os(macOS) / #if os(watchOS) / #if os(tvOS) blocks"},
{"label": "macOS only", "description": "Skip findings inside #if os(iOS) / #if os(watchOS) / #if os(tvOS) blocks"},
{"label": "Universal (iOS + macOS)", "description": "All non-iOS-only and non-macOS-only blocks count; honor #if conditionals for cross-platform consistency"},
{"label": "Other / multi-platform", "description": "I'll describe the platform set"}
],
"multiSelect": false
}
]
Record the answer. Every subsequent lens MUST honor it during classification (see Step 3, rule 7).
AskUserQuestion with questions:
[
{
"question": "What should I prospect?",
"header": "Scope",
"options": [
{"label": "Specific file or feature", "description": "I'll tell you which file(s) or feature to analyze"},
{"label": "Recently changed files", "description": "Analyze files changed in the last 5 commits"},
{"label": "Full codebase", "description": "Broad scan across all source files (slower, more thorough)"}
],
"multiSelect": false
}
]
If "Specific file or feature": Ask which file(s) or feature name.
If "Recently changed files":
git diff --name-only HEAD~5 -- "*.swift" | head -30
If "Full codebase": Use Glob pattern="**/*.swift" to inventory, then prioritize:
AskUserQuestion with questions:
[
{
"question": "Which analysis lenses should I apply?",
"header": "Lenses",
"options": [
{"label": "All 7 lenses (Recommended)", "description": "Full prospecting โ assumptions, state machines, boundaries, data lifecycle, error paths, time, platform"},
{"label": "Quick 3", "description": "Assumptions + Error Paths + Boundaries โ highest bug yield"},
{"label": "Let me pick", "description": "I'll choose specific lenses"}
],
"multiSelect": false
}
]
If "Let me pick":
AskUserQuestion with questions:
[
{
"question": "Select the lenses to apply:",
"header": "Lenses",
"options": [
{"label": "1. Assumption Audit", "description": "List every implicit assumption and what breaks when violated"},
{"label": "2. State Machine Analysis", "description": "Find unreachable states, simultaneous states, interrupted transitions"},
{"label": "3. Boundary Conditions", "description": "Zero, one, max values; empty strings; nil chains; off-by-one"},
{"label": "4. Data Lifecycle Tracing", "description": "Follow data from creation to deletion โ find gaps"}
],
"multiSelect": true
},
{
"question": "Additional lenses:",
"header": "More",
"options": [
{"label": "5. Error Path Exerciser", "description": "What happens when every try/catch and optional chain fails?"},
{"label": "6. Time-Dependent Bugs", "description": "Timezone, locale, rapid actions, slow network, first launch after weeks"},
{"label": "7. Platform Divergence", "description": "Hardware assumptions, OS version gaps, device-specific behavior"}
],
"multiSelect": true
}
]
For each file in scope, apply the selected lenses. Read the full file before analysis โ never analyze from grep matches alone.
Goal: Surface every implicit assumption the code makes, then evaluate what happens when each is violated.
Process:
Search accelerators (grep for common assumption patterns):
Grep pattern="\.first!" glob="**/*.swift"
Grep pattern="\.last!" glob="**/*.swift"
Grep pattern="\[0\]" glob="**/*.swift"
Grep pattern="\.removeFirst\(\)" glob="**/*.swift"
Grep pattern="as!" glob="**/*.swift"
Goal: Find states that become unreachable, states that can be simultaneously active, and transitions that leave the app in an inconsistent state.
Process:
@State, @Published, @Observable properties that represent user-facing stateSearch accelerators:
Grep pattern="@State.*=.*true" glob="**/*.swift"
Grep pattern="@Published.*=.*true" glob="**/*.swift"
Grep pattern="isLoading|isProcessing|isSaving|isAnalyzing" glob="**/*.swift"
Grep pattern="showingError|showingAlert|showingSheet" glob="**/*.swift"
Goal: Find off-by-one errors, empty collection crashes, and edge case failures.
Process:
if, guard, switch), evaluate:
removeFirst() / removeLast() have an emptiness guard?prefix() / suffix() handle count > array.count?Search accelerators:
Grep pattern="\.remove(First|Last)\(\)" glob="**/*.swift"
Grep pattern="\.\[.*\]" glob="**/*.swift"
Grep pattern="\.prefix\(|\.suffix\(" glob="**/*.swift"
Grep pattern="\.split\(|\.components\(" glob="**/*.swift"
Grep pattern="Int\.max|\.count\s*-\s*1" glob="**/*.swift"
Goal: Follow data from creation to deletion and find gaps where data can be lost, duplicated, or become stale.
Process:
Search accelerators:
Grep pattern="context\.insert\(" glob="**/*.swift"
Grep pattern="context\.delete\(" glob="**/*.swift"
Grep pattern="context\.save\(" glob="**/*.swift"
Grep pattern="\.deleteRule\s*=" glob="**/*.swift"
Grep pattern="@Query" glob="**/*.swift"
Goal: For every try/catch, async/await, and optional chain โ determine what happens when the error path is taken.
Process:
try / try? / try!await (can throw via Task cancellation)?.)guard let ... else { return }try? that converts a meaningful error to nil (information loss)catch blocks that log but don't update UI stateisLoading = false in error paths (loading state trap)guard let with bare return that silently aborts a user-initiated actionTask {} without error handling (errors vanish)Search accelerators:
Grep pattern="try\?" glob="**/*.swift"
Grep pattern="catch\s*\{" glob="**/*.swift" -A 3
Grep pattern="guard let.*else\s*\{\s*return\s*\}" glob="**/*.swift"
Grep pattern="Task\s*\{" glob="**/*.swift" -A 5
Goal: Find code that behaves differently based on time, speed, or duration.
Process:
< instead of Calendar methodsSearch accelerators:
Grep pattern="DateFormatter\(\)" glob="**/*.swift"
Grep pattern="Date\(\)" glob="**/*.swift"
Grep pattern="timeIntervalSince" glob="**/*.swift"
Grep pattern="URLSession.*dataTask\|URLSession.*data\(" glob="**/*.swift"
Grep pattern="\.debounce\|\.throttle" glob="**/*.swift"
Goal: Find code that assumes specific hardware, OS version, or device capabilities.
Process:
#available checks where the else branch is incomplete or empty#if os(iOS) with logic not mirrored in #else (macOS)Search accelerators:
Grep pattern="#if os\(" glob="**/*.swift"
Grep pattern="#available\(" glob="**/*.swift"
Grep pattern="UIScreen\.main" glob="**/*.swift"
Grep pattern="UIDevice\.current" glob="**/*.swift"
Grep pattern="ProcessInfo.*physicalMemory\|ProcessInfo.*processorCount" glob="**/*.swift"
Grep pattern="CIContext\|MTLDevice\|MTLCreateSystemDefaultDevice" glob="**/*.swift"
Before classifying ANY finding:
#if os(...) block, even if that means widening the window beyond 30 lines.#if os(X) block where X is NOT in the project's declared platform set, the finding is OK (excluded by build), not BUG. Example: on an iOS-only project, code inside #if os(macOS) is dead from the project's perspective and must not be flagged. On a Universal project, code inside #if os(iOS) is live for iOS but excluded for macOS โ flag the finding only if the bug condition can occur on a platform that DOES include the block.#if conditional from the project's platform setClassification rules:
#if os(...) block excluded from the project's platform set (Step 0)Before rendering the report, check terminal width:
tput cols
Compact view โ your terminal is [N] columns wide (160+ needed for full table). The complete Issue Rating Table with all 8 columns has been written to
.agents/research/YYYY-MM-DD-bug-prospector-<scope>.md. Open that file or widen your terminal to 160+ columns to view it as a single table.
Display the summary and findings inline, then write to .agents/research/YYYY-MM-DD-bug-prospector-<scope>.md.
The report file always uses the full 8-column table regardless of terminal width.
# Bug Prospector Report: [Scope Description]
**Date:** YYYY-MM-DD
**Scope:** [Files/features analyzed]
**Lenses Applied:** [List of lenses used]
**Files Analyzed:** N
## Summary
| Status | Count |
|--------|-------|
| Bugs Found | X |
| Fragile Code | Y |
| OK (Already Guarded) | Z |
| Needs Review | W |
## Issue Rating Table
All BUG and FRAGILE findings rated and sorted by Urgency then ROI:
Full table (160+ columns) โ used inline AND in report file:
| # | Finding | Lens | Urgency | Risk: Fix | Risk: No Fix | ROI | Blast Radius | Fix Effort |
|---|---|---|---|---|---|---|---|---|
| 1 | File.swift:45 โ array accessed without bounds check | Boundary | ๐ด Critical | โช Low | ๐ด Critical | ๐ Excellent | โช 1 file | Trivial |
| 2 | Manager.swift:89 โ isLoading never reset on error | Error Path | ๐ก High | โช Low | ๐ก High | ๐ Excellent | โช 1 file | Trivial |
| 3 | ViewModel.swift:200 โ DateFormatter without timezone | Time | ๐ข Medium | โช Low | ๐ข Medium | ๐ข Good | ๐ข 3 files | Small |
Compact table (under 160 columns) โ used inline only:
| # | Finding | Urgency | Fix Effort |
|---|---|---|---|
| 1 | File.swift:45 โ array accessed without bounds check | ๐ด Critical | Trivial |
| 2 | Manager.swift:89 โ isLoading never reset on error | ๐ก High | Trivial |
| 3 | ViewModel.swift:200 โ DateFormatter without timezone | ๐ข Medium | Small |
The compact table keeps the two most actionable columns (Urgency + Fix Effort). Full ratings are in the report file.
Use the Issue Rating scale:
- **Urgency:** ๐ด CRITICAL (crash/data loss) ยท ๐ก HIGH (incorrect behavior) ยท ๐ข MEDIUM (degraded UX) ยท โช LOW (cosmetic/minor)
- **Risk: Fix:** Risk of the fix introducing regressions (โช Low for isolated changes, ๐ก High for shared code paths)
- **Risk: No Fix:** User-facing consequence if left unfixed
- **ROI:** ๐ Excellent ยท ๐ข Good ยท ๐ก Marginal ยท ๐ด Poor
- **Blast Radius:** Number of files the fix touches (e.g., "โช 1 file", "๐ข 3 files", "๐ก 12 files"). Count by grepping for callers/references before rating.
- **Fix Effort:** Trivial / Small / Medium / Large
Lens: [Which lens found this] Assumption: [What the code assumes] Violation scenario: [How a real user triggers this] Consequence: [What happens โ crash, data loss, wrong UI, etc.]
Current code:
// problematic code
Suggested fix:
// corrected code
...
Lens: [Which lens found this] Current behavior: [What happens now] Breaking scenario: [What foreseeable change would break this] Recommendation: [How to harden it]
These were flagged by search but are correctly handled:
These findings require domain knowledge to classify:
bug-prospector finds bug patterns. After you fix any BUG finding above, run bug-echo on the fix to find sibling instances of the same pattern elsewhere in the codebase:
/bug-echo
bug-echo infers the anti-pattern from your fix's diff, validates it against the pre-fix file, then scans for matches. Bugs that haven't fired yet but share the same shape are the highest-ROI catches in any audit cycle. Run bug-prospector to find the first instance; run bug-echo to close the bug class.
---
## Step 5: Follow-up
AskUserQuestion with questions: [ { "question": "How would you like to proceed?", "header": "Next", "options": [ {"label": "Fix all bugs now", "description": "Walk through each BUG finding and apply fixes (phase-by-phase)"}, {"label": "Fix selected bugs", "description": "I'll choose which ones to fix"}, {"label": "Create implementation plan", "description": "Generate a phased plan from the findings"}, {"label": "Report is sufficient", "description": "I'll handle fixes manually"} ], "multiSelect": false } ]
If creating plan: Group findings by file proximity and dependency, order by urgency, output as a numbered plan.
### Fix Workflow: "Fix all bugs now"
Group bugs into phases by file proximity and dependency (as in the report's Implementation Plan). Before each phase, prompt with a **phase gate** โ one question, always includes opt-out:
AskUserQuestion with questions: [ { "question": "Phase N: [Phase name] ([count] fixes โ [key files]). Proceed?", "header": "Phase N", "options": [ {"label": "Proceed (Recommended)", "description": "Implement this phase now"}, {"label": "Proceed โ skip remaining phase gates", "description": "Batch mode: implement all remaining phases without prompting"}, {"label": "Let's chat about this phase", "description": "Discuss before deciding"}, {"label": "Stop here", "description": "Skip remaining phases"} ], "multiSelect": false } ]
**Every phase gets this same prompt** (including the opt-out) until the user either completes all phases or opts out.
**Rules:**
- If user chooses "skip remaining phase gates": execute all remaining phases without prompting
- If user chooses "Let's chat": wait for user input, answer questions, then re-prompt the same phase gate
- If user chooses "Stop here": stop fixing and report what was completed
- Always build both platforms after each phase to verify
### Fix Workflow: "Fix selected bugs"
Present the bug list for selection:
AskUserQuestion with questions: [ { "question": "Which bugs should I fix? (Reference the Issue Rating Table above)", "header": "Select", "options": [ {"label": "Bug 1 โ [brief description]", "description": "[Urgency] [Fix Effort]"}, {"label": "Bug 2 โ [brief description]", "description": "[Urgency] [Fix Effort]"}, {"label": "Bug 3 โ [brief description]", "description": "[Urgency] [Fix Effort]"} ], "multiSelect": true } ]
After selection, one confirmation prompt with opt-out:
AskUserQuestion with questions: [ { "question": "Fix [N] selected bugs: [brief list]. Proceed?", "header": "Confirm", "options": [ {"label": "Proceed (Recommended)", "description": "Fix all selected bugs now"}, {"label": "Let's chat first", "description": "Discuss specific bugs before fixing"}, {"label": "Go back", "description": "Re-select bugs"} ], "multiSelect": false } ]
Then fix all selected bugs without per-bug prompting โ the selection itself was the decision.
**If user chooses "Let's chat":** Answer questions, then re-prompt the confirmation.
---
## Lens Selection Guide
| Situation | Recommended Lenses |
|-----------|--------------------|
| Pre-release audit | All 7 |
| After adding a new feature | 1 (Assumptions) + 2 (State) + 5 (Errors) |
| After a crash report | 3 (Boundaries) + 5 (Errors) + 7 (Platform) |
| Debugging intermittent failures | 2 (State) + 6 (Time) |
| New platform support (macOS/iPad) | 7 (Platform) + 3 (Boundaries) |
| Data model changes | 4 (Data Lifecycle) + 1 (Assumptions) |
| Performance investigation | 3 (Boundaries) + 6 (Time) |
---
## What This Finds vs. What Auditors Find
| Auditors Find | Bug Prospector Finds |
|---------------|---------------------|
| Missing `@MainActor` | State machine deadlocks |
| Force unwraps | Assumptions that hold today but break tomorrow |
| Retain cycles | Data that's created but never cleaned up |
| Missing `try?` conversion | Error paths that leave UI in loading state |
| Deprecated API usage | Code that works on Apple Silicon but fails on Intel |
| Missing accessibility labels | Rapid-tap scenarios that create duplicate data |
---
## Troubleshooting
| Problem | Solution |
|---------|----------|
| Too many findings | Narrow scope to specific files or use "Quick 3" lenses |
| All findings are theoretical | Increase the realism threshold โ only flag scenarios a real user could trigger |
| Overlapping with auditor findings | Focus on *why* not *what* โ auditors find the pattern, prospector finds the consequence |
| File too complex to analyze | Split analysis by MARK sections or extract to Agent subprocesses |
| Can't determine if guarded | Classify as REVIEW, not BUG โ let the human decide |