关于 github-pr-review
用于通过 GitHub API 发布结构化 Pull Request 评审及行内评论的技能。它将反馈合并为一次评审,并指导如何准确指定代码行和修改建议。
主要功能
- 01通过 GitHub API 发布评审
- 02将评论合并为一次评审
- 03在差异行添加行内评论
- 04支持建议代码块
- 05提供 Windows PowerShell 替代方法
适用场景
- 01提交 Pull Request 评审
- 02针对具体变更行发表评论
- 03提出小型代码修改建议
- 04通过 Windows PowerShell 发布评审
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ openhands/ extensions --skill github-pr-review安装后在 Claude Code 中输入/github-pr-review确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.plugin/plugin.jsoncommands/github-pr-review.mdreferences/windows.md详细介绍
GitHub PR 评审
使用 GitHub API 发布结构化代码评审反馈,并在特定行添加内联评论。
在 references/windows.md 中提供了用于创建 JSON 文件、设置临时路径、查找行号和回退使用 curl 的 Windows PowerShell 等效方法。
核心规则:只调用一次 API
将所有评论打包到单个评审 API 调用中。不要逐条发布评论。
发布评审
使用 GitHub CLI(gh)和 JSON 输入文件。GITHUB_TOKEN 会自动提供。
重要:始终使用 --input 和 JSON 文件,而不要使用 -F 标志。这样可以避免评论正文中的特殊字符(引号、反引号、换行符等)带来的 shell 引号问题,也无需编写复杂的 heredoc 脚本。
步骤 1:创建 JSON 文件
cat > /tmp/review.json << 'EOF'
{
"commit_id": "{commit_sha}",
"event": "COMMENT",
"body": "Brief 1-3 sentence summary.",
"comments": [
{
"path": "path/to/file.py",
"line": 42,
"side": "RIGHT",
"body": "🟠 Important: Your comment here."
},
{
"path": "another/file.js",
"line": 15,
"side": "RIGHT",
"body": "🟡 Suggestion: Another comment."
}
]
}
EOF
步骤 2:发布评审
gh api -X POST repos/{owner}/{repo}/pulls/{pr_number}/reviews --input /tmp/review.json
参数
| 参数 | 描述 |
|---|---|
commit_id | 要评论的提交 SHA(使用 git rev-parse HEAD) |
event | APPROVE、COMMENT 或 REQUEST_CHANGES(见下文) |
path | diff 中显示的文件路径 |
line | 新版本中的行号(diff 右侧) |
side | 新增行使用 RIGHT,删除行使用 LEFT |
body | 带有优先级标签的评论文本 |
选择 event 值
| Event | 使用时机 |
|---|---|
APPROVE | 未发现问题,或仅有不阻碍合并的 🟡 建议 |
COMMENT | 有 🟠 重要反馈,但并非必须解决的阻碍问题 |
REQUEST_CHANGES | 存在 🔴 严重问题,必须在合并前修复 |
当代码正确且已达到可合并状态时,默认使用 APPROVE。只有存在值得提出的可操作问题时,才使用 COMMENT 或 REQUEST_CHANGES。
多行评论
对于跨越多行的评论,添加 start_line 以指定范围:
{
"path": "path/to/file.py",
"start_line": 10,
"line": 12,
"side": "RIGHT",
"body": "🟡 Suggestion: Refactor this block:\n\n```suggestion\nline_one = \"new\"\nline_two = \"code\"\nline_three = \"here\"\n```"
}
start_line/line 定义将被替换的范围。 建议块可以包含任意行数——无需与范围的行数相同。确切语义见下一节;弄错后,建议可能会悄无声息地删除或重复代码。
优先级标签
每条评论都以优先级标签开头。尽量减少琐碎评论——细微的风格问题留给代码检查工具处理。
| 标签 | 使用时机 |
|---|---|
| 🔴 严重 | 必须修复:安全漏洞、缺陷、数据丢失风险 |
| 🟠 重要 | 应当修复:逻辑错误、性能问题、缺少错误处理 |
| 🟡 建议 | 值得考虑:对清晰度或可维护性的显著改进 |
不要发布 🟢 琐碎问题或 🟢 可接受的评论。 如果代码没有问题,就不要发表评论。写着“这看起来不错”或“这是可以接受的权衡”的内联评论只是噪声——它们会产生必须处理、却没有提供可操作价值的评审讨论。
示例:
🟠 Important: This function doesn't handle None, which could cause an AttributeError.
```suggestion
if user is None:
raise ValueError("User cannot be None")
## GitHub Suggestions
For small code changes, use the suggestion syntax for one-click apply:
~~~
```suggestion
improved_code_here()
Use suggestions for: renaming, typos, small refactors (1-5 lines), type hints, docstrings.
Avoid for: large refactors, architectural changes, ambiguous improvements.
### How Suggestions Actually Work (READ THIS BEFORE WRITING ONE)
A suggestion block **replaces** the targeted range with its contents. The replaced range is:
- `line` only → the single line `line` (replaces 1 line)
- `start_line` + `line` → the inclusive range `start_line..line` (replaces `line - start_line + 1` lines)
The suggestion content can be **any number of lines** — 0 (deletion), 1, or many. It does not have to match the range size. Whatever is between the ` ```suggestion ` and closing ` ``` ` fences becomes the new content of those lines.
Writing the wrong combination of `start_line`/`line` and suggestion body is what causes accepted suggestions to **duplicate** or **delete** code. Use the table below as your contract:
| Intent | `start_line` | `line` | Suggestion body must contain |
|--------|--------------|--------|-------------------------------|
| Change line N | omit | N | the new content for line N |
| Change lines N..M | N | M | the new content for the whole block |
| **Add** a line **after** line N (keep line N) | omit | N | line N's exact current text, then the new line(s) |
| **Add** a line **before** line N (keep line N) | omit | N | the new line(s), then line N's exact current text |
| **Insert** lines inside range N..M (keep N..M) | N | M | every original line in N..M plus the new lines, in the final desired order |
| **Delete** line N | omit | N | empty body (just an empty ` ```suggestion ``` ` block) |
| **Delete** lines N..M | N | M | empty body |
### Common Mistakes That Break Code
1. **Duplicated lines.** You copy a neighboring line (N-1 or N+1) into the suggestion body as context — that line is still present in the file outside the replaced range, so accepting the suggestion inserts a second copy of it. Fix: only include lines that fall within the targeted range, plus any genuinely new content.
2. **Disappearing lines.** You target `start_line=10, line=12` to comment on a 3-line block, but your suggestion body only contains 1 line because you "only want to change line 11". Accepting that suggestion deletes lines 10 and 12. Fix: either narrow the range to just line 11, or include lines 10 and 12 verbatim in the body.
3. **Description does not match the suggestion.** The prose says "rename this variable" but the suggestion replaces an entire function. Or the prose says "add a None check" but the suggestion only contains the check (deleting the original code). Fix: after writing the suggestion, re-read the prose and confirm the resulting file would match it line-for-line.
### Mandatory Verification Before Posting
For every comment that contains a ` ```suggestion ``` ` block, do this check before adding it to the review JSON:
1. Read the actual file lines that will be replaced: `sed -n '<start_line>,<line>p' <path>` (or `sed -n '<line>p' <path>` for a single-line target).
2. Mentally apply the suggestion: drop those lines, splice in the suggestion body, and look at the result in context.
3. Confirm the resulting code matches **exactly** what your prose description promises — no extra duplicated line above/below, no original line accidentally dropped, no off-by-one.
4. If the change cannot be expressed cleanly as a contiguous replacement (e.g., it touches non-adjacent lines, or it depends on edits elsewhere in the file), do **not** use a suggestion block — describe the change in prose instead.
If you are not 100% sure the suggestion will produce the exact code you described, drop the ` ```suggestion ``` ` block and leave a regular inline comment. A correct prose comment is always better than a one-click suggestion that silently corrupts the file.
## Finding Line Numbers
```bash
# From diff header: @@ -old_start,old_count +new_start,new_count @@
# Count from new_start for added/modified lines
grep -n "pattern" filename # Find line number
head -n 42 filename | tail -1 # Verify line content
```
## Fallback: curl
If `gh` is unavailable, use curl with the JSON file:
```bash
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}/reviews" \
-d @/tmp/review.json
```
## Summary
1. Analyze the code and identify important issues (minimize nits)
2. Write review data to a JSON file (e.g., `/tmp/review.json`)
3. Post **ONE** review using `gh api --input /tmp/review.json`
4. Use priority labels (🔴🟠🟡) on every comment
5. Do NOT post comments for code that is acceptable — only comment when action is needed
6. Use suggestion syntax for concrete code changes, but only after verifying the resulting code matches your description (see "How Suggestions Actually Work")
7. Keep the review body brief (details go in inline comments)
8. If no issues: use `"event": "APPROVE"` with a short approval message and no inline comments