Skip to content
Development
Skill

/pr-review

Address feedback left on a GitHub pull request: fetch unresolved review threads, make agreed Elixir/Phoenix code fixes, reply, and resolve. Use for a PR URL/number or reviewer comments. NOT for pre-PR review, findings triage, or CI monitoring.

From plugin
claude-elixir-phoenix
576106 skills37 agents2 commands

Claude Code

$ npx -y skills add oliver-kriska/claude-elixir-phoenix --skill pr-review --agent claude-code

SKILL.md

pr-review.SKILL.md
name: pr-review
description: "Address feedback left on a GitHub pull request: fetch unresolved review threads, make agreed Elixir/Phoenix code fixes, reply, and resolve. Use for a PR URL/number or reviewer comments. NOT for pre-PR review, findings triage, or CI monitoring."
effort: high
argument-hint: <PR number or URL> [--fix] [--bots-only] [--no-resolve]

PR Review Response

Close the review loop: fetch unresolved threads → fix → reply → resolve. GitHub's `isResolved` is the state — re-runs are idempotent, handled threads drop out automatically.

Usage

/phx:pr-review 42                  # Triage unresolved threads on PR #42
/phx:pr-review 42 --fix            # Triage + apply approved code fixes
/phx:pr-review https://...         # Full URL also works (repo parsed from URL)
/phx:pr-review 42 --bots-only      # Triage only CI bot threads (Copilot, Codex...)
/phx:pr-review 42 --no-resolve     # Reply but leave threads open

Step 1: Resolve PR + Fetch Threads

`gh pr view "$PR" --json number,title,state,baseRefName,headRefName,url,author` (accepts number or URL; URL also yields owner/repo). Then fetch ALL review threads with thread IDs + resolved status — REST alone cannot do this:

cat > /tmp/review_threads.graphql <<'GQL'
query($owner:String!, $repo:String!, $pr:Int!, $cursor:String) {
  repository(owner:$owner, name:$repo) {
    pullRequest(number:$pr) {
      reviewThreads(first:50, after:$cursor) {
        pageInfo { hasNextPage endCursor }
        nodes {
          id isResolved isOutdated path line originalLine
          comments(first:20) { nodes {
            databaseId body createdAt
            author { login __typename } } }
        }
      }
    }
  }
}
GQL
gh api graphql --paginate -F owner="$OWNER" -F repo="$REPO" -F pr="$PR" \
  -F query=@/tmp/review_threads.graphql \
  --jq '.data.repository.pullRequest.reviewThreads.nodes[]
        | select(.isResolved == false)
        | {threadId: .id, isOutdated, path, line: (.line // .originalLine),
           firstCommentId: .comments.nodes[0].databaseId,
           author: .comments.nodes[0].author.login,
           isBot: (.comments.nodes[0].author.__typename == "Bot"),
           body: .comments.nodes[0].body}'

Also fetch review summaries (`gh api "repos/$OWNER/$REPO/pulls/$PR/reviews"`) — they are NOT threads and cannot be resolved; surface `CHANGES_REQUESTED` bodies separately. Bot detection: `__typename == "Bot"` / `user.type == "Bot"` (the `[bot]` login suffix is NOT reliable across endpoints).

Step 2: Triage Table

Group by file, one row per thread. With `--bots-only`, keep only `isBot` rows.

| # | file:line | author | category | proposed action | |---|-----------|--------|----------|-----------------|

Categories: **code-change** ("should be", "use X instead") · **question** ("why", "how does") · **nitpick** ("nit:", style) · **praise** (no action) · **discussion** (architecture) · **bot-finding** (CI bot inline comment — verify before accepting, many are false positives) · **outdated** (`isOutdated: true` — line moved; default: reply "addressed in {commit}" + resolve). Present the table and let the user greenlight threads.

Step 3: Per-Thread Loop

For each greenlit thread:

1. Read code at `path:line`; check the suggestion against Iron Laws 2. Apply fix with a user-visible diff (only with `--fix` or explicit ok) 3. Draft reply (templates: `${CLAUDE_SKILL_DIR}/references/response-patterns.md`) 4. **STOP — show diff + reply, get confirmation** 5. Post reply — REST, targeting the thread's root comment:

   gh api --method POST \
     "repos/$OWNER/$REPO/pulls/$PR/comments/$FIRST_COMMENT_ID/replies" \
     -f body="$REPLY_TEXT"

6. Resolve the thread (skip with `--no-resolve`):

   gh api graphql -f query='mutation($threadId:ID!){
     resolveReviewThread(input:{threadId:$threadId}){
       thread { id isResolved } }}' -F threadId="$THREAD_ID"

Mistake recovery: `unresolveReviewThread` takes the same input shape.

Step 4: Verify

`mix compile --warnings-as-errors && mix test` scoped to changed files. Do NOT commit or push — leave that to the user.

Step 5: Final Summary

Print rollup: `# | thread | action | status (replied/resolved/skipped)`. List changed files. Optionally post a top-level conversation comment (`gh api --method POST "repos/$OWNER/$REPO/issues/$PR/comments" -f body=...`) with the rollup — **only on user approval**.

Iron Laws

1. **NEVER auto-post responses** — Always show drafts and get explicit approval 2. **NEVER dismiss a review** — Only the reviewer should dismiss 3. **Iron Laws override reviewer suggestions** — If a suggestion violates an Iron Law, explain why in the reply 4. **Keep responses constructive** — Acknowledge the feedback, explain reasoning 5. **Separate fixes from responses** — Apply code changes in a distinct step 6. **NEVER resolve a thread without first posting a reply** — every resolve is preceded by a reply on that thread explaining what was done 7. **NEVER claim a fix without a shown diff** — no "should be fixed" replies without a user-visible change 8. **Bot findings get the same scrutiny as humans** — decline Iron-Law-violating bot suggestions with explanation; never bulk-resolve "bot noise" without replies

Integration

PR receives review → /phx:pr-review {number}  ← YOU ARE HERE
   ↓ fetch unresolved threads (GraphQL, paginated)
   ↓ triage table → user greenlights
   ↓ per thread: fix (diff) → reply → resolve
   ↓ verify (mix compile + test) → summary
Push changes → user handles git push

Next Steps

  • `/phx:plan` — if findings reveal scope gaps
  • `/phx:verify` — full verification before pushing
  • Re-run `/phx:pr-review` after the next review round (idempotent)

References

  • `${CLAUDE_SKILL_DIR}/references/response-patterns.md` — Response templates and tone
  • `${CLAUDE_SKILL_DIR}/references/gh-commands.md` — Full gh command reference (3 comment surfaces, pagination, bot
Read more
@oliver-kriska
Ships withclaude-elixir-phoenix

Docs: phxagents.dev -- install guides per runtime, the runtime compatibility matrix, all 26 Iron Laws, and a browsable skill and agent catalog. Claude Code is great.

576106 skills37 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
576
Star history of oliver-kriska/claude-elixir-phoenix on GitHub, a chart by star-history.com

Other skills on claude-elixir-phoenix.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about pr-review.

Which coding agents can use pr-review?
pr-review installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.