github-code-review
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.
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.
Real data. Real impact.
Emerging
Developers
Per week
Excellent
Skills give you superpowers. Install in 30 seconds.
Perform code reviews on local changes before pushing, or review open PRs on GitHub. Most of this skill uses plain
git — the gh/curl split only matters for PR-level interactions.
github-auth skill)if command -v gh &>/dev/null && gh auth status &>/dev/null; then AUTH="gh" else AUTH="git" if [ -z "$GITHUB_TOKEN" ]; then if [ -f ~/.hermes/.env ] && grep -q "^GITHUB_TOKEN=" ~/.hermes/.env; then GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" ~/.hermes/.env | head -1 | cut -d= -f2 | tr -d '\n\r') elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\([^@]*\)@.*|\1|') fi fi fi REMOTE_URL=$(git remote get-url origin) OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||') OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1) REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)
This is pure
git — works everywhere, no API needed.
# Staged changes (what would be committed) git diff --staged # All changes vs main (what a PR would contain) git diff main...HEAD # File names only git diff main...HEAD --name-only # Stat summary (insertions/deletions per file) git diff main...HEAD --stat
git diff main...HEAD --stat git log main..HEAD --oneline
read_file on changed files for full context, and the diff to see what changed:git diff main...HEAD -- src/auth/login.py
# Debug statements, TODOs, console.logs left behind git diff main...HEAD | grep -n "print(\|console\.log\|TODO\|FIXME\|HACK\|XXX\|debugger" # Large files accidentally staged git diff main...HEAD --stat | sort -t'|' -k2 -rn | head -10 # Secrets or credential patterns git diff main...HEAD | grep -in "password\|secret\|api_key\|token.*=\|private_key" # Merge conflict markers git diff main...HEAD | grep -n "<<<<<<\|>>>>>>\|======="
When reviewing local changes, present findings in this structure:
## Code Review Summary ### Critical - **src/auth.py:45** — SQL injection: user input passed directly to query. Suggestion: Use parameterized queries. ### Warnings - **src/models/user.py:23** — Password stored in plaintext. Use bcrypt or argon2. - **src/api/routes.py:112** — No rate limiting on login endpoint. ### Suggestions - **src/utils/helpers.py:8** — Duplicates logic in `src/core/utils.py:34`. Consolidate. - **tests/test_auth.py** — Missing edge case: expired token test. ### Looks Good - Clean separation of concerns in the middleware layer - Good test coverage for the happy path
With gh:
gh pr view 123 gh pr diff 123 gh pr diff 123 --name-only
With git + curl:
PR_NUMBER=123 # Get PR details curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \ | python3 -c " import sys, json pr = json.load(sys.stdin) print(f\"Title: {pr['title']}\") print(f\"Author: {pr['user']['login']}\") print(f\"Branch: {pr['head']['ref']} -> {pr['base']['ref']}\") print(f\"State: {pr['state']}\") print(f\"Body:\n{pr['body']}\")" # List changed files curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$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']}\")"
This works with plain
git — no gh needed:
# Fetch the PR branch and check it out git fetch origin pull/123/head:pr-123 git checkout pr-123 # Now you can use read_file, search_files, run tests, etc. # View diff against the base branch git diff main...pr-123
With gh (shortcut):
gh pr checkout 123
General PR comment — with gh:
gh pr comment 123 --body "Overall looks good, a few suggestions below."
General PR comment — with curl:
curl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/$PR_NUMBER/comments \ -d '{"body": "Overall looks good, a few suggestions below."}'
Single inline comment — with gh (via API):
HEAD_SHA=$(gh pr view 123 --json headRefOid --jq '.headRefOid') gh api repos/$OWNER/$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"
Single inline comment — with curl:
# Get the head commit SHA HEAD_SHA=$(curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$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/$OWNER/$REPO/pulls/$PR_NUMBER/comments \ -d "{ \"body\": \"This could be simplified with a list comprehension.\", \"path\": \"src/auth/login.py\", \"commit_id\": \"$HEAD_SHA\", \"line\": 45, \"side\": \"RIGHT\" }"
With gh:
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, nothing blocking."
With curl — multi-comment review submitted atomically:
HEAD_SHA=$(curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$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/$OWNER/$REPO/pulls/$PR_NUMBER/reviews \ -d "{ \"commit_id\": \"$HEAD_SHA\", \"event\": \"COMMENT\", \"body\": \"Code review from Hermes Agent\", \"comments\": [ {\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"Use parameterized queries to prevent SQL injection.\"}, {\"path\": \"src/models/user.py\", \"line\": 23, \"body\": \"Hash passwords with bcrypt before storing.\"}, {\"path\": \"tests/test_auth.py\", \"line\": 1, \"body\": \"Add test for expired token edge case.\"} ] }"
Event values:
"APPROVE", "REQUEST_CHANGES", "COMMENT"
The
line field refers to the line number in the new version of the file. For deleted lines, use "side": "LEFT".
When performing a code review (local or PR), systematically check:
When the user asks you to "review the code" or "check before pushing":
git diff main...HEAD --stat — see scope of changesgit diff main...HEAD — read the full diffread_file if you need more contextWhen the user asks you to "review PR #N", "look at this PR", or gives you a PR URL, follow this recipe:
source "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/gh-env.sh" # Or run the inline setup block from the top of this skill
Get the PR metadata, description, and list of changed files to understand scope before diving into code.
With gh:
gh pr view 123 gh pr diff 123 --name-only gh pr checks 123
With curl:
PR_NUMBER=123 # PR details (title, author, description, branch) curl -s -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER # Changed files with line counts curl -s -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER/files
This gives you full access to
read_file, search_files, and the ability to run tests.
git fetch origin pull/$PR_NUMBER/head:pr-$PR_NUMBER git checkout pr-$PR_NUMBER
# Full diff against the base branch git diff main...HEAD # Or file-by-file for large PRs git diff main...HEAD --name-only # Then for each file: git diff main...HEAD -- path/to/file.py
For each changed file, use
read_file to see full context around the changes — diffs alone can miss issues visible only with surrounding code.
# Run tests if there's a test suite python -m pytest 2>&1 | tail -20 # or: npm test, cargo test, go test ./..., etc. # Run linter if configured ruff check . 2>&1 | head -30 # or: eslint, clippy, etc.
Go through each category: Correctness, Security, Code Quality, Testing, Performance, Documentation.
Collect your findings and submit them as a formal review with inline comments.
With gh:
# If no issues — approve gh pr review $PR_NUMBER --approve --body "Reviewed by Hermes Agent. Code looks clean — good test coverage, no security concerns." # If issues found — request changes with inline comments gh pr review $PR_NUMBER --request-changes --body "Found a few issues — see inline comments."
With curl — atomic review with multiple inline comments:
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'])") # Build the review JSON — event is APPROVE, REQUEST_CHANGES, or COMMENT 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\": \"## Hermes Agent Review\n\nFound 2 issues, 1 suggestion. See inline comments.\", \"comments\": [ {\"path\": \"src/auth.py\", \"line\": 45, \"body\": \"🔴 **Critical:** User input passed directly to SQL query — use parameterized queries.\"}, {\"path\": \"src/models.py\", \"line\": 23, \"body\": \"⚠️ **Warning:** Password stored without hashing.\"}, {\"path\": \"src/utils.py\", \"line\": 8, \"body\": \"💡 **Suggestion:** This duplicates logic in core/utils.py:34.\"} ] }"
In addition to inline comments, leave a top-level summary so the PR author gets the full picture at a glance. Use the review output format from
references/review-output-template.md.
With gh:
gh pr comment $PR_NUMBER --body "$(cat <<'EOF' ## Code Review Summary **Verdict: Changes Requested** (2 issues, 1 suggestion) ### 🔴 Critical - **src/auth.py:45** — SQL injection vulnerability ### ⚠️ Warnings - **src/models.py:23** — Plaintext password storage ### 💡 Suggestions - **src/utils.py:8** — Duplicated logic, consider consolidating ### ✅ Looks Good - Clean API design - Good error handling in the middleware layer --- *Reviewed by Hermes Agent* EOF )"
git checkout main git branch -D pr-$PR_NUMBER
MIT
mkdir -p ~/.hermes/skills/github/github-code-review && curl -o ~/.hermes/skills/github/github-code-review/SKILL.md https://raw.githubusercontent.com/NousResearch/hermes-agent/main/skills/github/github-code-review/SKILL.md1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.