skills/address-pr-feedback/SKILL.md
Address, fix, respond to, or resolve GitHub pull request feedback. Use when the user asks to handle PR review comments, or address feedback on PRs.
npx skillsauth add afollestad/personal-ai-skills address-pr-feedbackInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This is a mutating workflow. You may edit files, rewrite commits, push branches, reply to comments, resolve threads, and hide eligible bot comments. Act immediately unless the user explicitly asks for a checkpoint.
All direct GitHub API, comment, review, and PR metadata operations must use the gh CLI. Do not use curl, direct API URLs outside gh api, or web fetching. When Graphite applies, gt may be used for stack-aware restacking and submission.
gh auth status. If authentication fails, stop and tell the user to run gh auth login.gh api user --jq .login; use it to avoid duplicate replies from prior runs.git status --short. Do not overwrite unrelated dirty changes. If unrelated dirty changes would block the work, stop and explain the conflict.git branch --show-current.Use the PR URL, PR number, or branch the user supplied. If none was supplied, use the PR for the checked-out branch:
gh pr view --json number,title,url,baseRefName,headRefName,headRefOid,state,isCrossRepository,maintainerCanModify,headRepository,headRepositoryOwner
If no PR is found and the user did not supply one, stop and say there is no PR for the checked-out branch.
For each target PR, load metadata:
gh pr view <PR> --json number,title,url,baseRefName,headRefName,headRefOid,body,comments,reviews,author,state,isCrossRepository,maintainerCanModify,headRepository,headRepositoryOwner
gh pr diff <PR>
Before editing, verify the PR head branch is writable. For cross-repository PRs, require maintainerCanModify == true and a successful gh pr checkout <PR>; otherwise stop before edits and report that the branch cannot be updated. Make sure the local checkout is on the branch that should own the fix, or on a stack branch where the owning commit is reachable and can be amended safely. If the needed PR branch is not checked out locally, create it from the remote PR head with gh pr checkout <PR>. Do not apply fixes to whatever branch happened to be checked out.
Default to stack-aware behavior. If the PR belongs to a stack, gather feedback for the stack. If the user gives a specific PR in a stack, gather feedback for all PRs from the stack base through that PR.
Treat Graphite as available only when both checks pass in the target checkout:
command -v gt
gt --no-interactive log short --stack
Use Graphite only when the target PR's headRefName is present as an exact branch name in the Graphite-tracked stack. Do not use gt just because it is installed. If gt exists but the target branch is not tracked by Graphite, Graphite commands fail, Graphite auth/init is missing, or the target PR branch is absent from gt --no-interactive log short --stack, fall back to gh-based stack inference.
When Graphite applies:
gt --no-interactive log short --stack to identify ancestors and descendants.gt --no-interactive restack --upstack after amending a non-tip branch.gt --no-interactive submit --stack --update-only to push the current branch and subsequent stack branches after fixes. If the installed Graphite version supports --no-edit, it may be added, but do not rely on it.gt --no-interactive absorb for staged fixes that should be amended into owning commits or gt --no-interactive modify for the current branch.Without applicable Graphite, infer stack links from open PR branch relationships:
gh pr list --state open --limit 100 --json number,title,url,baseRefName,headRefName,headRefOid,isCrossRepository,maintainerCanModify,headRepository,headRepositoryOwner
gh pr list --state open --head <branch> --json number,title,url,baseRefName,headRefName,headRefOid,isCrossRepository,maintainerCanModify,headRepository,headRepositoryOwner
gh pr list --state open --base <branch> --json number,title,url,baseRefName,headRefName,headRefOid,isCrossRepository,maintainerCanModify,headRepository,headRepositoryOwner
Treat PR B as stacked on PR A when B.baseRefName == A.headRefName. Walk ancestors by looking up an open PR whose headRefName equals the current PR's baseRefName. Walk descendants by looking up open PRs whose baseRefName equals the current PR's headRefName. Use the broad --limit 100 list as a cache, but run the targeted --head/--base lookups when the next stack link is not found there. For a supplied PR, include ancestors through that PR. For an inferred current-branch PR, include the whole connected stack.
gh pr list --head does not support owner:branch syntax. If multiple open PRs share the same headRefName, disambiguate with headRepositoryOwner.login and headRepository.name. If the owning repository is still ambiguous, stop instead of guessing the stack.
Ignore already-resolved feedback before analysis:
isResolved == true for feedback analysis, but keep their node data for the bot minimization cleanup pass. A resolved review thread can still keep a bot review block visible in GitHub until the bot's review comments and review summary are minimized.isMinimized == true.state is not SUBMITTED.outdated == true as obsolete unless a newer unresolved comment in the same thread keeps the issue current.Keep separate collections for actionable feedback and hide/minimize cleanup candidates. Actionable feedback excludes already-resolved threads. Cleanup candidates may include resolved threads, outdated bot comments, and bot review summaries when the feedback is already addressed, replied to, invalid, obsolete, duplicate, blocked, or too risky to address.
When GraphQL returns an author, request author { __typename login }. Treat the author as confidently automated for hiding only when author.__typename == "Bot". For REST issue comments, continue using user.type == "Bot".
Gather top-level PR comments:
gh api repos/{owner}/{repo}/issues/<number>/comments --paginate
The REST response includes node_id and user.type. Use user.type for bot detection. REST issue comments do not expose minimization state, so check those comment nodes with GraphQL before analyzing or hiding top-level comments. Repeat -F ids[]=... for each comment node ID:
gh api graphql -F ids[]=<comment-node-id> -f query='
query($ids: [ID!]!) {
nodes(ids: $ids) {
... on IssueComment {
id
body
url
isMinimized
minimizedReason
viewerCanMinimize
author { __typename login }
}
}
}'
Gather a quick view of review bodies:
gh pr view <PR> --json reviews
For complete review-body feedback, fetch reviews through GraphQL and use only non-dismissed reviews with non-empty bodies:
gh api graphql --paginate -F owner='{owner}' -F name='{repo}' -F number=<number> -f query='
query($owner: String!, $name: String!, $number: Int!, $endCursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviews(first: 100, after: $endCursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
body
state
url
isMinimized
minimizedReason
viewerCanMinimize
author { __typename login }
}
}
}
}
}'
Gather review threads with GraphQL. Use unresolved threads for actionable feedback, and keep resolved threads available for the bot minimization cleanup pass:
gh api graphql --paginate -F owner='{owner}' -F name='{repo}' -F number=<number> -f query='
query($owner: String!, $name: String!, $number: Int!, $endCursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
id
number
reviewThreads(first: 100, after: $endCursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
isResolved
viewerCanReply
viewerCanResolve
path
line
originalLine
startLine
comments(first: 100) {
totalCount
nodes {
id
body
url
createdAt
state
outdated
author { __typename login }
isMinimized
minimizedReason
viewerCanMinimize
pullRequestReview {
id
url
isMinimized
minimizedReason
viewerCanMinimize
author { __typename login }
}
}
}
}
}
}
}
}'
gh api graphql --paginate paginates the outer reviewThreads connection here. If a thread's comments.totalCount is greater than the number of fetched comment nodes, fetch the remaining comments for that thread with a separate thread-node query before evaluating it:
gh api graphql --paginate -F threadId=<thread-id> -f query='
query($threadId: ID!, $endCursor: String) {
node(id: $threadId) {
... on PullRequestReviewThread {
comments(first: 100, after: $endCursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
body
url
createdAt
state
outdated
author { __typename login }
isMinimized
minimizedReason
viewerCanMinimize
pullRequestReview {
id
url
isMinimized
minimizedReason
viewerCanMinimize
author { __typename login }
}
}
}
}
}
}'
For every remaining item, decide and record:
Address valid and addressable feedback. Do not make requested changes that would introduce regressions; reply with the reason instead.
Unless the user says otherwise, amend fixes into the relevant existing commit.
gt --no-interactive absorb or gt --no-interactive modify when appropriate, then restack.--force-with-lease.Co-authored-by: Codex <[email protected]>
Run focused tests or checks appropriate to the changed code before pushing. If checks cannot run, say why in the final report.
When feedback is addressed in a stack, push the current branch and every subsequent branch whose history changed.
gt --no-interactive restack --upstack, then gt --no-interactive submit --stack --update-only.git push --force-with-lease.Stop and report conflicts instead of guessing through a conflicted restack or rebase.
Reply to every considered feedback item, whether addressed or not. Keep replies concise:
For review threads with multiple comments, evaluate each unresolved comment but prefer one consolidated thread reply that covers all considered points in that thread.
Before posting, check existing PR comments and review-thread replies by the authenticated user. Do not post a duplicate reply if a prior reply already references the same original comment or thread and no new feedback has appeared since that reply.
For review threads, reply in the thread only when viewerCanReply == true. If viewerCanReply == false, do not attempt the mutation; report that the thread could not be replied to.
cat <<'REPLY' > /tmp/pr-feedback-reply.md
<reply>
REPLY
gh api graphql -f query='
mutation($threadId: ID!, $body: String!) {
addPullRequestReviewThreadReply(input: {pullRequestReviewThreadId: $threadId, body: $body}) {
comment { url }
}
}' -F threadId=<thread-id> -F body=@/tmp/pr-feedback-reply.md
For top-level PR comments or review bodies, GitHub comments are flat. Add a new PR comment that references the original comment/review URL or author:
cat <<'REPLY' > /tmp/pr-feedback-reply.md
<reply>
REPLY
gh pr comment <PR> --body-file /tmp/pr-feedback-reply.md
After replying, resolve every considered review thread with GraphQL when viewerCanResolve == true, including threads where the feedback was invalid, obsolete, duplicate, blocked, or too risky to address. Leave a thread unresolved only if viewerCanResolve == false, the API refuses the action, permissions are missing, or the user explicitly asked to keep it open.
gh api graphql -f query='
mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread { id isResolved }
}
}' -F threadId=<thread-id>
Hide/minimize addressed comments and reviews only when viewerCanMinimize == true and the author is confidently automated:
user.type == "Bot".author.__typename == "Bot".If user.type or author.__typename is missing or ambiguous, do not hide the comment or review. Do not hide comments based on username substrings. Never hide comments from uncertain or human-looking accounts.
Also minimize eligible bot-authored review nodes after their feedback has been considered:
PullRequestReviewComment nodes in every considered thread when viewerCanMinimize == true and the author is confidently automated.PullRequestReview summary node when viewerCanMinimize == true, the review body has been considered or only contains boilerplate for the considered review comments, and none of that bot review's current comments remain unresolved/actionable.PullRequestReviewComment nodes and the associated bot PullRequestReview without posting duplicate replies.Minimize eligible top-level comments, review bodies, and review comments with GraphQL:
gh api graphql -f query='
mutation($subjectId: ID!) {
minimizeComment(input: {subjectId: $subjectId, classifier: RESOLVED}) {
minimizedComment { isMinimized minimizedReason }
}
}' -F subjectId=<comment-node-id>
Use the REST issue comment's node_id, the PullRequestReview.id, or the PullRequestReviewComment.id as subjectId; do not use the numeric database ID.
Return a concise final report with the PRs handled, what changed, what was pushed, what was resolved or left open, and which checks ran.
documentation
Review a PR and submit suggestions as comments, along with an optional approval/request for changes.
development
Self-review, self review, self-reviewing, audit, check, or fix the current uncommitted Git diff or other uncommitted local Git changes before a commit or pull request. Use when the user asks for a repo-aware quality audit, pre-commit review, review of their diff, another pass, or another pass over local changes, or when asked to inspect local diffs, staged changes, unstaged changes, or untracked files for bugs, regressions, missing tests, lint, accessibility, stale code, or similar issues. The workflow loops after automatic or confirmed fixes until two consecutive clean passes verify that nothing remains to fix or report.
development
Invoke this skill whenever the user asks you to produce a prompt, summary, or context package intended as input for a future AI session. This covers: handoff prompts, context dumps, new-thread prompts, paste-ready prompts for fresh sessions, or any request to distill this conversation so another Claude instance or background agent can continue the work. Also invoke when the user mentions context window limits, thread length concerns, or wanting to reset/wrap up while preserving progress for a next session. This skill owns the output format and relevance filtering — do not attempt these handoffs without it. Do NOT invoke for human-audience artifacts: docs, READMEs, commit messages, tickets, release notes, standup updates, code explanations, or handoffs to human coworkers.
documentation
Review a PR and submit suggestions as comments, along with an optional approval/request for changes.