github-issues
Purpose
Standardize GitHub issue creation and management across any project. Ensure every issue has a clear structure, proper labels, and actionable content. Guide the user through creating well-formed issues and applying GitHub's default label taxonomy consistently.
Prerequisites
Before any operation, verify the environment:
- Detect repository context:
git remote get-url origin
Parse owner and repo from the remote URL. Supports both formats:
- SSH:
git@github.com:owner/repo.git - HTTPS:
https://github.com/owner/repo.git
Store the result as REPO="owner/repo". If not in a git repository or no remote is configured, ask the user to specify owner/repo manually and store it as REPO.
Perform this parsing step before running any gh issue or gh label commands. When constructing gh issue or gh label commands, include -R "$REPO" so they always target the correct repository, regardless of whether the user is inside a local clone.
When to use
- Creating a new GitHub issue (with a duplicate check first — updating an existing issue when one already covers the request)
- Viewing issue details
- Closing issues with explanation
- Commenting on existing issues
- Triaging or labeling existing issues
- Listing open issues with their labels
Detailed references
Load these on demand — don't read them up front:
- references/issue-templates.md — title rules, the enhancement and bug body templates, the body-section rules, and type detection from title/context. Read before writing or rewriting an issue body.
- references/labels.md — the type/status label taxonomy, how to validate a label exists before applying it, and the
--add-labelvs--labelrule. Read before applying or changing labels.
Operations
Based on $ARGUMENTS, perform ONE of these operations:
create <title>
- Determine the issue type from the title and context — see the type-detection indicators in references/issue-templates.md.
- Check for an existing issue covering the same thing — before creating anything. Filing a second issue for a problem that already has one fragments the discussion and wastes triage effort, so always search first. Pull the most distinctive keywords from the title (drop generic verbs like "add"/"fix" and stop-words) and search across both open and closed issues:
gh issue list -R "$REPO" --search "<keywords>" --state all --json number,title,state,url,updatedAt --limit 20
Read the candidates and judge whether any describes the same underlying request or bug — not just a keyword overlap. Two issues that touch the same file but ask for different things are not duplicates; two issues worded differently that would be resolved by the same change are. When unsure, treat the closest candidate as a possible match and let the user decide rather than guessing.
- No real match: proceed to step 3 and create a new issue.
- A matching OPEN issue exists: do not create a duplicate. Open it (
gh issue view <number> -R "$REPO") and compare its body against the new details. If the request brings genuinely new information (extra repro steps, an affected file the issue is missing, a clearer proposed solution, new context), update the existing issue instead — see step 6b. If the existing issue already covers everything, tell the user it's already filed (with the link) and stop without changing anything. - A matching CLOSED issue exists: surface it to the user with its link and state. Ask whether to reopen it (if the problem has resurfaced), add the new context as a comment, or file a fresh issue (e.g. the old one was a different root cause). Don't reopen silently.
- Check which labels are available in the target repository and handle any missing type label — follow references/labels.md.
- Select the matching body template (enhancement or bug) from references/issue-templates.md and pre-fill the "Summary" section from context. If the user has provided enough detail, fill all applicable sections. Otherwise, ask for the missing required sections — especially "Proposed Solution" with specific file paths and implementation approach.
- Suggest appropriate labels based on the type detection and available labels discovered in step 3.
- Present the full issue (title, body, labels) for user review before creating. Wait for confirmation or edits.
- Create the issue:
gh issue create -R "$REPO" --title "<title>" --label "<label1>,<label2>" --body "$(cat <<'EOF'
<body content>
EOF
)"
- Output the issue URL.
Step 6b: Updating an existing issue instead of creating
Reached only when step 2 found a matching open issue that's missing information the new request provides. The goal is to enrich the existing issue without clobbering what's already there — its body may contain edits, discussion references, or detail the user added by hand.
- Decide what genuinely needs to change. For a small addition (an extra repro step, a link, a newly identified cause), a comment is the least destructive and keeps an audit trail:
gh issue comment <number> -R "$REPO" --body "$(cat <<'EOF'
<the new information, e.g. additional repro steps or an affected file>
EOF
)"
- If the issue's structured body is materially incomplete (missing the "Proposed Solution", wrong/empty "Summary") and rewriting it makes the issue clearer, edit the body — but show the user the proposed new body first and merge with the existing content rather than replacing it wholesale:
gh issue edit <number> -R "$REPO" --body "$(cat <<'EOF'
<merged body — existing content plus the new details>
EOF
)"
- If the new context changes the categorization (e.g. it turns out to be a bug, not just an enhancement), add the appropriate label with
--add-label(never--label, which would wipe existing labels). - Output the issue URL and a one-line note of what you changed.
view <number>
- Display the issue details:
gh issue view <number> -R "$REPO"
- If the user wants to see discussion, show comments:
gh issue view <number> -R "$REPO" --comments
close <number> [reason]
- Fetch the issue to verify state:
gh issue view <number> -R "$REPO" --json title,labels,state
- If the issue is already closed, inform the user and stop.
- If closing as duplicate, require the user to specify the original issue number. Verify the original issue exists, then validate the
duplicatelabel and close:
gh issue view <original> -R "$REPO" --json number,title,state
gh label list -R "$REPO" --json name --jq '.[].name' | grep -q '^duplicate$'
gh issue comment <number> -R "$REPO" --body "Closing as duplicate of #<original>."
gh issue close <number> -R "$REPO" --reason "not planned"
gh issue edit <number> -R "$REPO" --add-label "duplicate"
If the duplicate label does not exist, ask the user whether to create it or skip labeling — the comment and close are sufficient on their own.
Note: gh issue close --reason only accepts completed or not planned. For duplicates, use not planned — the duplicate label and comment provide the actual context.
- For other closures, add a comment explaining why, then close:
gh issue comment <number> -R "$REPO" --body "<reason>"
gh issue close <number> -R "$REPO"
- If the user provides a reason in the arguments, use it. Otherwise, ask for a reason before closing — never close silently.
comment <number> <text>
- Verify the issue exists:
gh issue view <number> -R "$REPO" --json number,title,state
- Add the comment:
gh issue comment <number> -R "$REPO" --body "<text>"
- Confirm the comment was posted with a link.
assign <number> <user> [--remove]
- Verify the issue exists:
gh issue view <number> -R "$REPO" --json number,title,state,assignees
- If
--removeis not provided, assign the user:
gh issue edit <number> -R "$REPO" --add-assignee "<user>"
If --remove is provided, unassign:
gh issue edit <number> -R "$REPO" --remove-assignee "<user>"
- If
<user>is@meorme, resolve to the authenticated user:
gh api user --jq '.login'
- Confirm the assignment change.
label <number> <label> [--remove]
- Fetch available labels to validate the requested label exists:
gh label list -R "$REPO" --json name --jq '.[].name'
- Add or remove the label with
--add-label/--remove-label— see references/labels.md for the exact commands and why--labelmust never be used ongh issue edit. - If the label does not exist, warn the user and list available labels. Suggest the closest match if possible.
triage
- List all open issues with their labels:
gh issue list -R "$REPO" --state open --json number,title,body,labels,createdAt --limit 100
- Filter for issues where
labelsis empty. - If no unlabeled issues are found, inform the user ("All open issues are labeled") and stop.
- Analyze the title and body of each unlabeled issue to suggest a label, using the type-detection indicators in references/issue-templates.md and the taxonomy in references/labels.md.
- Present a summary table with suggested labels:
# Title Suggested Label
37 Add database corruption recovery enhancement
33 Fix error state on successful ops bug
30 Update API documentation documentation
- Ask the user to confirm, modify, or skip each suggestion before applying.
- Apply confirmed labels:
gh issue edit <number> -R "$REPO" --add-label "<label>"
list (default when no arguments given)
- List open issues:
gh issue list -R "$REPO" --state open --json number,title,labels,assignees --limit 50
If --label <label> is specified in the arguments, add --label "<label>" to filter.
- Display in a readable table format:
# Title Labels Assignee
12 Add dark mode toggle enhancement @user
11 App crashes on startup with empty DB bug, good first —
10 Update README with build instructions documentation @user
- Show summary: total count and label distribution.
- If there are more issues than the displayed limit, inform the user and suggest using
--labelto filter or increasing the limit.
Error handling
| Scenario | Detection | Action |
|---|---|---|
gh not installed |
command -v gh fails |
Direct user to https://cli.github.com |
| Not in a git repo | git rev-parse --show-toplevel fails |
Ask user for owner/repo manually |
| No remote configured | git remote get-url origin fails |
Ask user for owner/repo manually |
| Issue not found | gh issue view exits non-zero |
Verify the issue number and repository |
| Label not found | Label not in gh label list output |
Show available labels, suggest closest match |
| Permission denied | gh returns 403/404 |
Check repo access and authentication scopes |
| Rate limited | gh returns 429 |
Wait and retry, or inform the user |
Constraints
These rules keep issue quality high and prevent accidental damage to existing labels and issues:
- Search for an existing issue before creating a new one, and update that issue rather than filing a duplicate — duplicate issues split discussion and double the triage burden
- Every issue needs at least one type label — labels are the primary categorization mechanism and enable filtering and triage
- Present the full issue (title, body, labels) for user review before creating — the user owns the final content
- Add a comment explaining why before closing any issue — future readers need to understand the decision
- Link the original issue before closing as duplicate — this preserves the relationship in GitHub's UI
- Use
--add-label(not--label) when editing issues —--labelreplaces all existing labels, which can silently remove important categorization - Do not create new labels without user confirmation — labels are shared across the entire repository and affect everyone's workflow
- Include specific file paths and code references in issue bodies when context is available — actionable issues with concrete pointers get resolved faster