From review-pr
Generate a guided PR review tour that walks through code changes in logical order. Creates a "street guide" with landmarks, context, and review priorities. Triggers: "review PR #123", "walk me through this PR", "PR tour guide", "explain this PR", "review and approve". Supports CLI display, PR comments, and human-style inline reviews. Can approve PRs with semantic messages.
How this skill is triggered — by the user, by Claude, or both
Slash command
/review-pr:review-prThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate a structured, guided tour of a Pull Request that helps reviewers understand changes efficiently. Acts as a knowledgeable guide walking someone through a codebase change.
Generate a structured, guided tour of a Pull Request that helps reviewers understand changes efficiently. Acts as a knowledgeable guide walking someone through a codebase change.
Claude will invoke this skill when you:
This skill creates a guided tour of PR changes that:
The skill needs:
Before starting the review, detect the operation context to determine default behavior:
CLI Mode Indicators (weight toward local display first):
Pass-Through/Delegated Mode Indicators (weight toward inline GitHub comments):
| Mode | Default Action | Rationale |
|---|---|---|
| CLI (interactive) | Display review locally first, then offer to post | User can review and edit before posting |
| Pass-through/Delegated | Post inline comments directly (if confident) | Automation context benefits from persistent comments |
If unsure about mode: Ask the user: "Would you like me to display the review here first, or post comments directly on the PR?"
# Get PR metadata
gh pr view <PR_NUMBER> --repo <OWNER/REPO> --json title,body,additions,deletions,changedFiles,files,commits
# Get the full diff
gh pr diff <PR_NUMBER> --repo <OWNER/REPO>
# If linked issue/ticket provided, fetch details based on tracker type:
# - GitHub Issues: gh issue view <ISSUE_NUMBER> --repo <OWNER/REPO>
# - Jira: Use mcp__atlassian__getJiraIssue or API
# - Linear: Use Linear MCP or API
# - Other trackers: Use appropriate MCP or API
Order files using depth-first traversal (folders before files):
Example ordering:
app/
models/
user.py # 1. Deepest nested first
account.py # 2. Same level, alphabetical
services/
auth.py # 3. Next subdirectory
utils.py # 4. Files in app/ after all subdirectories
config/
settings.py # 5. Next root subdirectory
main.py # 6. Root-level files last
Create a summary table:
| # | File | +/- | Purpose |
|---|------|-----|---------|
| 1 | `path/to/file1.py` | +50/-10 | Brief purpose |
| 2 | `path/to/file2.py` | +20/-5 | Brief purpose |
For each significant change, create a "tour stop" with:
### Stop N: [Descriptive Title] (Lines X-Y)
[Code snippet or reference]
**Context:** Why this code exists, what problem it solves
**Notice:** What the reviewer should observe about this change
**Review:**
- [Checkbox] Items that need careful review
- [Warning] Potential issues or risks
- [Check] Items that look good
Use these markers:
End with actionable review checklist:
## Summary Checklist
| Area | Status | Action |
|------|--------|--------|
| Core logic | [Status] | [Action needed] |
| Error handling | [Status] | [Action needed] |
| Tests | [Status] | [Action needed] |
# PR #[NUMBER] Review Tour Guide
## File Order (as shown in GitHub UI)
| # | File | +/- | Purpose |
|---|------|-----|---------|
| 1 | `file1.py` | +50 | Description |
---
## File 1: `path/to/file1.py`
**This is the [main/supporting] file. [Brief overview].**
---
### Stop 1: [Section Title] (Lines X-Y)
```python
# Relevant code snippet (abbreviated)
Context: [Why this exists]
Notice: [What to observe]
Review:
[Continue pattern...]
| Area | Status | Action |
|---|---|---|
| Item | Status | Action |
## Tour Stop Guidelines
### Grouping Rules
1. **One function/class per stop** - Don't mix unrelated changes
2. **Max ~25 lines of code** - Keep stops digestible
3. **Group related small changes** - Multiple one-liners can share a stop
4. **Separate concerns** - Config changes vs. logic changes vs. tests
### What to Call Out
**Always mention:**
- Breaking changes to public APIs
- Security-sensitive code (auth, crypto, user input)
- Database schema changes
- External service integrations
- Error handling patterns
- Performance implications
**Highlight patterns:**
- Code that duplicates existing functionality
- Missing error handling
- Hardcoded values that should be configurable
- Tests that don't actually test the change
### Context Sources
Provide context from:
- Linked issue/ticket description (GitHub Issues, Jira, Linear, etc.)
- PR description and commits
- Related code in the codebase
- Previous implementations being replaced
## Example Tour Stop
```markdown
### Stop 7: Row Processor - Column Count (Lines 802-830) - CRITICAL BUG FIX
```python
def _process_column_count_row(self, row: dict) -> dict:
table_rk = _get_snowflake_table_rk(
table, self.is_instance_default, self.instance_id
)
column_rk = _get_column_rk_from_table_rk(table_rk, column) if table_rk else None
# ^^^^^^^^^^^^^^^^^^^^^^
Context: This is the bug fix from commit a187cd4c. Previously, when table_rk was None, _get_column_rk_from_table_rk(None, column) would return "none/column_name" - a string that bypassed skip logic.
Review:
column_rk is None when table_rk is None
## Comparison with Linked Issue/Ticket
When a linked issue or ticket is provided (GitHub Issue, Jira, Linear, etc.):
### Step 1: Detect and Fetch Ticket Details
**GitHub Issues:**
```bash
gh issue view <ISSUE_NUMBER> --repo <OWNER/REPO> --json title,body,labels,assignees
Jira:
mcp__atlassian__getJiraIssueLinear:
Other Trackers:
### Issue vs. Implementation Comparison
| Requirement | Status | Notes |
|-------------|--------|-------|
| Item from issue | Implemented/Missing/Partial | Details |
The skill supports three modes, with defaults based on operation context and confidence:
1. Detect operation mode (CLI vs pass-through)
2. Assess confidence in review findings
3. Select mode based on:
- High confidence + Pass-through → Post inline comments directly
- High confidence + CLI → Display locally, offer to post
- Low confidence (any mode) → Display locally, discuss before posting
Display the tour guide in the Claude session. User reviews in terminal.
Use when:
Post inline comments directly on the PR using conventional comment labels.
Use when:
Leave # Reviewer Note comments on the PR to guide human reviewers through the UI.
Use when: Team collaboration, asynchronous review, onboarding reviewers.
High Confidence (post directly in pass-through mode):
Low Confidence (always discuss locally first):
The workflow varies based on confidence level and operation mode:
When running via delegation (OpenClaw, automation) AND confident in findings:
1. COMPLETE REVIEW
- Generate full tour guide (all files, all stops)
- Assess confidence in each finding
2. POST COMMENTS DIRECTLY
- Batch post all comments at once
- Verify each landed on correct line
- Report summary of posted comments
When confidence is low OR running interactively in CLI:
1. COMPLETE LOCAL REVIEW
- Generate full tour guide (all files, all stops)
- Identify all issues, suggestions, and considerations
- Compile into a summary for human review
2. PRESENT FINDINGS TO HUMAN
- Show summary of all proposed comments
- Include: file, line, label, message for each
- Flag any low-confidence items
- Ask: "Would you like me to post these as inline
comments on the PR?"
3. HUMAN APPROVAL
- Human reviews proposed comments
- Human may: approve all, modify some, reject some
- Human confirms which comments to post
4. BATCH POST APPROVED COMMENTS
- Post all approved comments at once
- Verify each landed on correct line
- Report back with links to posted comments
Why discuss first for low confidence:
# Get PR head commit SHA (required for comments)
gh pr view <PR_NUMBER> --json headRefOid --jq '.headRefOid'
# Save diff to temp file for analysis
gh pr diff <PR_NUMBER> > /tmp/pr_diff_<PR_NUMBER>.txt
Use these prefixes for professional code review comments:
| Label | Use Case | Example |
|---|---|---|
suggestion: | Improvements, refactoring ideas | "suggestion: Extract to shared constants file" |
thought: | Considerations, questions for discussion | "thought: Verify backend API compatibility" |
nit: | Minor style/formatting issues | "nit: Use Tailwind classes instead of inline styles" |
question: | Clarification needed | "question: Is this intentional behavior?" |
praise: | Good patterns worth noting | "praise: Nice use of early returns" |
issue: | Bugs or problems found | "issue: This will throw if array is empty" |
The GitHub API uses position (line number within the file's diff section), NOT the actual file line number.
Strategy:
Save diff to temp file:
gh pr diff <PR_NUMBER> > /tmp/pr_diff_<PR_NUMBER>.txt
Find where file starts in diff:
grep -n "^diff --git.*<filename>" /tmp/pr_diff_<PR_NUMBER>.txt
# Example: Returns "38:" meaning file diff starts at line 38
Find target line in diff:
grep -n "<search_pattern>" /tmp/pr_diff_<PR_NUMBER>.txt
# Example: Returns "81:" meaning target is at diff line 81
Calculate position:
position = target_diff_line - file_start_diff_line
# Example: position = 81 - 38 = 43
JSON payload approach (handles complex comment bodies):
cat > /tmp/review_comment.json << 'EOF'
{
"body": "**suggestion:** Consider extracting `PRODUCT_COLORS` to a shared constants file.\n\nThis configuration is duplicated in 4 files.",
"commit_id": "<HEAD_COMMIT_SHA>",
"path": "src/path/to/file.tsx",
"position": 43
}
EOF
gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/comments --input /tmp/review_comment.json
Verify comment placement:
# Check which line the comment landed on
gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/comments \
--jq '.[] | {file: .path, line: .line, body: .body[0:50]}'
For a file like api.ts with multiple hunks:
Diff structure:
Line 1: diff --git a/src/api.ts
Line 5: @@ -36,6 +36,8 @@ <- First hunk
Line 14: @@ -185,6 +187,14 @@ <- Second hunk
Line 29: @@ -602,6 +612,8 @@ <- Third hunk
Line 34: + sort_order?: string; <- Target line
Position for sort_order = 34 - 4 (header lines) = 30
# Delete duplicate/incorrect comments
gh api -X DELETE repos/<OWNER>/<REPO>/pulls/comments/<COMMENT_ID>
# List your comments to verify
gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/comments \
--jq '.[] | select(.user.login == "<YOUR_USERNAME>") | {id, file: .path, line: .line}'
When local files don't exist (PR not checked out), fetch from GitHub:
# Get PR branch name
BRANCH=$(gh pr view <PR_NUMBER> --json headRefName --jq '.headRefName')
# Fetch file content and find line numbers
gh api repos/<OWNER>/<REPO>/contents/<FILE_PATH>?ref=<BRANCH> \
--jq '.content' | base64 -d | grep -n "<SEARCH_PATTERN>"
This is useful for:
# 1. Get commit SHA
COMMIT=$(gh pr view 1999 --json headRefOid --jq '.headRefOid')
# 2. Save diff
gh pr diff 1999 > /tmp/pr_diff_1999.txt
# 3. Find position (example: PRODUCT_COLORS in DatabricksCostChartTooltip.tsx)
FILE_START=$(grep -n "^diff --git.*DatabricksCostChartTooltip" /tmp/pr_diff_1999.txt | cut -d: -f1)
TARGET=$(grep -n "PRODUCT_COLORS" /tmp/pr_diff_1999.txt | head -1 | cut -d: -f1)
POSITION=$((TARGET - FILE_START))
# 4. Post comment
cat > /tmp/comment.json << EOF
{
"body": "**suggestion:** This configuration is duplicated in 4 files. Consider extracting to shared constants.",
"commit_id": "$COMMIT",
"path": "src/pages/databricks/components/DatabricksCostChartTooltip.tsx",
"position": $POSITION
}
EOF
gh api repos/<OWNER>/<REPO>/pulls/1999/comments --input /tmp/comment.json
Comment lands on wrong line:
gh api -X DELETE repos/.../pulls/comments/<ID>"position" not found error:
Multiple hunks in file:
diff --git line, not from each @@ hunk headerWhen user requests "review and approve" or similar:
Do NOT automatically approve a PR. Even if the user says "review and approve", follow this workflow:
1. Complete review
↓
2. Any red flags found?
→ YES: Present concerns, do NOT approve, recommend changes
→ NO: Continue to step 3
↓
3. Assess risk level and correctness confidence
↓
4. Present to user:
"No red flags found. [Summary of changes].
Risk level: [low/medium/high]
My confidence: [high/medium/low]
Would you like me to approve? Please confirm your confidence level."
↓
5. User confirms confidence
↓
6. Approve with appropriate semantic message
Use these approval messages based on confidence level:
| Message | Meaning | When to Use |
|---|---|---|
| LGTM | Looks Good To Me | High confidence. Code is correct, well-written, follows best practices. Would approve without hesitation. |
| lgtm | looks good to me | Lower confidence/less emphatic. Code appears correct but haven't verified exhaustively. Quieter approval. |
| LFTM | Looks Fine To Me | High confidence shipping won't break anything. No major concerns, but not necessarily exceptional code. Pragmatic approval. |
| lftm | looks fine to me | Lower confidence. No red flags visible, but recommend user has fully tested and is confident before merging. |
Approve (LGTM/lgtm) when:
Approve (LFTM/lftm) when:
Do NOT approve when:
# Approve with comment
gh pr review <PR_NUMBER> --approve --body "LGTM - [brief summary of why]"
# Or with more detail
gh pr review <PR_NUMBER> --approve --body "$(cat <<'EOF'
LGTM
✓ Logic looks correct
✓ Tests cover the changes
✓ Follows existing patterns
Ship it!
EOF
)"
Version: 1.0.0
npx claudepluginhub jontsai/claude-plugins --plugin review-prReviews a pull request for code quality and correctness. Use when asked to review a PR or when running as an automated PR reviewer.
Reviews GitHub pull requests end-to-end using the gh CLI. Covers diff analysis, commit history, CI checks, and severity-leveled feedback submission.