Fetch all review comments on the current branch's open pull request and address them.
-
Enable hook bypass. Run:
~/.claude/scripts/marker.sh activate respond-pr
The require-respond-pr.sh PreToolUse hook bypasses while THIS session's marker exists and its stored PID is alive (PID liveness check via kill -0). Per-session keying prevents parallel respond-pr sessions from thrashing on cleanup or leaking bypass to unrelated sessions. If the chain fails (empty SESSION_ID, etc.), the capture-session-id.sh SessionStart hook didn't run — abort and report; do not proceed without the marker, since every gated gh call below will be blocked.
Marker lifecycle: this marker must stay active for the entire skill session — step 9 is the only step that removes it. If you run other skills as intermediate steps (e.g., /ready-for-review before pushing in step 8), their cleanup must not touch this marker. If the marker is accidentally removed mid-session, restore it in a standalone Bash call before any subsequent gh command — the hook fires before the shell executes, so you cannot create the marker and use it atomically in the same call.
-
Identify the PR number for the current branch: gh pr view --json number -q '.number'
-
Fetch all three types of comments. Two failure modes Claude commonly hits: (a) fetching only the first type and missing the other two; (b) fetching without --paginate and silently truncating at 30 results per type. Both produce reviews that look complete but miss real feedback.
- Inline file comments:
gh api repos/{owner}/{repo}/pulls/{number}/comments --paginate
- Top-level review comments:
gh api repos/{owner}/{repo}/pulls/{number}/reviews --paginate --jq '.[] | select(.body != "")'
- Issue-level comments:
gh api repos/{owner}/{repo}/issues/{number}/comments --paginate
-
Divergence precheck. Before applying any FIXED change or posting any reply, run the canonical detection recipe (see git-feature-branch-sync/SKILL.md § "Detecting divergence") against the PR's base branch (gh pr view --json baseRefName --jq .baseRefName). If the trial merge reports CONFLICT, abort the skill — print a message naming the PR number (captured in step 1) and route the user to /git-feature-branch-sync. Do not apply FIXED changes onto a stale tree; replies acknowledging fixes would refer to a commit the reviewer cannot cleanly resolve. If the trial merge is CLEAN, proceed even when behind > 0 — small drift is normal during review; the precheck only blocks on actual conflicts.
-
Holistic triage. Before classifying or fixing anything, read the complete set of unresolved comments as one body and name what you find across them:
- Shared root causes — multiple comments tracing to one underlying issue. Fix at the root once; a serial fix-the-first-then-the-next sequence has produced regressions where the second fix stripped what the first one needed.
- Contradictions — reviewers asking for incompatible things. Pick a direction explicitly; a silent choice surfaces in the next review round.
- Batched-design choices — comments that are constraints on one design question, not independent issues (e.g., three comments that all resolve to "pick A or B"; naming conventions across functions; error-handling shape across handlers).
If none apply after a careful read, say so — but the read is required. Per-comment patching that skips this step produces overlapping fixes and diffs reviewers must re-review one thread at a time.
-
Classify, then batch. Assign each unresolved comment to one of the five types below. When there are 3+ unresolved comments, render the classification as a four-column table — Comment (one-line + source link) | Theme (from step 4, or —) | Disposition | Plan — before starting any per-comment work; the table forces all comments to be seen at once and ties each one to the cross-cutting themes named in step 4. All code changes across the batch go into a single commit (step 8); all replies are posted after that commit. Required fields are not optional — if a field's value is non-obvious, that is exactly when it earns its keep.
FIXED — a code change was made.
Required fields: disposition (one of fixed-as-requested | fixed-with-modification | fixed-differently), rationale (REQUIRED when disposition ≠ fixed-as-requested — explain what was changed and why), commit_sha (filled in after the commit in step 8).
EXPLAIN-DESIGN — the existing code is correct; the comment misreads intent.
Required fields: decision (what the code does), why (the reason it does that), why-not-alternative (why the reviewer's apparent alternative was not taken), where-documented (file:line or "inline below").
OUT-OF-SCOPE — the comment identifies a real issue but it belongs in a separate PR.
Required fields: acknowledgment (confirm the issue is real), where-tracked (ticket or backlog), link-or-ticket (URL or "will create").
DEFERRED — the change is valid but intentionally left for a follow-up.
Required fields: acknowledgment, deferral-reason, follow-up-ticket (URL to an existing ticket, or "will create: <one-line summary>" if none exists yet — but the ticket must be created before the skill session ends).
AGREE-NO-CHANGE — the reviewer is right but the code already handles it, or the suggestion is a matter of preference and no change is warranted.
Required fields: acknowledgment, rationale.
Worked examples (illustrating required-field depth, not wording to copy verbatim):
FIXED with fixed-with-modification:
[Claude Code] Fixed. Applied the reviewer's intent (validate before writing) but checked at the handler level rather than inline at the call site — the call site is shared by three paths and an inline check would need to be duplicated. disposition: fixed-with-modification | rationale: moved check to handler boundary to avoid three-way duplication | commit_sha: <sha>
EXPLAIN-DESIGN:
[Claude Code] The early return is intentional — when the session token is absent we want a fast 401 with no DB round-trip. The alternative (falling through to a null-check deeper in the stack) would silently succeed for unauthenticated callers in contexts where the token field is optional. where-documented: auth/middleware.ts:42
-
For each unresolved comment:
- Read the referenced file and line to understand the context
- Apply the classification from step 5
- If a code change is needed, make it; note it in the reply using the
FIXED field template
- If it's design explanation, draft using the
EXPLAIN-DESIGN template
-
Post replies using the appropriate endpoint for each comment type — do not use gh api .../pulls/comments/{id} with -F body=...; that endpoint PATCHes the target comment in place and silently overwrites the author's text.
-
Inline file comments (fetched from pulls/{n}/comments) — reply via the /replies sub-resource:
gh api repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies \
-F body='**[Claude Code]** ...reply text...'
-
Top-level review bodies (fetched from pulls/{n}/reviews) — no /replies primitive exists; post a new top-level comment in the conversation tab:
gh api repos/{owner}/{repo}/issues/{number}/comments \
-F body='**[Claude Code]** ...reply text...'
-
Issue-level comments (fetched from issues/{n}/comments) — same path; no /replies sub-resource:
gh api repos/{owner}/{repo}/issues/{number}/comments \
-F body='**[Claude Code]** ...reply text...'
-
Commit and push any code changes in a single commit
-
Remove this session's hook bypass marker:
~/.claude/scripts/marker.sh deactivate respond-pr
Removes only this session's file. If the skill errors out before reaching this step, the gate will evict the orphan automatically once the session's process ends — the hook checks PID liveness on each gate hit.