Metadata-Version: 2.4
Name: fresh-eyes
Version: 0.6.0
Summary: Independent AI peer review of git diffs for Claude Code and other coding agents
Project-URL: Homepage, https://github.com/lucasgerads/fresh-eyes
Project-URL: Source, https://github.com/lucasgerads/fresh-eyes
Project-URL: Issues, https://github.com/lucasgerads/fresh-eyes/issues
Author-email: Lucas Gerads <me@lucasgerads.com>
License: MIT License
        
        Copyright (c) 2026 Lucas Gerads
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ai,claude-code,code-review,git,peer-review
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Version Control :: Git
Requires-Python: >=3.11
Requires-Dist: openai>=1.40
Description-Content-Type: text/markdown

# 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

```bash
uv tool install fresh-eyes
```

Or from a local checkout:

```bash
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:

```bash
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:

```toml
[keys]
gemini  = "AIza..."
mistral = "..."
```

Environment variables still work and **take precedence** over the file — handy for CI or one-off experiments:

```bash
GEMINI_API_KEY=... fresh-eyes        # env wins over secrets.toml for this run
```

> Migrating from `~/.bashrc`? Run `fresh-eyes --set-key <reviewer>` for each key, then delete the `export …` 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:

```toml
[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` (default `true`) **and** a key is resolvable.
- `--only <gemini|mistral|deepseek>` runs a single reviewer, overriding `enabled` (it still needs a key).
- Model precedence: `FRESH_EYES_<NAME>_MODEL` env 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:

```bash
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:

```bash
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.

```bash
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:

```bash
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
