Friday, 6:47 PM. You push a branch, open a PR, and get back to your coffee. Monday morning, your reviewer comments: "What if data
is null?" You know that feeling. The one where you wish a second pair of eyes existed, one that never sleeps and never gets annoyed.
That second pair of eyes is now free. MonkeyCode, an open-source project, ships with free model access and a free server option. Disclosure: This article was prepared as part of MonkeyCode's product outreach. You can wire it into your workflow in about twenty minutes. Here's the exact path.
A GitHub Action that runs on every pull request. It calls the MonkeyCode API, sends your diff, and posts a review comment with potential issues. No more "did you handle null?" from humans. The machine handles the obvious stuff first.
Head to the MonkeyCode repo and read the README. The setup changes, so trust the README over this article. You'll need an API key or a CLI login. For this guide, I'll assume you have a key.
Create a file called review.py
. It reads the diff from stdin, sends it to the API, and prints the review.
#!/usr/bin/env python3
import json
import os
import sys
import urllib.request
API_URL = os.environ.get("MONKEYCODE_API_URL", "https://api.monkeycode.example/v1/review")
API_KEY = os.environ.get("MONKEYCODE_API_KEY")
def read_diff():
return sys.stdin.read()
def send_review(diff):
payload = json.dumps({
"diff": diff,
"language": "python",
"instructions": "Review this diff for bugs, edge cases, and style issues. Be concise."
}).encode()
req = urllib.request.Request(API_URL, data=payload, headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
})
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read())
def main():
diff = read_diff()
if not diff.strip():
print("No diff to review.")
return
result = send_review(diff)
print(result.get("review", "No review returned."))
if __name__ == "__main__":
main()
Note: The API endpoint and request format are placeholders. Check the current docs for the real shape. The principle stays: send a diff, get a review.
Create .github/workflows/review.yml
:
name: AI Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get diff
run: git diff origin/${{ github.event.pull_request.base.ref }}...HEAD > /tmp/diff.txt
- name: Run review
env:
MONKEYCODE_API_KEY: ${{ secrets.MONKEYCODE_API_KEY }}
run: |
python review.py < /tmp/diff.txt > /tmp/review.txt
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('/tmp/review.txt', 'utf8');
if (body.trim()) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## AI Review\n\n${body}`
});
}
Now every PR gets a comment from your new reviewer. It's not perfect, but it catches the "you forgot null" class of bugs before a human has to.
The real power is in the instructions. Change the prompt to match your team's standards. For example:
TODO
or FIXME
comments."The free server has limits. It's shared capacity, so expect occasional latency. It's not for confidential code. And the model isn't a senior engineer. It's a fast, tireless junior who reads every line.
If your codebase is proprietary or regulated, don't send it to a free server. If your PRs are huge, the diff will exceed context limits. If you need deterministic behavior, a free tier won't give you that. For everyone else, this is a twenty-minute investment that pays off in fewer "did you handle null?" comments.
Free AI access isn't just about saving money. It's about removing the friction between you and a second opinion. The setup above is a starting point. Once you see it work, you'll think of a dozen more ways to use it.
Try it on your next PR. Your future self will thank you.