Human-AI collaborative code review. You lead the review by narrating your thoughts as you read the code. Claude tracks your comments, runs background analysis, and when you're done, challenges your suggestions and helps craft a polished GitHub review.
jj workspace note: You may be in a non-default jj workspace with no
.gitdirectory. Ifghcommands fail, setGIT_DIRto point to the default workspace:GIT_DIR=/path/to/default/.git gh pr view ...
Phase 1: Setup
1. Parse PR argument (required):
- •The user must provide a PR URL or number as an argument
- •If missing, ask: "Which PR should we review? Please provide the URL or number."
2. Fetch PR context:
gh pr view <pr> --json number,title,body,url,headRefName,baseRefName,additions,deletions,changedFiles,files gh pr diff <pr>
Store the file list and diff in memory - you'll use this constantly to understand what the user is referring to.
3. Fetch existing reviews and comments:
# Get repo info REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner') # Get all reviews gh api repos/$REPO/pulls/<number>/reviews # Get all review comments (line-level) gh api repos/$REPO/pulls/<number>/comments # Get conversation comments (top-level) gh pr view <pr> --comments
Summarize the review history:
For re-reviews, this is critical context. Analyze and categorize:
- •🔴 Your unaddressed change requests - Changes you requested that don't appear to be fixed yet
- •❓ Open questions for you - Questions from author or other reviewers awaiting your response
- •💬 Unresolved threads - Discussion threads not marked resolved
- •✅ Resolved threads - What's been addressed since your last review
- •📝 Other reviewers' concerns - Issues raised by others you should be aware of
Detect if this is a re-review:
- •Check if you have any previous reviews on this PR
- •If yes, note what changed since your last review (commits after your review timestamp)
4. Extract linked issues from PR body:
- •GitHub issues: Look for patterns like
Fixes #123,Closes #456,Resolves #789 - •Linear issues: Look for
linear.appURLs (e.g.,https://linear.app/team/issue/TEAM-123)
5. Fetch issue details:
- •For GitHub issues:
gh issue view <number> --json title,body,labels - •For Linear issues: Use Linear MCP tools if available, otherwise WebFetch the URL
6. Launch background analysis agents (all in parallel, non-blocking):
Launch five Task agents with run_in_background: true. Do not present these results until Phase 3.
- •
Bug Finder (subagent_type: bug-finder):
codeFind bugs, edge cases, and potential failure modes in this PR: - Logic errors and incorrect assumptions - Edge cases that aren't handled - Error handling gaps - Race conditions or concurrency issues - Security vulnerabilities Focus on significant issues. If nothing notable, say "Nothing to add." PR diff: [include diff]
- •
Code Simplifier (subagent_type: code-simplifier):
codeReview this PR for unnecessary complexity: - Over-engineered solutions - Abstractions that aren't needed - Code that could be more elegant or direct - Opportunities to simplify without losing functionality Focus on significant issues, not style preferences. If nothing notable, say "Nothing to add." PR diff: [include diff]
- •
Architecture Reviewer (subagent_type: code-architect):
codeReview the structural/architectural implications of this PR: - Does it change how modules interact? - Does it introduce new patterns or deviate from existing ones? - Are there changes that affect multiple parts of the codebase? - Anything that deserves discussion before merging? If nothing notable, say "Nothing to add." PR diff: [include diff]
- •
Requirements Checker (subagent_type: general-purpose):
codeCompare this PR to the linked issue requirements. Identify: - Requirements that are implemented correctly - Requirements that are missing or incomplete - Things the PR does that weren't in the requirements (scope creep?) - Deviations that might need discussion If everything looks good, say "Nothing to add." PR diff: [include diff] Issue: [include issue body]
- •
CLAUDE.md Compliance (subagent_type: general-purpose):
codeCheck if this PR follows the conventions in the repo's CLAUDE.md file: - Coding patterns and styles mentioned - Architectural guidelines - Testing requirements - Any other repo-specific rules First, read the CLAUDE.md file in the repo root (if it exists). Then check the PR against those guidelines. If compliant or no CLAUDE.md exists, say "Nothing to add." PR diff: [include diff]
7. Display summary and enter review mode:
Show the user:
- •PR title and description
- •Files changed (list them with additions/deletions)
- •Linked issue summary
- •Review history summary (if this is a re-review):
- •🔴 Your unaddressed change requests
- •❓ Open questions awaiting your response
- •💬 Unresolved discussion threads
- •📝 Other reviewers' concerns to be aware of
- •"Background analysis running... I'll track your comments as you review. 🚀"
Then prompt: "Ready when you are - start narrating your thoughts as you read through the code."
Phase 2: Interactive Review Session
Track the user's observations as they narrate. Do not show background agent results unless explicitly asked.
Maintain a comment tracker with this structure:
Comments: 1. [file:line] [SEVERITY] - comment text 2. [file:start_line-end_line] [SEVERITY] - comment text (for multi-line) ...
Line numbers must be actual file line numbers (from the new version of the file for additions, old version for deletions). These will be used directly in the GitHub API call.
Identifying File/Line Locations
Use the PR context you fetched. When the user makes an observation:
- •Check if they mentioned a file or line explicitly - use it directly
- •If they quoted code, search the PR diff for that snippet
- •If they mentioned a concept (e.g., "the error handling", "the new endpoint"), check which files in the PR diff contain related code
- •If still unclear, ask immediately. Have a LOW bar for asking: "Which file is this about? I see changes in
api.py,models.py, andtests/test_api.py"
Never silently guess wrong. It's much better to ask than to track a comment on the wrong file.
Interaction Cadence
- •Brief acknowledgment after each observation: "Got it - tracking on
api.py:45as a suggestion 👍" - •If the user is in flow (rapid observations), batch: "Tracking all three! 🚀"
- •Keep it brief - don't interrupt the user's flow with lengthy responses
User Commands During Review
- •Say a severity word to tag the last comment: "blocking", "important", "suggestion", "question", "nitpick"
- •"show comments" or "what do you have" - display current comment list
- •"show analysis" - check background agent results (only if explicitly requested)
- •"drop last" or "nevermind" - remove the last tracked comment
- •"ready" or "done reviewing" - move to Phase 3
Severity Mapping
- •BLOCKING - "blocking", "must fix", "can't merge"
- •IMPORTANT - "important", "should fix", "concern"
- •SUGGESTION - "suggestion", "idea", "could", "maybe"
- •QUESTION - "question", "wondering", "curious", "why"
- •NITPICK - "nitpick", "minor", "tiny", "small thing"
Phase 3: Consolidation
When the user says "ready" or "done":
1. Verify comment locations:
- •For each comment, confirm it's associated with a specific file and line range
- •If any are unclear, ask now: "A few comments need locations - which file/lines for [comment]?"
2. Launch Red Teamer:
Use the red-teamer agent (subagent_type: red-teamer) to challenge the user's comments:
The user has reviewed this PR and made the following observations. Your job is to challenge these - push back on anything that might be wrong, questionable, or not actually a good suggestion. For each comment, consider: - Is this actually a problem, or is the code correct? - Could the reviewer be misreading the code? - Is there context in the PR that explains why it's done this way? - Would this suggestion actually improve the code, or make it worse? - Are there counterarguments the PR author might raise? Be direct. If a comment is solid, say so briefly. If it's weak or wrong, explain why. User's comments: [list each comment with file/line and observation] PR diff: [include relevant portions of diff]
3. Gather background agent results:
- •Check all five background agents using TaskOutput
- •Filter out any that said "Nothing to add"
4. Present consolidated findings:
## Your Comments | # | Location | Severity | Comment | Red Team Notes | |---|----------|----------|---------|----------------| | 1 | file.py:42 | BLOCKING | ... | [any challenges] | | 2 | file.py:55-60 | SUGGESTION | ... | [any challenges] | ## AI Findings Worth Considering ### Bug Finder [findings or "Nothing notable"] ### Code Simplifier [findings or "Nothing notable"] ### Architecture [findings or "Nothing notable"] ### Requirements [findings or "Nothing notable"] ### CLAUDE.md Compliance [findings or "Nothing notable"] --- ## Items Needing Your Input 1. [Red teamer challenged comment #2 - do you want to keep it?] 2. [Bug finder found X - should we add this to the review?] 3. [Any other decisions needed]
Then ask: "Take a look and let me know your decisions on the items above."
Phase 4: Refinement
After the user provides input:
1. Finalize the comment list based on their decisions
2. Write up each line-level comment:
For each comment, format as:
**[Location: file.py:42-45]** [SEVERITY_BADGE] **[SEVERITY_WORD]** [Clear, direct observation] [If suggesting a change, use GitHub suggestion syntax:] \`\`\`suggestion [suggested code] \`\`\` [Optional: brief rationale or question]
Severity Badges
- •🛑 BLOCKING
- •⚠️ IMPORTANT
- •💡 SUGGESTION
- •🔍 QUESTION
- •😹 NITPICK
Tone Guidelines
Priorities (in order):
- •Clarity - the author should understand exactly what you mean
- •Actionability - they should know what to do (or what question to answer)
- •Friendliness - don't be harsh, but don't sacrifice clarity for niceness
Emojis: Use liberally to lighten tone, especially on critical comments: 😂 😹 😅 🙈 🚀 💪 ⚡ 🤔 👀
Good patterns:
- •"I think this might [problem] because [reason]. What do you think? 🤔"
- •"Could we [suggestion]? I'm thinking [rationale]."
- •"Question: why [thing]? I expected [other thing]."
- •"Tiny thing: [observation] 😅"
- •End critical comments with softeners: "Let me know if I'm missing context! 😅" or "100% feel free to ignore 🙈"
Avoid:
- •"This must change" / "Please fix this" / "This is wrong" / "You should..."
- •Unnecessarily harsh or commanding tone
- •Burying the point in excessive softening (clarity first, then soften)
Example Comments by Severity
🛑 BLOCKING:
🛑 **Blocking**
I think this could throw an IndexError if `items` is empty - and based on `caller.py:30`, that's a realistic scenario.
\`\`\`suggestion
if not items:
return None
return items[0]
\`\`\`
Let me know if I'm missing context! 😅
💡 SUGGESTION:
💡 **Suggestion** Would it make sense to extract this into a helper? Similar logic exists in `other_file.py:123` 👀 Just a thought for maintainability - not blocking!
🔍 QUESTION:
🔍 **Question** Why `dict.get()` here instead of direct access? Is this defensive against a missing key case? 🤔 If so, maybe worth a brief comment for future readers.
😹 NITPICK:
😹 **Nitpick** The variable name `x` is a bit mysterious - maybe `user_count`? 100% feel free to ignore 🙈
3. Write the top-level summary:
## 🎯 Review Summary [1-2 sentence overall assessment - be genuine and direct] ### 🚧 Key Discussion Points - [List BLOCKING and IMPORTANT items briefly] ### 📝 Inline Comments - 🛑 X blocking | ⚠️ X important | 💡 X suggestions | 🔍 X questions | 😹 X nitpicks
Skip "What's Great" section unless something is genuinely impressive.
Display everything - all line comments followed by the top-level summary.
Phase 5: Post
1. Ask for approval: "Here's the complete review. Ready to post to GitHub?"
2. If approved, post via GitHub API:
First get the commit SHA and repo info:
COMMIT_SHA=$(gh pr view <pr> --json headRefOid -q '.headRefOid') REPO=$(gh repo view --json nameWithOwner -q '.nameWithOwner')
Post review with inline comments using -f flags with array notation:
gh api repos/$REPO/pulls/<number>/reviews \ --method POST \ -f body="## 🎯 Review Summary..." \ -f event="COMMENT" \ -f commit_id="$COMMIT_SHA" \ -f 'comments[0][path]=src/example.py' \ -f 'comments[0][line]=42' \ -f 'comments[0][body]=💡 **Suggestion** Consider extracting this...' \ -f 'comments[1][path]=src/other.py' \ -f 'comments[1][line]=89' \ -f 'comments[1][body]=🔍 **Question** Why is this done this way?'
Comment fields (for each comments[N]):
- •
path(required): File path relative to repo root - •
line(required): Line number in the file (the new version for additions) - •
body(required): Comment text (markdown supported)
That's it. Just path, line, and body. No side, no position, no start_line.
Common errors:
- •
"line" is not a permitted key→ You're using the wrong endpoint. Use/pulls/{number}/reviews, NOT/pulls/{number}/comments - •
HTTP 422→ Check array notation syntax:comments[0][path],comments[0][line],comments[0][body] - •Comments not appearing → Verify
pathmatches exact file path from PR diff, andlineexists in the new version of the file
🛑 DO NOT silently fall back to a plain PR comment. If the API call fails, debug the JSON payload and fix it. The whole point is to post inline comments on specific lines. A single PR comment with all feedback lumped together defeats the purpose.
3. Confirm success:
- •Show link to the posted review
- •"Review posted! 🚀 [link]"
Quick Reference
| User Says | Claude Does |
|---|---|
| [narrates observation] | Track comment, infer file/line from PR context (ask if unclear) |
| "blocking" / "nitpick" / etc. | Update severity of last comment |
| "show comments" | Display current comment list |
| "show analysis" | Show background agent findings (only when asked) |
| "drop last" | Remove last comment |
| "ready" / "done" | Move to Phase 3 (consolidation) |
| [after consolidation decisions] | Move to Phase 4 (write up comments) |
| "post it" / "looks good" | Move to Phase 5 (post to GitHub) |
Key Principles
- •Hold back AI findings until Phase 3 - let the user form their own opinions first
- •Low bar for asking clarification - better to ask "which file?" than guess wrong
- •Red team challenges user's comments - not the PR itself
- •Clarity over niceness - be friendly but don't bury the point
- •Line comments before summary - specifics first, then overview
- •Explicit approval required - never post without user confirmation
Done when: Review is posted to GitHub and link is shared with user.