melodic-software

claude-code-plugins

"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."

melodic-software 28 5 Updated 3w ago

Resources

2
GitHub

Install

npx skillscat add melodic-software/claude-code-plugins/plugins-bugs-skills-write

Install via the SkillsCat registry.

SKILL.md

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/Grep for 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:

  1. If the consumer configured output_dir, write to ${user_config.output_dir}.
  2. 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.
  3. 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-items plugin 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. Without work-items, in a GitHub repository with the gh CLI: --body-file needs a report file on disk (in --file mode 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). Run gh issue create --type Bug --body-file <report> and let gh prompt 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 run gh 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 Bug sets 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 a type: bug label 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. --file persists 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. "priceFor returns wrong total when discountPercent is 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 ## Gotchas concatenate after these bullets. The pre-computed Consumer gotchas block is the cascade ## Gotchas from .claude/bugs.md layers (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 --file frontmatter, 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