GitHub Code Review with Hermes Agent: Local Diffs, PRs, and Inline Comments
Review PRs: diffs, inline comments via gh or REST.
Written by Neura Market from the official Hermes Agent documentation for Github Code Review. Commands, paths, and version numbers are reproduced from the source unchanged.
Read the official documentationThe GitHub Code Review skill lets you review local changes before pushing and inspect open pull requests on GitHub. It uses plain git for local diffs and either the gh CLI or curl against the GitHub REST API for PR interactions. You would reach for this when you want an automated agent to audit code changes, catch common issues, and post structured feedback directly on a PR.
What it does
This skill gives Hermes Agent the ability to:
- Show staged or unstaged diffs against a base branch (typically
main). - List changed files, insertion/deletion counts, and commit summaries.
- Scan diffs for debug statements, TODO markers, secrets, and merge conflict markers.
- Fetch PR metadata, changed files, and the full diff from GitHub.
- Check out a PR branch locally for deeper inspection with
read_fileandsearch_files. - Leave general PR comments, inline review comments, and submit formal reviews (approve, request changes, or comment).
- Follow a structured review checklist covering correctness, security, code quality, testing, performance, and documentation.
- Present findings in a consistent format (Critical / Warnings / Suggestions / Looks Good).
Before you start
- You must be authenticated with GitHub. The
github-authskill handles this. The setup block at the top of this skill triesgh auth statusfirst; if that fails, it falls back toGITHUB_TOKENfrom the environment, from$HERMES_HOME/.env, or from~/.git-credentials. - You must be inside a git repository that has a remote named
originpointing to a GitHub URL. The skill parsesOWNERandREPOfrom that remote. - The skill works on Linux, macOS, and Windows.
- For PR interactions, you need either the
ghCLI installed and authenticated, or aGITHUB_TOKENwith appropriate repo scope.
Setup (for PR interactions)
if command -v gh &>/dev/null && gh auth status &>/dev/null; then
AUTH="gh"
else
AUTH="git"
if [ -z "$GITHUB_TOKEN" ]; then
if _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -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)
1. Reviewing Local Changes (Pre-Push)
This is pure git, works everywhere, no API needed.
Get the Diff
# 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
Review Strategy
- Get the big picture first:
git diff main...HEAD --stat
git log main..HEAD --oneline
- Review file by file, use
read_fileon changed files for full context, and the diff to see what changed:
git diff main...HEAD -- src/auth/login.py
- Check for common issues:
# 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 "<<<<<<\|>>>>>>\|======="
- Present structured feedback to the user.
Review Output Format
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
2. Reviewing a Pull Request on GitHub
View PR Details
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']}\")"
Check Out PR Locally for Full Review
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
Leave Comments on a PR
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."}'
Leave Inline Review Comments
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\"
}"
Submit a Formal Review (Approve / Request Changes)
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".
3. Review Checklist
When performing a code review (local or PR), systematically check:
Correctness
- Does the code do what it claims?
- Edge cases handled (empty inputs, nulls, large data, concurrent access)?
- Error paths handled gracefully?
Security
- No hardcoded secrets, credentials, or API keys
- Input validation on user-facing inputs
- No SQL injection, XSS, or path traversal
- Auth/authz checks where needed
Code Quality
- Clear naming (variables, functions, classes)
- No unnecessary complexity or premature abstraction
- DRY, no duplicated logic that should be extracted
- Functions are focused (single responsibility)
Testing
- New code paths tested?
- Happy path and error cases covered?
- Tests readable and maintainable?
Performance
- No N+1 queries or unnecessary loops
- Appropriate caching where beneficial
- No blocking operations in async code paths
Documentation
- Public APIs documented
- Non-obvious logic has comments explaining "why"
- README updated if behavior changed
4. Pre-Push Review Workflow
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 diff- For each changed file, use
read_fileif you need more context - Apply the checklist above
- Present findings in the structured format (Critical / Warnings / Suggestions / Looks Good)
- If critical issues found, offer to fix them before the user pushes
5. PR Review Workflow (End-to-End)
When the user asks you to "review PR #N", "look at this PR", or gives you a PR URL, follow this recipe:
Step 1: Set up environment
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
Step 2: Gather PR context
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
Step 3: Check out the PR locally
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
Step 4: Read the diff and understand changes
# 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.
Step 5: Run automated checks locally (if applicable)
# 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.
Step 6: Apply the review checklist (Section 3)
Go through each category: Correctness, Security, Code Quality, Testing, Performance, Documentation.
Step 7: Post the review to GitHub
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.\"}
]
}"
Step 8: Also post a summary comment
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
)"
Step 9: Clean up
git checkout main
git branch -D pr-$PR_NUMBER
Decision: Approve vs Request Changes vs Comment
- Approve, no critical or warning-level issues, only minor suggestions or all clear
- Request Changes, any critical or warning-level issue that should be fixed before merge
- Comment, observations and suggestions, but nothing blocking (use when you're unsure or the PR is a draft)
When not to use it
This skill is designed for reviewing code changes in a GitHub repository. It is not a substitute for a human code review that requires deep domain knowledge or architectural judgment. If the PR involves complex business logic, security-sensitive cryptographic code, or decisions that require product context, you should still involve a human reviewer. The skill also cannot run the application or verify runtime behavior beyond what tests and static analysis can show.
Limits and gotchas
- The
linefield in inline comments refers to the line number in the new version of the file. For deleted lines, you must set"side": "LEFT". - The skill relies on the
ghCLI or aGITHUB_TOKENwith appropriate permissions. If neither is configured, PR interactions will fail. - The setup block parses
OWNERandREPOfrom theoriginremote URL. If your remote uses a different name or format, you may need to adjust the parsing. - The pre-push review workflow assumes
mainas the base branch. If your project uses a different default branch, replacemainaccordingly. - The skill does not handle GitHub Enterprise instances out of the box; the API endpoint would need to be changed.
Related skills
- github-auth, handles authentication setup that this skill depends on.
- github-pr-workflow, a higher-level skill that may orchestrate PR creation, merging, and other operations alongside review.