| name | github-code-review |
| description | Review code changes by analyzing git diffs, leaving inline comments on PRs, and performing thorough pre-push review. Works with gh CLI or falls back to git + GitHub REST API via curl. Trigger keywords: code review, pr review, review, review pr, leave inline comments, request changes, approve pr, review checklist. |
| license | MIT |
| metadata | {"version":"1.1.3","upstream_attribution":"Adapted and condensed from the Hermes Agent 'github-code-review' skill (Nous). Rewritten and self-contained by ngpestelos; republished under MIT.","hermes":{"tags":["GitHub","Code-Review","Pull-Requests","Git","Quality"],"related_skills":[]}} |
GitHub Code Review
Review local changes pre-push, or open PRs on GitHub. Most operations are pure git; the gh/curl split only matters for PR-level interactions. Output template at references/review-output-template.md.
Setup
The curl fallbacks below read $GITHUB_TOKEN, $GH_OWNER, $GH_REPO. Derive them from gh (pure-gh users can skip the exports — only the curl examples need them):
gh auth status
export GITHUB_TOKEN=$(gh auth token)
export GH_OWNER=$(gh repo view --json owner --jq .owner.login)
export GH_REPO=$(gh repo view --json name --jq .name)
No gh? Set GITHUB_TOKEN to a PAT and GH_OWNER/GH_REPO by hand.
1. Reviewing Local Changes (Pre-Push)
Pure git — no API needed.
Get the diff
git diff --staged
git diff main...HEAD
git diff main...HEAD --name-only
git diff main...HEAD --stat
git log main..HEAD --oneline
Common-issue scans
git diff main...HEAD | grep -n "print(\|console\.log\|TODO\|FIXME\|HACK\|XXX\|debugger"
git diff main...HEAD --stat | sort -t'|' -k2 -rn | head -10
git diff main...HEAD | grep -in "password\|secret\|api_key\|token.*=\|private_key"
git diff main...HEAD | grep -n "<<<<<<\|>>>>>>\|======="
Output structure
Use references/review-output-template.md — Critical / Warnings / Suggestions / Looks Good with path:line — issue + suggestion.
2. Reviewing a PR on GitHub
Get PR context
gh pr view 123
gh pr diff 123
gh pr diff 123 --name-only
gh pr checks 123
PR_NUMBER=123
curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER
curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER/files \
| python3 -c "
import sys, json
for f in json.load(sys.stdin):
print(f\"{f['status']:10} +{f['additions']:-4} -{f['deletions']:-4} {f['filename']}\")"
Check out PR locally
gh pr checkout 123
git fetch origin pull/123/head:pr-123 && git checkout pr-123
Run automated checks (if applicable)
python -m pytest 2>&1 | tail -20
ruff check . 2>&1 | head -30
Top-level PR comment
gh pr comment 123 --body "Overall looks good, a few suggestions below."
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$GH_OWNER/$GH_REPO/issues/$PR_NUMBER/comments \
-d '{"body": "..."}'
Single inline comment
HEAD_SHA=$(gh pr view 123 --json headRefOid --jq '.headRefOid')
gh api repos/$GH_OWNER/$GH_REPO/pulls/123/comments \
--method POST \
-f body="This could be simplified with a list comprehension." \
-f path="src/auth/login.py" \
-f commit_id="$HEAD_SHA" \
-F line=45 \
-f side="RIGHT"
side: RIGHT for new content, LEFT for deletions. line is the line number in the new file version — and must use -F (typed, integer), not -f (raw string): the API rejects a string line with a 422.
Formal review with multiple inline comments (atomic submission)
gh pr review 123 --approve --body "LGTM!"
gh pr review 123 --request-changes --body "See inline comments."
gh pr review 123 --comment --body "Some suggestions."
HEAD_SHA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER \
| python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])")
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER/reviews \
-d "{
\"commit_id\": \"$HEAD_SHA\",
\"event\": \"REQUEST_CHANGES\",
\"body\": \"## Summary\nFound 2 issues, 1 suggestion.\",
\"comments\": [
{\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"🔴 Critical: SQL injection — use parameterized queries.\"},
{\"path\": \"src/models.py\", \"line\": 23, \"body\": \"⚠️ Warning: hash passwords with bcrypt before storing.\"},
{\"path\": \"src/utils.py\", \"line\": 8, \"body\": \"💡 Suggestion: duplicates logic in core/utils.py:34.\"}
]
}"
Event values: APPROVE, REQUEST_CHANGES, COMMENT.
Decision: approve / request changes / comment
- Approve — no critical or warning issues; only minor suggestions or all clear
- Request Changes — any critical or warning issue blocking merge
- Comment — observations and suggestions, nothing blocking; use for drafts or when unsure
Cleanup after review
git checkout main
git branch -D pr-123
3. Review Checklist
Correctness
- Does the code do what it claims?
- Edge cases (empty inputs, nulls, concurrent access)?
- Error paths handled gracefully?
Security
- No hardcoded secrets, credentials, API keys
- Input validation on user-facing inputs
- No SQL injection, XSS, path traversal
- Auth/authz checks where needed
Code Quality
- Clear naming
- No premature abstraction
- DRY — no duplicated logic that should extract
- Single-responsibility functions
Testing
- New code paths tested
- Happy path + error cases covered
- Tests readable and maintainable
Performance
- No N+1 queries or unnecessary loops
- Caching where beneficial
- No blocking ops in async paths
Documentation
- Public APIs documented
- Non-obvious logic has "why" comments
- README updated if behavior changed
End-to-End PR Review Recipe
- Authenticate and set vars (Setup section), then gather PR context (Section 2:
gh pr view, file list, checks)
gh pr checkout N for full local access
- Read full diff against base; for each changed file, also
read_file for surrounding context
- Run automated checks if applicable
- Apply the checklist (Section 3)
- Submit a formal review with inline comments (atomic via
pulls/N/reviews)
- Optionally also leave a top-level summary comment using
references/review-output-template.md
- Cleanup:
git checkout main && git branch -D pr-N