Issue Analyze
Fetches a GitHub issue, analyzes its full scope, cross-references local project docs,
checks blocking relationships, and outputs a structured analysis with an implementation
task list. Standalone — no forced next step.
Phase 1: Resolve & Fetch
Guard: no argument
Provide an issue number or URL. Usage: /issue-analyze 42
Detect repo
bash
gh repo view --json nameWithOwner --jq '.nameWithOwner'
Outputs
. Split on
to get owner and repo name separately.
Parse argument
- A bare number:
- A full URL:
https://github.com/owner/repo/issues/42
For a URL, extract the number from the last path segment. If the URL contains a different
owner/repo than the current repo, use the URL's owner/repo for all API calls.
Fetch the issue
bash
gh issue view <N> --repo <owner>/<repo> --json number,title,body,state,labels,assignees,url
Detect current user
Guard: closed issue
Issue #<N> is closed — no implementation plan needed.
<url>
Stop. Do not output anything else.
Guard: not assigned to you
If
is non-empty and none match the current user login, print this line before
all other output:
> Note: #<N> is assigned to @<other-user> — you may be looking at someone else's work.
Then continue normally.
Fetch sub-issues
bash
gh api repos/<owner>/<repo>/issues/<N>/sub_issues 2>/dev/null
- Empty array → no sub-issues, skip
- HTTP 404 → sub-issues feature not enabled on this repo, skip silently
- Non-empty array → for each sub-issue number, fetch:
bash
gh issue view <sub-N> --repo <owner>/<repo> --json number,title,body,state
Collect all sub-issue data. Closed sub-issues are noted in the analysis as already done
but do not generate implementation tasks.
Phase 2: Local Context Search
Find the git root:
bash
git rev-parse --show-toplevel
Check whether any of these local context sources exist. If none do, skip this phase
entirely — do not mention it in output.
Find doc files
<git-root>/.claude/docs/*.md
<git-root>/.agents/docs/*.md
<git-root>/docs/superpowers/**/*.md
If no files found, skip phase.
Search for issue number
Use
to search all found files for:
- (e.g. )
- Word-boundary match for bare number (to avoid matching when looking for )
Extract and search key terms
From the issue title and body, extract:
- Capitalized component/module names (e.g. , )
- camelCase or PascalCase identifiers
- File paths mentioned (e.g.
src/components/Button.tsx
)
- Technical terms: API endpoint names, config keys, function names in backticks
Use
to search all found files for each extracted term. Collect unique
(file path, matching line) pairs. Deduplicate across term searches.
Result
If nothing found across all searches → omit the Local Context section from output.
If matches found → collect as:
{ file: string, reason: string }[]
for use in Phase 4.
Phase 3: Dependency Analysis
Query issue relationships via GraphQL. Fetch the issue's tracking relationships:
bash
gh api graphql -f query='{
repository(owner: "<owner>", name: "<repo>") {
issue(number: <N>) {
trackedInIssues(first: 5) {
nodes { number title state url }
}
}
}
}'
— parent issues or epics that track this issue. If this issue is part
of a larger epic, these are the parents.
Also try blocked-by relationships. GitHub stores these via node-ID-based relationships
(same mechanism as
/
mutations). Query them directly as
a
separate call so a failure here does not affect the
result:
bash
gh api graphql -f query='{
repository(owner: "<owner>", name: "<repo>") {
issue(number: <N>) {
blockedByIssues(first: 10) {
nodes { number title state url }
}
blockingIssues(first: 10) {
nodes { number title state url }
}
}
}
}' 2>&1 || true
— what is blocking this issue (must be resolved first).
— what this issue blocks (expects deliverables from this one).
These fields are part of GitHub's issue dependencies preview and are not available on
most repos or plans. When unavailable,
exits with code 1 and prints an
GraphQL error on
stdout (not stderr). Handle this silently:
- The above prevents the non-zero exit from surfacing as a tool error.
- If the response contains an field, or any /
Field '...' doesn't exist
message, treat it as "not available" and skip this section.
- Only parse
data.repository.issue.blockedByIssues
/ when the
response has no field.
If all queries fail or return no data, skip silently.
Relevance filter
For each dependency found:
- Open blocker (blocks this issue and is still open): always include — it constrains
what can be built. Fetch its title and state. Note what it's expected to deliver.
- Closed blocker: skip — already resolved, doesn't affect planning.
- Parent epic: include only if it adds implementation context not in the issue itself.
- No dependencies: omit the Dependencies section from output entirely.
Phase 4: Synthesize & Output
Scope Analysis — quality bar
This is the highest-value section. Write it to be directly useful for implementation
planning — not a summary of the issue text, but an interpretation of it.
A high-quality Scope Analysis:
- Explains what the issue is truly asking for (beyond restating the title)
- Identifies technical scope: what needs to be built or changed, and roughly where
- For epics: weaves sub-issues into a coherent narrative. Example: "This epic covers three
areas: authentication (#43, done), session management (#44), and token refresh (#45)."
Closed sub-issues are noted as already implemented and excluded from tasks.
- Surfaces implicit requirements not stated in the issue (e.g., "adding X implies Y also
needs to handle the new input format")
- Calls out ambiguities or decisions the implementer will face
- States what is explicitly out of scope
- When a blocker is open: explains what cannot be built until it's resolved, and what can
be built in parallel
Length: 2–5 paragraphs for a normal issue; more for a large epic (one paragraph per
sub-issue area).
Implementation Tasks — quality bar
- Each task is a concrete, actionable step (not "investigate X" — investigation is part
of Scope Analysis)
- Ordered logically: setup before implementation, implementation before tests, tests
before integration
- 3–12 tasks (3–4 is fine for small/trivial issues; 5–12 for normal scope)
- For epics: group tasks under sub-issue headings
- If a blocker is open: mark affected tasks as "blocked by #N" and list them last
Output format
Print output in this exact structure:
> Note: #<N> is assigned to @<user> — you may be looking at someone else's work.
(omit line if current user is among assignees, or if issue has no assignees)
# #<N>: <title>
## Scope Analysis
<analysis paragraphs>
## Local Context
(omit entire section if Phase 2 found nothing)
- `.claude/docs/foo.md` — <one sentence on why it's relevant to this issue>
## Dependencies
(omit entire section if no implementation-relevant open dependencies)
Depends on #<M> (open) — <what that issue provides that this one needs>.
This issue's output expected by #<K> — must deliver <Y>.
## Implementation Tasks
1. <task>
2. <task>
3. <task>
---
<issue URL>
Error Handling
| Situation | Action |
|---|
| is empty | Stop: "Provide an issue number or URL. Usage: /issue-analyze 42" |
| not authenticated | Stop: "Run first." |
| Not in a git repo + no URL given | Stop: "Provide a full GitHub URL or run from inside a git repository." |
| Issue number not found ( 404) | Stop: "Issue #<N> not found in <owner>/<repo>." |
| Sub-issues API returns 404 | Skip silently |
| No directory | Skip local context phase silently |
| GraphQL returns error or empty data | Skip dependencies section silently |
| Issue body is empty | Analyze from title only; note in Scope Analysis that the issue has no description |