Independent AI peer review of git diffs for Claude Code and other coding agents
Project description
fresh-eyes
Independent AI peer review of git diffs, designed for use alongside Claude Code (or any coding agent). Sends your latest changes to a different model so you get a second opinion with different blind spots from the one that wrote the code.
Install
uv tool install fresh-eyes
Or from a local checkout:
uv tool install --from . fresh-eyes
This installs two equivalent commands: fresh-eyes (canonical) and fe (typeable alias).
Setup
fresh-eyes calls three independent reviewers (Gemini, Mistral, DeepSeek). You need at least one API key; the tool runs whichever reviewers have a key it can resolve.
| Reviewer | Sign up | Cost |
|---|---|---|
| Gemini | https://aistudio.google.com/apikey | free tier |
| Mistral | https://console.mistral.ai | free experiment tier / paid |
| DeepSeek | https://platform.deepseek.com | paid |
Storing keys
Store each key once in ~/.config/fresh-eyes/secrets.toml, written at mode 600 so it isn't group/world-readable:
fresh-eyes --set-key gemini # prompts for the key (input hidden), writes secrets.toml
fresh-eyes --set-key mistral
The file looks like this. You can hand-edit it instead — but then you must chmod 600 it yourself, or fresh-eyes refuses to read it:
[keys]
gemini = "AIza..."
mistral = "..."
Environment variables still work and take precedence over the file — handy for CI or one-off experiments:
GEMINI_API_KEY=... fresh-eyes # env wins over secrets.toml for this run
Migrating from
~/.bashrc? Runfresh-eyes --set-key <reviewer>for each key, then delete theexport …lines from your shell profile.
Choosing models and reviewers
Create ~/.config/fresh-eyes/config.toml to override per reviewer — useful for swapping a noisy model or benching one entirely, without touching your keys:
[reviewers.mistral]
enabled = false # skip Mistral in the default run
model = "mistral-large-latest" # used if/when it runs (e.g. via --only mistral)
[reviewers.gemini]
model = "gemini-2.5-flash"
- A reviewer runs in the default (no-flag) invocation when it's
enabled(defaulttrue) and a key is resolvable. --only <gemini|mistral|deepseek>runs a single reviewer, overridingenabled(it still needs a key).- Model precedence:
FRESH_EYES_<NAME>_MODELenv var >config.toml> the built-in default.
Activation
fresh-eyes is opt-in per repo, so it doesn't fire in every git repo you cd into. Enable it once per repo:
fresh-eyes --init # enables fresh-eyes in this repo (writes .git/fresh_eyes_enabled)
fresh-eyes --disable # disables it again
Running any other command in a non-activated repo prints a friendly message and exits without making API calls.
Usage
From inside an activated git repository:
fresh-eyes # review the last commit (HEAD~1..HEAD)
fresh-eyes --since HEAD~3 # review the last 3 commits
fresh-eyes --since abc1234 # review since a specific commit
fresh-eyes --since main # review everything on this branch since it diverged from main
fresh-eyes --full # shortcut: diff entire branch against the default branch
fresh-eyes --all # one-time baseline: review the entire current codebase
fresh-eyes --staged # review staged-but-uncommitted changes
fe is the short alias — fe --since HEAD~3 works identically.
--since accepts anything git rev-parse resolves: SHAs, branch names, tags, HEAD~N. This is how Claude Code can scope a review around the actual unit of work rather than a fixed window.
Adding intent and trimming context
By default the reviewer sees the diff hunks and the full post-change content of every changed file, so it can see callers, types, and surrounding code without hallucinating about what's outside the hunk. What it does not know is what the change is supposed to do — pass --context for that.
fresh-eyes --context "Adds rate limiting to the /login endpoint. Should reject >5 req/min per IP."
fresh-eyes --context-file SPEC.md # read intent from a file (relative to CWD)
fresh-eyes --diff-only # send only diff hunks, skip full files (trim tokens)
fresh-eyes --since HEAD~3 --context "Refactors auth to use the new token store"
Use --context to tell the reviewer the author's stated goal — the prompt asks it to use this for grading "does the diff do what the author claims?" while still surfacing out-of-scope issues. Use --diff-only to drop the full-file attachments when you know the diff is self-contained or the changed files are very large (cuts token cost on paid providers).
Claude Code integration
Copy the slash command files from this repo into your Claude Code commands directory:
cp commands/fresh-eyes.md commands/fe.md ~/.claude/commands/
You can now invoke /fresh-eyes or /fe in a Claude Code session. The command tells Claude to run the CLI (forwarding flags like --since HEAD~3 when the request implies a specific baseline), read its output, synthesize the findings against the current task context, and raise genuine concerns before continuing.
How it works
- Stateless: every invocation is explicit about scope. Default is the last commit; pass
--since <commit>for anything else. No review-history markers, no hidden state about previous runs. - Independent reviewers in parallel: each enabled reviewer is called concurrently and its output is emitted verbatim under a
## <Model>header. The tool does not synthesize — that's left to the calling agent (Claude Code), which weighs the findings against the live task context. One reviewer failing (bad key, API error) is isolated to its own section; the others still complete. - Noise filtering: lockfiles, minified assets, and
dist//build/are excluded from the diff so they don't burn tokens. - Size guard: bails out with a message (exit
0) if the assembled prompt (diff + optional intent + optional full files) exceeds ~100k estimated tokens.
Exit codes
| Code | Meaning |
|---|---|
0 |
Review ran successfully, OR diff was too large to send (the tool reports; it does not gate) |
1 |
--since commit not found, or other git error |
2 |
No resolvable API key for the selected reviewer(s), or secrets.toml has insecure (non-600) permissions |
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fresh_eyes-0.6.0.tar.gz.
File metadata
- Download URL: fresh_eyes-0.6.0.tar.gz
- Upload date:
- Size: 53.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
763931afd17e9b4658f6c38bb91b22634c12cad3affb2135f56d0e0f6c14e7bb
|
|
| MD5 |
79066a59db80d101bd74e98269d0c8db
|
|
| BLAKE2b-256 |
e39d30816add4d01e4f5dbff1bd05a498adf8b6157d481b596e3dc594a84edbf
|
Provenance
The following attestation bundles were made for fresh_eyes-0.6.0.tar.gz:
Publisher:
release.yml on lucasgerads/fresh-eyes
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fresh_eyes-0.6.0.tar.gz -
Subject digest:
763931afd17e9b4658f6c38bb91b22634c12cad3affb2135f56d0e0f6c14e7bb - Sigstore transparency entry: 1711393611
- Sigstore integration time:
-
Permalink:
lucasgerads/fresh-eyes@7d1077d684a12f4ffe63c49fbca6a1ba749658ef -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lucasgerads
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d1077d684a12f4ffe63c49fbca6a1ba749658ef -
Trigger Event:
push
-
Statement type:
File details
Details for the file fresh_eyes-0.6.0-py3-none-any.whl.
File metadata
- Download URL: fresh_eyes-0.6.0-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6e46b934ad9888964c7d4f46c4bea8b35b66c1cae974e5d1077d67cef2860661
|
|
| MD5 |
2e3fe74c03f0f06f846bf3ffa0fdf3fb
|
|
| BLAKE2b-256 |
71343ccd95c30e9e7057f01ffd212c69495bd2b4c7ed6d439a3a3342759485dd
|
Provenance
The following attestation bundles were made for fresh_eyes-0.6.0-py3-none-any.whl:
Publisher:
release.yml on lucasgerads/fresh-eyes
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fresh_eyes-0.6.0-py3-none-any.whl -
Subject digest:
6e46b934ad9888964c7d4f46c4bea8b35b66c1cae974e5d1077d67cef2860661 - Sigstore transparency entry: 1711393840
- Sigstore integration time:
-
Permalink:
lucasgerads/fresh-eyes@7d1077d684a12f4ffe63c49fbca6a1ba749658ef -
Branch / Tag:
refs/heads/main - Owner: https://github.com/lucasgerads
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d1077d684a12f4ffe63c49fbca6a1ba749658ef -
Trigger Event:
push
-
Statement type: