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, ...
Installs into .claude/skills of the current project.
Are you the author of Write?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/melodic-software-write)
---
description: "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."
argument-hint: "[--file] [--quick|--full] [--no-survey] <bug description>"
user-invocable: true
disable-model-invocation: false
shell: bash
metadata:
workflow-stage: contract
summary: Turn an informal bug description into a structured 5-field report, read-only
---
## 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) |
A pasted screenshot or image path backs Expected vs actual the way the reporter's own words do; name it under Notes so it is attached when the report is filed. A video file cannot be read, so ask for a screenshot or a few still frames instead. A repo that wants a screenshot on every rendered-output report says so in the `## Gotchas` section of its `.claude/bugs.md`.
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`](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.
## Boundary, the built-in `/bug` command
"Report a bug" can mean a defect in the person's own code or one in Claude Code itself.
- **`/bug` (built-in command, alias `/share`)**: sends a report about Claude Code, with the
conversation, to Anthropic. It is reserved for the person to run; the model does not invoke it.
- **This skill (marketplace plugin).** A five-field report for a defect in the person's code,
grounded in their repository, filed nowhere unless they ask.
**Routing.** When the defect is in Claude Code itself (the CLI, a built-in command, a bundled
skill), offer it to the person: you can run `/bug` instead of or alongside this skill. Keep this
skill for defects in the person's code. An unattended run records the offer in its output instead
of asking.
**Mutation gate.** `/bug` sends the conversation off the machine; only the person decides that.
This skill never runs `/bug` on the person's behalf.
**Availability is never assumed.** This section states what to do when the person can run
`/bug`, never that it is present in their host. The four-part records live in
[context/native-bug.md](context/native-bug.md).
## 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`](context/template.md). Read it before emitting a report: the full Markdown template, the `--file` frontmatter, and the "No bug confirmed" form
- [`context/native-bug.md`](context/native-bug.md). The basis of the `/bug` Boundary section; read it when its recheck trigger fires
- 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