work-issue
Work a GitHub issue end-to-end: move to In Progress, create branch/PR if needed, check out branch, implement, summarize. Use when: picking up an issue, starting implementation from an issue number, working a GitHub issue, resuming work on a PR.
Install
mkdir -p .claude/skills/work-issue && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15076" && unzip -o skill.zip -d .claude/skills/work-issue && rm skill.zipInstalls to .claude/skills/work-issue
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Work a GitHub issue end-to-end: move to In Progress, create branch/PR if needed, check out branch, implement, summarize. Use when: picking up an issue, starting implementation from an issue number, working a GitHub issue, resuming work on a PR.About this skill
Work Issue
Pick up a GitHub issue by number, ensure it is In Progress, ensure a branch and PR exist, set up an isolated worktree, understand the current state of work, implement the requirements, and summarize the completed work for review.
Worktrees allow multiple issues to be worked concurrently without switching branches or stashing changes.
Prerequisites
ghCLI (identity set per operation — see below)- The workspace must be a git repository with a GitHub remote
Identity (local agents only): This skill is executed by the implementer agent. If you are running locally with the gh CLI, set up before Step 2:
. .github/skills/github-ops/scripts/Set-GitHubIdentity.ps1 -Identity implementer
Cloud-hosted agents (e.g., GitHub Copilot coding agent) should skip identity setup and use their built-in GitHub access.
Step 0: Validate Issue Number
An issue number must be provided by the user. If no issue number was provided when this skill was invoked:
- Ask the user for the issue number.
- Do NOT assume, guess, or proceed without it.
- Wait for an explicit issue number before continuing.
Step 1: Detect Repository
Determine the target GitHub owner/repo:
- Run
git remote get-url originin the workspace root. - Extract the
owner/reposlug from the URL (handles bothhttps://github.com/owner/repo.gitand[email protected]:owner/repo.gitformats). - Use this value for all GitHub API calls throughout the skill.
If the remote is not a GitHub URL, inform the user and stop.
Step 2: Read the Issue
gh issue view <issue-number> --json title,body,labels,assignees,state,milestone
Parse and retain:
- Issue title and body — these define what needs to be done
- Labels — may indicate issue type (bug, enhancement,
spec-{NNN}, etc.) - Existing linked PRs — determines whether Step 4 creates or reuses
Step 2b: Check Prerequisites
Parse the issue body for a ## Prerequisites section. Look for lines matching Blocked by #<number> or similar patterns.
For each referenced blocking issue:
- Run
gh issue view <blocking-number> --json state --jq '.state'to check if it is open or closed. - Collect any that are still open.
If any blocking issues are open, warn the user:
⚠️ Issue #<number> has open prerequisites:
- #<blocking-number> — <blocking issue title> (open)
- #<blocking-number> — <blocking issue title> (open)
These issues should be completed first to avoid implementation conflicts.
Proceed anyway? (yes/no)
Wait for the user to respond. Only continue if the user explicitly confirms. If the user declines, STOP.
If no prerequisites section exists, or all blocking issues are closed, proceed normally.
Step 2c: Determine the Branch Base
Before creating or reusing an implementation branch, determine which branch this issue should build on.
Use the shared Resolve Base Branch from Issue helper in the github-ops skill.
- Read the issue labels and look for
spec-{NNN}. - If there is no
spec-{NNN}label, use the repository default branch. - If there is a
spec-{NNN}label, resolve the single matchingorigin/spec/{NNN}-*branch. - If the matching spec branch is missing or ambiguous, stop instead of guessing.
Record this as <base-branch> and use it consistently for branch creation, PR creation, and later sync checks.
Step 3: Move Issue to In Progress
Check whether the issue is already in "In Progress" status on its GitHub Project board. If not, move it there.
Approach — use gh CLI project commands:
- Find the project(s) associated with the repository:
gh project list --owner <owner> --format json - For each project, find the issue's item ID:
Search the results for the issue number.gh project item-list <project-number> --owner <owner> --format json - Get the Status field ID and the "In Progress" option ID:
gh project field-list <project-number> --owner <owner> --format json - Update the item's status:
gh project item-edit --id <item-id> --field-id <status-field-id> --project-id <project-id> --single-select-option-id <in-progress-option-id>
Fallback: If no project board is found, or the gh project commands fail, log a warning and continue — do not block implementation on project board status. Note the failure in the final summary so the user can manually update the status.
Step 4: Ensure Branch and PR Exist
Check whether a pull request already exists for this issue.
4a. Search for Existing PR
gh pr list --state open --json number,title,body,headRefName |
ConvertFrom-Json |
Where-Object { $_.body -match "Closes #<issue-number>" -or $_.title -match "<issue-number>" }
4b. If No PR Exists — Create Branch and PR
-
Create a branch linked to the issue using
gh issue develop:- Branch name format:
issue-<number>-<slugified-title>(e.g.,issue-42-fix-auth-token-expiry) - Slugify: lowercase, replace spaces/special chars with hyphens, truncate to ~50 chars
- Base branch:
<base-branch>from Step 2c
gh issue develop <issue-number> --base <base-branch> --name issue-<number>-<title-slug>This creates the branch on the remote, links it to the issue in GitHub's "Development" sidebar, and sets up tracking. It does NOT check out the branch locally (the worktree step handles that).
If
gh issue developfails (e.g., permissions, olderghversion), fall back to manual creation:git branch issue-<number>-<title-slug> <base-branch> git push -u origin issue-<number>-<title-slug> - Branch name format:
-
Create a draft PR:
gh pr create ` --title "<issue title>" ` --body "Closes #<issue-number>`n`n## Summary`n<brief description>" ` --draft ` --head issue-<number>-<title-slug> ` --base <base-branch>Closes #<issue-number>in the body auto-links the PR to the issue- Set as draft so it's clear the work is in progress
- Use
--headto specify the branch since we are not checked out on it - When the issue has a
spec-{NNN}label, this keeps incomplete feature work isolated from the default branch and integrates it through the spec branch first
-
Confirm the PR was created and note the PR number.
4c. If PR Already Exists
Record the existing PR number and branch name. No creation needed.
Step 5: Assess PR State and Determine Work Needed
This step determines what, if any, work needs to be done. The PR may be brand new (empty), may have complete implementation awaiting review, may have review feedback that hasn't been addressed, or may be fully approved with nothing left to do. You must assess all of this before proceeding.
5a. Collect All Signals
Gather all four of these data points:
- PR details — status, description, merge state:
gh pr view <pr-number> --json title,body,state,isDraft,baseRefName,headRefName,mergeable - PR diff and changed files:
gh pr diff <pr-number> gh pr view <pr-number> --json files --jq '.files[].path' - PR reviews — list of review submissions with state and timestamp:
gh api /repos/<owner>/<repo>/pulls/<pr-number>/reviews - PR review comments — individual inline comments with resolved status:
gh api /repos/<owner>/<repo>/pulls/<pr-number>/comments
Also collect: 5. PR commits — list of commits on the branch with timestamps:
gh api /repos/<owner>/<repo>/pulls/<pr-number>/commits
5b. Determine the Work State
Evaluate these signals in order to classify the current state. Use the first matching state:
State 1: Already Merged or Closed
| Signal | Value |
|---|---|
| PR status | merged or closed |
Action: Inform the user that the PR is already merged/closed and there is no work to do. STOP.
State 2: Approved — No Work Remaining
| Signal | Value |
|---|---|
| Most recent review state | APPROVED |
| Unresolved review comments | None (0 unresolved) |
Action: Inform the user:
Issue #<number> / PR #<pr-number> has been approved with no unresolved
review comments. There is no remaining work to implement.
STOP. Do not proceed to implementation.
State 3: Review Feedback Not Yet Addressed
| Signal | Value |
|---|---|
| Reviews exist | Yes, at least one with CHANGES_REQUESTED or with unresolved comments |
| Unresolved review comments | 1 or more |
| Commits after latest review | None — no commits exist with a timestamp after the most recent review's timestamp |
This means a reviewer has left feedback and no work has been done to address it yet. The unresolved review comments are the current "instructions."
Action: The work to do is address the unresolved review comments. Compile a list of every unresolved comment with its file, line, and body. These become the implementation requirements for Step 7.
State 4: Review Feedback Partially Addressed
| Signal | Value |
|---|---|
| Reviews exist | Yes |
| Unresolved review comments | 1 or more |
| Commits after latest review | Yes — at least one commit exists after the review timestamp |
This means some review feedback was addressed (there are newer commits) but some comments remain unresolved.
Action: The work to do is address the remaining unresolved review comments. Read the diff of commits made after the review to understand what was already addressed, then compile the still-unresolved comments as the remaining work.
State 5: Implementation Done, Awaiting Review (No Unresolved Feedback)
| Signal | Value |
|---|---|
| PR diff | Non-empty (code changes exist) |
| Reviews | Either none, or all are COMMENTED/`DISM |
Content truncated.