feat: Initial agent-skills repo — 4 adapted skills for Mosaic Stack
Skills included: - pr-reviewer: Adapted for Gitea/GitHub via platform-aware scripts (dropped fetch_pr_data.py and add_inline_comment.py, kept generate_review_files.py) - code-review-excellence: Methodology and checklists (React, TS, Python, etc.) - vercel-react-best-practices: 57 rules for React/Next.js performance - tailwind-design-system: Tailwind CSS v4 patterns, CVA, design tokens New shell scripts added to ~/.claude/scripts/git/: - pr-diff.sh: Get PR diff (GitHub gh / Gitea API) - pr-metadata.sh: Get PR metadata as normalized JSON Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
368
skills/pr-reviewer/references/gh_cli_guide.md
Normal file
368
skills/pr-reviewer/references/gh_cli_guide.md
Normal file
@@ -0,0 +1,368 @@
|
||||
# GitHub CLI (gh) Guide for PR Reviews
|
||||
|
||||
This reference provides quick commands and patterns for accessing PR data using the GitHub CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install GitHub CLI: https://cli.github.com/
|
||||
|
||||
Authenticate:
|
||||
```bash
|
||||
gh auth login
|
||||
```
|
||||
|
||||
## Basic PR Information
|
||||
|
||||
### View PR Details
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo>
|
||||
|
||||
# With JSON output
|
||||
gh pr view <number> --repo <owner>/<repo> --json number,title,body,state,author,headRefName,baseRefName
|
||||
```
|
||||
|
||||
### View PR Diff
|
||||
```bash
|
||||
gh pr diff <number> --repo <owner>/<repo>
|
||||
|
||||
# Save to file
|
||||
gh pr diff <number> --repo <owner>/<repo> > pr_diff.patch
|
||||
```
|
||||
|
||||
### List PR Files
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo> --json files --jq '.files[].path'
|
||||
```
|
||||
|
||||
## PR Comments and Reviews
|
||||
|
||||
### Get PR Comments (Review Comments on Code)
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/comments
|
||||
|
||||
# Paginate through all comments
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/comments --paginate
|
||||
|
||||
# With JQ filtering
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/comments --jq '.[] | {path, line, body, user: .user.login}'
|
||||
```
|
||||
|
||||
### Get PR Reviews
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/reviews
|
||||
|
||||
# With formatted output
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/reviews --jq '.[] | {state, user: .user.login, body}'
|
||||
```
|
||||
|
||||
### Get Issue Comments (General PR Comments)
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/issues/<number>/comments
|
||||
```
|
||||
|
||||
## Commit Information
|
||||
|
||||
### List PR Commits
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/commits
|
||||
|
||||
# Get commit messages
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/commits --jq '.[] | {sha: .sha[0:7], message: .commit.message}'
|
||||
|
||||
# Get latest commit SHA
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/commits --jq '.[-1].sha'
|
||||
```
|
||||
|
||||
### Get Commit Details
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/commits/<sha>
|
||||
|
||||
# Get commit diff
|
||||
gh api /repos/<owner>/<repo>/commits/<sha> -H "Accept: application/vnd.github.diff"
|
||||
```
|
||||
|
||||
## Branches
|
||||
|
||||
### Get Branch Information
|
||||
```bash
|
||||
# Source branch (head)
|
||||
gh pr view <number> --repo <owner>/<repo> --json headRefName --jq '.headRefName'
|
||||
|
||||
# Target branch (base)
|
||||
gh pr view <number> --repo <owner>/<repo> --json baseRefName --jq '.baseRefName'
|
||||
```
|
||||
|
||||
### Compare Branches
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/compare/<base>...<head>
|
||||
|
||||
# Get files changed
|
||||
gh api /repos/<owner>/<repo>/compare/<base>...<head> --jq '.files[] | {filename, status, additions, deletions}'
|
||||
```
|
||||
|
||||
## Related Issues and Tickets
|
||||
|
||||
### Get Linked Issues
|
||||
```bash
|
||||
# Get PR body which may contain issue references
|
||||
gh pr view <number> --repo <owner>/<repo> --json body --jq '.body'
|
||||
|
||||
# Search for issue references (#123 format)
|
||||
gh pr view <number> --repo <owner>/<repo> --json body --jq '.body' | grep -oE '#[0-9]+'
|
||||
```
|
||||
|
||||
### Get Issue Details
|
||||
```bash
|
||||
gh issue view <number> --repo <owner>/<repo>
|
||||
|
||||
# JSON format
|
||||
gh issue view <number> --repo <owner>/<repo> --json number,title,body,state,labels,assignees
|
||||
```
|
||||
|
||||
### Get Issue Comments
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/issues/<number>/comments
|
||||
```
|
||||
|
||||
## PR Status Checks
|
||||
|
||||
### Get PR Status
|
||||
```bash
|
||||
gh pr checks <number> --repo <owner>/<repo>
|
||||
|
||||
# JSON format
|
||||
gh api /repos/<owner>/<repo>/commits/<sha>/status
|
||||
```
|
||||
|
||||
### Get Check Runs
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/commits/<sha>/check-runs
|
||||
```
|
||||
|
||||
## Adding Comments
|
||||
|
||||
### Add Inline Code Comment
|
||||
```bash
|
||||
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/comments \
|
||||
-f body="Your comment here" \
|
||||
-f commit_id="<sha>" \
|
||||
-f path="src/file.py" \
|
||||
-f side="RIGHT" \
|
||||
-f line=42
|
||||
```
|
||||
|
||||
### Add Multi-line Inline Comment
|
||||
```bash
|
||||
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/comments \
|
||||
-f body="Multi-line comment" \
|
||||
-f commit_id="<sha>" \
|
||||
-f path="src/file.py" \
|
||||
-f side="RIGHT" \
|
||||
-f start_line=40 \
|
||||
-f start_side="RIGHT" \
|
||||
-f line=45
|
||||
```
|
||||
|
||||
### Add General PR Comment
|
||||
```bash
|
||||
gh pr comment <number> --repo <owner>/<repo> --body "Your comment"
|
||||
|
||||
# Or via API
|
||||
gh api -X POST /repos/<owner>/<repo>/issues/<number>/comments \
|
||||
-f body="Your comment"
|
||||
```
|
||||
|
||||
## Creating a Review
|
||||
|
||||
### Create Review with Comments
|
||||
```bash
|
||||
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/reviews \
|
||||
-f body="Overall review comments" \
|
||||
-f event="COMMENT" \
|
||||
-f commit_id="<sha>" \
|
||||
-f comments='[{"path":"src/file.py","line":42,"body":"Comment on line 42"}]'
|
||||
```
|
||||
|
||||
### Submit Review (Approve/Request Changes)
|
||||
```bash
|
||||
# Approve
|
||||
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/reviews \
|
||||
-f body="LGTM!" \
|
||||
-f event="APPROVE" \
|
||||
-f commit_id="<sha>"
|
||||
|
||||
# Request changes
|
||||
gh api -X POST /repos/<owner>/<repo>/pulls/<number>/reviews \
|
||||
-f body="Please address these issues" \
|
||||
-f event="REQUEST_CHANGES" \
|
||||
-f commit_id="<sha>"
|
||||
```
|
||||
|
||||
## Searching and Filtering
|
||||
|
||||
### Search Code in PR
|
||||
```bash
|
||||
# Get PR diff and search
|
||||
gh pr diff <number> --repo <owner>/<repo> | grep "search_term"
|
||||
|
||||
# Search in specific files
|
||||
gh pr view <number> --repo <owner>/<repo> --json files --jq '.files[] | select(.path | contains("search_term"))'
|
||||
```
|
||||
|
||||
### Filter by File Type
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo> --json files --jq '.files[] | select(.path | endswith(".py"))'
|
||||
```
|
||||
|
||||
## Labels, Assignees, and Metadata
|
||||
|
||||
### Get Labels
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo> --json labels --jq '.labels[].name'
|
||||
```
|
||||
|
||||
### Get Assignees
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo> --json assignees --jq '.assignees[].login'
|
||||
```
|
||||
|
||||
### Get Reviewers
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo> --json reviewRequests --jq '.reviewRequests[].login'
|
||||
```
|
||||
|
||||
## Advanced Queries
|
||||
|
||||
### Get PR Timeline
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/issues/<number>/timeline
|
||||
```
|
||||
|
||||
### Get PR Events
|
||||
```bash
|
||||
gh api /repos/<owner>/<repo>/issues/<number>/events
|
||||
```
|
||||
|
||||
### Get All PR Data
|
||||
```bash
|
||||
gh pr view <number> --repo <owner>/<repo> --json \
|
||||
number,title,body,state,author,headRefName,baseRefName,\
|
||||
commits,reviews,comments,files,labels,assignees,milestone,\
|
||||
createdAt,updatedAt,mergedAt,closedAt,url,isDraft
|
||||
```
|
||||
|
||||
## Common JQ Patterns
|
||||
|
||||
### Extract specific fields
|
||||
```bash
|
||||
--jq '.field'
|
||||
--jq '.array[].field'
|
||||
--jq '.[] | {field1, field2}'
|
||||
```
|
||||
|
||||
### Filter arrays
|
||||
```bash
|
||||
--jq '.[] | select(.field == "value")'
|
||||
--jq '.[] | select(.field | contains("substring"))'
|
||||
```
|
||||
|
||||
### Count items
|
||||
```bash
|
||||
--jq '. | length'
|
||||
--jq '.array | length'
|
||||
```
|
||||
|
||||
### Map and transform
|
||||
```bash
|
||||
--jq '.array | map(.field)'
|
||||
--jq '.[] | {newField: .oldField}'
|
||||
```
|
||||
|
||||
## Line Number Considerations for Inline Comments
|
||||
|
||||
**IMPORTANT**: The `line` parameter for inline comments refers to the **line number in the diff**, not the absolute line number in the file.
|
||||
|
||||
### Understanding Diff Line Numbers
|
||||
|
||||
In a diff:
|
||||
- Lines are numbered relative to the diff context, not the file
|
||||
- The `side` parameter determines which version:
|
||||
- `"RIGHT"`: New version (after changes)
|
||||
- `"LEFT"`: Old version (before changes)
|
||||
|
||||
### Finding Diff Line Numbers
|
||||
|
||||
```bash
|
||||
# Get diff with line numbers
|
||||
gh pr diff <number> --repo <owner>/<repo> | cat -n
|
||||
|
||||
# Get specific file diff
|
||||
gh api /repos/<owner>/<repo>/pulls/<number>/files --jq '.[] | select(.filename == "path/to/file")'
|
||||
```
|
||||
|
||||
### Example Diff
|
||||
```diff
|
||||
@@ -10,7 +10,8 @@ def process_data(data):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
- result = old_function(data)
|
||||
+ # New implementation
|
||||
+ result = new_function(data)
|
||||
return result
|
||||
```
|
||||
|
||||
In this diff:
|
||||
- Line 13 (old) would be `side: "LEFT"`
|
||||
- Line 14-15 (new) would be `side: "RIGHT"`
|
||||
- Line numbers are relative to the diff hunk starting at line 10
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
|
||||
**Resource not found**:
|
||||
```bash
|
||||
# Check repo access
|
||||
gh repo view <owner>/<repo>
|
||||
|
||||
# Check PR exists
|
||||
gh pr list --repo <owner>/<repo> | grep <number>
|
||||
```
|
||||
|
||||
**API rate limit**:
|
||||
```bash
|
||||
# Check rate limit
|
||||
gh api /rate_limit
|
||||
|
||||
# Use authentication to get higher limits
|
||||
gh auth login
|
||||
```
|
||||
|
||||
**Permission denied**:
|
||||
```bash
|
||||
# Check authentication
|
||||
gh auth status
|
||||
|
||||
# May need additional scopes
|
||||
gh auth refresh -s repo
|
||||
```
|
||||
|
||||
## Tips and Best Practices
|
||||
|
||||
1. **Use `--paginate`** for large result sets (comments, commits)
|
||||
2. **Combine with `jq`** for powerful filtering and formatting
|
||||
3. **Cache results** by saving to files to avoid repeated API calls
|
||||
4. **Check rate limits** when making many API calls
|
||||
5. **Use `--json` output** for programmatic parsing
|
||||
6. **Specify `--repo`** when outside repository directory
|
||||
7. **Get latest commit** before adding inline comments
|
||||
8. **Test comments** on draft PRs or test repositories first
|
||||
|
||||
## Reference Links
|
||||
|
||||
- GitHub CLI Manual: https://cli.github.com/manual/
|
||||
- GitHub REST API: https://docs.github.com/en/rest
|
||||
- JQ Manual: https://jqlang.github.io/jq/manual/
|
||||
- PR Review Comments API: https://docs.github.com/en/rest/pulls/comments
|
||||
- PR Reviews API: https://docs.github.com/en/rest/pulls/reviews
|
||||
Reference in New Issue
Block a user