Tutorials & Guides
How to Build a Local Git Diff Reviewer with Claude 3.5 Sonnet and Python
Stop writing tedious git commit messages and pull request descriptions by hand. Build a lightweight local script to automatically analyse your changes and summarise them using Claude.
Updated 10/12/2026
Why Write Commit Messages When Claude Can Do It Better?
Let’s be honest. Nobody actually enjoys writing pull request descriptions. We have all committed code with the message "fixes" or "various updates" because we simply could not face the prospect of manually comparing branch differences.
But bad commit hygiene makes your git history useless.
Instead of paying a monthly fee to some generic AI-assisted coding platform that wants to scan your entire repository and sell your data, you can build your own lightweight local tool. In this tutorial, we will construct a Python utility that grabs your current uncommitted changes, feeds them securely to Claude 3.5 Sonnet, and returns a perfectly formatted markdown summary.
By leveraging the API directly, we keep things local, cheap, and private. Let's look at how to make it tick.
Prerequisites
Before writing any code, you will need a few essentials installed on your machine:
- Python 3.9+
- Git (active in your target directory)
- An Anthropic API key with some credits loaded. If you are new to using this API, check out our guide on /platforms/claude to understand rate limits and developer setup.
Now, install the Anthropic Python SDK using pip:
`bash
pip install anthropic
`
Set your API key as an environment variable in your terminal:
`bash
export ANTHROPIC_API_KEY="your-api-key-here"
`
Step 1: Programmatically Fetching the Git Diff
Our first job is to extract the local modifications using Python’s standard subprocess library. We want to capture both staged and unstaged changes so we can review our progress before committing.
Create a new file called diff_reviewer.py and add this helper function:
`python
import subprocess
import sys
def get_git_diff() -> str:
try:
# Check if we are inside a git repository
subprocess.run(["git", "rev-parse", "--is-inside-work-tree"], check=True, capture_output=True)
# Get unstaged changes
unstaged = subprocess.run(["git", "diff"], capture_output=True, text=True).stdout
# Get staged changes
staged = subprocess.run(["git", "diff", "--staged"], capture_output=True, text=True).stdout
combined = unstaged + "\n" + staged
return combined.strip()
except subprocess.CalledProcessError:
print("Error: This directory is not a Git repository.")
sys.exit(1)
`
This function safely queries your current working directory. If you are not in a Git project, it gracefully exits rather than failing with a confusing stack trace.
Step 2: Designing the System Prompt
To get the best possible analysis from Claude 3.5 Sonnet, we must build a system prompt that enforces strict output constraints. We do not want conversational fluff like "Sure, here is your summary!" We want clean, bullet-pointed, technical updates.
We will structure our prompt on the /prompts principles: define the role, set context, provide explicit constraints, and demand structured markdown.
`python
SYSTEM_PROMPT = """
You are an expert senior software engineer conducting a peer review on local changes.
Your task is to review the git diff provided and produce a concise, professional markdown summary.
Structure your response exactly like this:
Summary of Changes - [A high-level summary of what was added, removed, or refactored]
Key Impact Areas - **[File Name]**: [Brief explanation of changes made to this specific file and potential risks]
Suggested Commit Message `[feat/fix/refactor]: [short imperative sentence]`
Keep your writing direct and clear. Avoid preambles, explanations, or introductory fluff. If you notice potential bugs or logical errors in the diff, add a small section at the bottom titled "### Code Quality Notes".
"""
`
Step 3: Sending the Diff to Claude 3.5 Sonnet
Now we tie our git diff utility to the Anthropic API. We will use the claude-3-5-sonnet-latest model to process the diff, as its reasoning capabilities are top-tier for understanding complex logic changes across multiple files.
`python
import os
from anthropic import Anthropic
def generate_review(diff_content: str): if not diff_content: print("No local changes detected. Git diff is empty.") return
print("Analysing your local changes with Claude...")
client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
try:
message = client.messages.create(
model="claude-3-5-sonnet-latest",
max_tokens=1500,
temperature=0.2, # Low temperature ensures consistent, logical reviews
system=SYSTEM_PROMPT,
messages=[
{
"role": "user",
"content": f"Please review the following git diff:\n\n{diff_content}"
}
]
)
print("\n--- CLAUDE'S REVIEW ---\n")
print(message.content[0].text)
print("\n-----------------------\n")
except Exception as e:
print(f"An error occurred during generation: {e}")
`
Step 4: Bringing It All Together
Add the execution block to your python script so it runs smoothly from the command line:
`python
if __name__ == "__main__":
# Ensure the API key is set before running
if not os.environ.get("ANTHROPIC_API_KEY"):
print("Error: ANTHROPIC_API_KEY environment variable is not set.")
sys.exit(1)
diff = get_git_diff()
generate_review(diff)
`
Save the file as diff_reviewer.py. Try editing a script in your workspace, staging it, and running our new tool:
`bash
python diff_reviewer.py
`
In seconds, you will receive a clean markdown write-up outlining your modifications, pointing out possible bugs, and handing you a clean commit message to copy-paste.
Optimising for Large Codebases
While Claude 3.5 Sonnet has a massive context window, pasting a massive git diff containing multi-megabyte database dumps or minified JavaScript builds will burn through your token limits quickly. To prevent this, exclude lockfiles and binary assets from your git diff queries by modifying the git command inside your script:
`python
# Exclude package-lock.json, poetry.lock, and other static assets from the diff
unstaged = subprocess.run(
["git", "diff", "--", ":!package-lock.json", ":!yarn.lock", ":!*poetry.lock"],
capture_output=True,
text=True
).stdout
`
If you run into issues with system paths, shell configurations, or API rate limiting, jump over to our dedicated troubleshooting resource at /platforms/claude/articles to get unstuck. Now go write some clean, annotated code without the manual documentation headache.
Keep going
Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.
Which AI should I use for this?
Tickd is independent and not affiliated with any AI company.