Per-operation playbooks for gh issue workflows. Every write op that has author voice (--body / --title) is preview-gated per hard rule 8 — quote the draft verbatim in chat, name the send command, wait for explicit user approval, then send.
# Single issue with metadata
gh issue view <n> --repo <owner>/<repo>
# Issue + full comment thread (use this when responding — you need the context)
gh issue view <n> --repo <owner>/<repo> --comments
# Raw JSON for fields the default view omits (createdAt, labels, assignees, etc.)
gh api repos/<owner>/<repo>/issues/<n> --jq '{number,title,state,user:.user.login,labels:[.labels[].name],body}'
# List + filter
gh issue list --repo <owner>/<repo> --state open --label bug --limit 20
# Search across repos
gh search issues "is:open label:bug repo:<owner>/<repo>"
When reading an issue you intend to respond to, always pull comments too (--comments) — replying to the issue body without seeing the discussion is how stale answers happen.
Labels, assignees, milestones carry no author voice — they're metadata. Surface what you're about to do in chat, but no body preview needed.
# Add labels
gh issue edit <n> --repo <o>/<r> --add-label "bug,needs-repro"
# Remove labels
gh issue edit <n> --repo <o>/<r> --remove-label "needs-triage"
# Assign
gh issue edit <n> --repo <o>/<r> --add-assignee <user>
# Milestone
gh issue edit <n> --repo <o>/<r> --milestone "v2.11.0"
If the repo has a label scheme (bug/feat/docs/question/needs-repro/good-first-issue etc.), match it. gh label list --repo <o>/<r> to see what exists. Don't invent labels without asking.
The flow that gets it wrong without discipline. Always:
Drafted comment for issue #:
> <comment body, exactly as it would be sent> > ``` > > Command: `gh issue comment <n> --repo <o>/<r> --body "..."` > > Send? ### Sendbash gh issue comment --repo / --body "$(cat <<'EOF' EOF )"
Heredoc with single-quoted `'EOF'` so the body is literal (no shell interpolation). Markdown renders on github.com — code fences, links, `@mentions`, `#refs` all work. ### Tone defaults (project maintainer responding to a reporter) - Lead with thanks and acknowledge what was right about the report. - If a fix shipped, state the version/PR. Link the release if minor+. - If the report uncovered related issues, briefly note them — credit goes to the reporter. - Sign-off via `@mention` if directly thanking. Don't `@mention` everyone in a thread. - Don't apologise excessively or perform humility. Match the project's existing voice. - Anti-patterns: marketing fluff, emoji walls, "we'll get right on it" without a concrete plan. ## Create (preview required — title AND body) A new issue's title shows in lists and notifications; body is the substance. Preview both. ### Chat preview > Drafted issue for `<o>/<r>`: > > **Title:** `<title>` > > **Body:** > ```markdown > <body> > ``` > > **Labels:** bug, needs-repro > **Assignee:** (none) > > Command: `gh issue create --title "..." --body "..." --label "..."` > > Send? ### Sendbash gh issue create --repo / \ --title "" \ --body "$(cat <<'EOF' EOF )" \ --label "" \ --assignee ""
### Bug report template (recommended body shape)markdown
Problem
Repro
Expected vs actual
- Expected: <…>
- Actual: <…>
Environment
- Tool / version: <…>
- OS: <…>
Suggested cause / fix (optional)
<…>
## Edit title/body (preview required) Same preview discipline as create — edits are public. The original is also preserved in the issue's edit history so reviewers can see what changed.bash gh issue edit --repo / \ --title "" \ --body "$(cat <<'EOF' EOF )"
If you're only changing labels/assignees, that's mechanical — preview not required. ## Close / reopen Plain close — no preview.bash gh issue close --repo / gh issue reopen --repo /
Closing with a reason (`--reason completed|not-planned|duplicate`) — no preview, but state the reason in chat first. Closing with a parting comment — **preview the comment** (it's a public post), then:bash gh issue comment --repo / --body "..." # preview-gated gh issue close --repo /
### Closing-comment templates **Fixed:** > Fixed in v<X.Y.Z>. <one-sentence summary of the fix>. <PR link if applicable>. **Won't fix:** > Closing as <reason — out of scope / duplicate of #N / by design>. Brief why: <…>. Happy to reopen if <condition>. **Not reproducible:** > Closing as not reproducible — tried <what>, saw <what>. If you can share <specific thing>, please reopen. ## Common workflows ### Respond to a bug report and fix
- gh issue view --comments # context
- Reproduce locally; identify cause
- Draft fix on branch; PR with "Fixes #" in body
After merge, GitHub auto-closes #; post a closing comment with version + link (preview-gated)
### Triage incoming issuesgh issue list --label needs-triage # batch view
For each:
- gh issue view --comments
- Apply labels: gh issue edit --add-label … --remove-label needs-triage
- Assign milestone if scoped
- If duplicate: comment with "Duplicate of #", close with --reason duplicate
If needs more info: comment requesting specifics, add label "needs-repro"
### Convert a discussion into an actionable issuegh issue view --comments # distill the actionable scope
gh issue create --title "" --body ""
Optionally close the discussion with a link to the new issue ```
Anti-patterns
- ❌ Replying to an issue without reading its existing comments.
- ❌ Inventing labels that don't exist in the project's scheme.
- ❌ Closing with
--reason not-plannedwithout a comment — leaves the reporter guessing.- ❌
@mentioningevery previous commenter to "ping" them — they already got notified.- ❌ Promising a fix or timeline you can't commit to.
- ❌ Sending a comment without showing the draft to the user first (hard rule 8).