"Produce a structured 5-field bug report (title, steps to reproduce, expected vs actual, severity with justification, suggested fix location) from an informal description. Read-only, never modifies code, never opens PRs, never files issues by default. Use when the user names a defect they observed ('there is a bug in <X>', 'expected X got Y', 'I am seeing <error> in <file>') or asks for one written up ('report a bug', 'file a bug', 'write this up as a bug'). Skip when: deep investigation is needed, a fix is already in progress, or the request is a feature request (missing capability) rather than a defect. Emits Markdown to stdout by default; with --file, persists a report file and can hand off to a work-item tracker for filing."
Resources
2Install
npx skillscat add melodic-software/claude-code-plugins/plugins-bugs-skills-write Install via the SkillsCat registry.
Repository context. Gather first
Collect these with individual Bash calls, one command per call, never combined into a single
invocation:
- Current branch,
git branch --show-current - Working tree (empty = clean),
git status --porcelain | head -5
The pipe is the bound and belongs in the command. A read-time cap ("read only the first 5 entries")
bounds nothing: the Bash tool returns the command's complete output into context before there is
anything to decide about.
Treat a failure (not a repository, git unavailable) as an unknown value and carry on. Keep these as
separate body Bash calls rather than pre-compute lines: the harness runs a skill's whole pre-compute
block as one shell invocation, and a worktree-isolated session refuses a compound command that
contains git.
Pre-computed context
Consumer gotchas:
!bash "${CLAUDE_PLUGIN_ROOT}/scripts/concat-gotchas.sh"
Variables
Arguments: $ARGUMENTS
Purpose
/bugs:write produces a five-field structured report so the next session (or a human) can act without re-asking on vague repro, missing severity, no fix location, or hand-wavy expected/actual. Read-only. It captures, it does not fix, and it does not file (unless you explicitly ask).
This is the bug-intake stage. It sits upstream of filing the report into a work-item tracker, and it is independent of any downstream fix workflow, when the report itself is the deliverable (a Slack message, a PR comment, a verbal handoff), that is all this skill needs to do.
Five fields: title, steps to reproduce, expected vs actual, severity (with justification), and suggested fix location. A (unknown — needs reporter confirmation) placeholder is used for any field that cannot be backed from the source, rather than inventing one.
A sharp report captured up front saves the next session from re-asking. Unrepresented reproduction steps cost far more to recover later than to capture now.
Skip conditions, when not to invoke
- Investigation needed, the bug needs reproduce-first diagnosis, not just capture. If your project provides a debugging or investigation skill, hand off to it; otherwise scope the investigation separately from this read-only capture.
- Fix already in progress. This skill only captures; it does not complete a fix.
- Feature request (a missing capability, not a defect). This is product intent, not a bug. If your project provides a PRD or requirements-intake skill, route there; otherwise capture it as a feature request, not a five-field bug report.
- Generic chore (a TODO, docs gap, or non-defect task). File it directly in your tracker; it does not need the five-field bug shape.
If it is ambiguous, surface the question once and let the user pick.
The bugs process
Step 1. Skip-condition check
If the request matches a skip condition, stop and recommend the right path instead of producing a report: a feature request, an investigation task, and a generic chore each have a better home (above).
Step 2. Survey before you write
A fast breadth pass before deep work. In parallel:
Glob/Grepfor the symbol named in the description (function, class, file, error message)- If more than one symbol matches, the description is ambiguous. Ask which one
git log --oneline -10 -- <suspected-file>if a file is named, a recent change may be the cause- Check the output directory (see Step 4) for prior bug reports on the same area, to avoid duplicates
Skip the survey when --no-survey was passed (unconditionally, the flag means "trust the description"), or when --quick was passed AND the description names a single unambiguous symbol.
Step 3. Targeted Q&A
Ask one question at a time. Use AskUserQuestion when 2-4 named options exist (e.g. "which flush()? There are 3 in the repo: …"); use prose for open-ended questions.
Question priority order. Only ask if the field cannot be backed from context:
| Field | Highest-value question |
|---|---|
| Steps to reproduce | "Walk me through the smallest sequence that triggers it." |
| Expected vs actual | "What did you expect? What did you see instead?" |
| Severity | "Who or what is blocked? Production users / dev workflow / cosmetic?" |
| Fix location | (do not ask. Derive from the survey; if unknown, mark (unknown — needs reporter confirmation)) |
| Title | (do not ask. Derive from symptom + symbol) |
Stop conditions: every required field has a backed answer OR an explicit (unknown — needs reporter confirmation) placeholder. Modifiers:
| Flag | Effect |
|---|---|
| (none) | Survey + targeted Q&A; default to --full discipline if the symbol is ambiguous |
--quick |
Skip the survey if the symbol is unambiguous; max 1 round of Q&A |
--full |
Always survey; up to 3 rounds of Q&A |
--no-survey |
Trust the description; only ask when a field would otherwise be invented |
--file |
Write the report to a file (see Step 4) instead of only stdout; then offer to file it in a tracker |
Step 4. Emit the report
Default: emit Markdown to stdout (read-only). Follow the 5-field template. See `context/template.md` for the full structure.
A person reads the report, so each field opens with its finding and carries no filler: invoke /writing:be-concise via the Skill tool when the writing plugin is installed; otherwise apply that discipline inline. The five fields, their order, and the template's shape are unchanged, and no repro step, severity justification, or unknown-field placeholder is dropped to shorten it.
--file mode: write the report to a file with frontmatter type: bug-report. Resolve the output directory in this precedence, and always tell the user the final path:
- If the consumer configured
output_dir, write to${user_config.output_dir}. - Otherwise, write to
${CLAUDE_PLUGIN_DATA}/bug-reports/<project-slug>/, where<project-slug>is the kebab-cased basename of the project root (${CLAUDE_PROJECT_DIR}, or the git toplevel when unset). The plugin data directory is per-plugin, not per-project. Without the slug, Step 2's duplicate scan would match another repository's report on the same symbol. - If neither resolves, fall back to
${CLAUDE_PROJECT_DIR}/.bug-reports/and state clearly where the file landed.
Filename: derive a slug from the title (kebab-case, ~40-char cap), prefix an ISO basic UTC timestamp with no colons (Windows-safe), e.g. 20260502T143000Z-bug-pricefor-discount-math.md. If the title cannot yet produce a slug, fall back to the timestamp alone.
Step 5. Hand off
After emitting the report, recommend the next step; do not invoke it yourself:
- File it as a work item. When the
work-itemsplugin is installed and a tracker binding resolves, hand the report to/work-items:track add(pass the report summary via--context); it owns dedupe, the body template, the issue type, and the argv-safe write, so do not call the tracker directly beside it. Map the severity onto the tracker's priority labels if it has them. Withoutwork-items, in a GitHub repository with theghCLI:--body-fileneeds a report file on disk (in--filemode use the emitted report path; in stdout mode save the report first, offering to re-run the write step or Write it to a temp file). Rungh issue create --type Bug --body-file <report>and letghprompt for the title interactively. If filing non-interactively, never interpolate the reporter's title text into the command string: write the title to a file first, then rungh issue create --type Bug --title "$(cat <title-file>)" --body-file <report>, because the command-substitution result is a quoted argument value and is not re-parsed, so backticks or$( )inside the reporter's text cannot execute.--type Bugsets the native GitHub Issue Type (an org-repo feature, the same one the work-items lanes set); on a repo without native Issue Types, drop the flag and add atype: buglabel instead when the repo defines one. If a work-item tracker MCP tool is available and neither path applies, use it. - A fix is next. If your project provides an investigation or implementation workflow, route there; otherwise scope the fix separately.
- The report is the deliverable (Slack, PR comment, hand-off). Done; copy/paste the stdout.
Severity rubric
Severity is low / medium / high / critical with a one-line justification. It is not "how upset is the reporter". It is blast radius × blocking factor × data-integrity impact:
| Severity | Use when |
|---|---|
critical |
Production data corruption, security breach, full-app outage, money-affecting math bug |
high |
Feature broken for a large share of users, blocking dependent work, affects a core flow |
medium |
Feature broken for a narrow case, has a workaround, edge-case data issue |
low |
Cosmetic, documentation, dev-experience, or tooling drift |
If a tracker uses priority labels (e.g. p0/p1/p2/p3 or priority:high), map this rubric onto them when filing. If severity cannot be calibrated from context, ask one question rather than inventing it.
What this skill does NOT do
- Does not write code or open a PR. It produces a report only.
- Does not invent reproduction steps. If a step cannot be backed from the source, a test, or the reporter's description, it is marked
(unknown — needs reporter confirmation)and surfaced under Notes. Flag a gap rather than fabricate one. - Does not file the report by default. The user reads the report and decides.
--filepersists it; filing into a tracker is an explicit hand-off in Step 5. - Does not investigate the bug. Step 2's survey is a fast grounding pass, not deep work. A fix that needs real investigation should be scoped separately.
- Does not auto-fix typos in the user's description. "There is a bug in
flusH()" may be intentional in some languages. Ask one question.
Gotchas
- Repro steps must be backed. If you cannot derive them from the user's description, the source, or a test, mark
(unknown — needs reporter confirmation). Inventing repro is worse than admitting a gap. - Severity is blast radius, not frustration. Use the rubric; justify in one sentence.
- Suggested fix location is not a patch. Name the file path and function/class. No code, no diff, no "just change line X to Y". The fixer decides the patch.
- Title in present tense. "
priceForreturns wrong total whendiscountPercentis non-zero", not "fixed pricing bug" or "pricing was broken". - When there is no bug, do not emit a report. If the survey and Q&A reveal the behavior is correct, emit the short "No bug confirmed" summary instead (see
context/template.md). - Consumer
## Gotchasconcatenate after these bullets. The pre-computed Consumer gotchas block is the cascade## Gotchasfrom.claude/bugs.mdlayers (user-global, team, local overlay) in layer order. Treat those lines as additional gotchas for this invocation. Missing layers are absent, not an error. Generalizable lines belong in this shipped skill via an issue, not in the consumer file.
Cross-references
- `context/template.md`. Read it before emitting a report: the full Markdown template, the
--filefrontmatter, and the "No bug confirmed" form - Consumer conventions (naming, areas, priority labels, tracker choice) come from the consuming project's own
CLAUDE.md/ rules. This skill reads them rather than imposing its own