Interactive wizard for reviewing AI-generated code changes by risk
Project description
git-sift
An interactive CLI wizard for reviewing AI-generated code changes, ordered from highest to lowest risk.
git-sift walks you through every changed file in a diff — categorising each one by risk, showing you exactly why it was flagged, and letting you approve, raise a concern, mark a blocker, or ask Claude Code to fix it. Once everything is approved it can merge the PR for you.
Why
AI-generated code changes can bury high-risk edits — a removed auth check, a bumped dependency, an altered migration — inside large diffs full of low-risk formatting changes. git-sift forces you to confront the riskiest files first, every time.
Installation
pip install git-sift
Or from source:
git clone https://github.com/eamonnfaherty/git-compare-tool
cd git-compare-tool
pip install -e .
Requires Python 3.11+.
Quick start
# In any git repository — compares current branch against main
git-sift
That's it. git-sift detects your branch, diffs it against main (or master), and opens the wizard.
Usage
# Default: current branch vs main
git-sift
# Staged changes only
git-sift --staged
# Unstaged working-tree changes
git-sift --unstaged
# Specific refs
git-sift --ref-a main --ref-b feature/my-branch
git-sift --ref-a v1.0.0 --ref-b v1.1.0
# Non-interactive CI mode — exit 1 if security or dependency changes are detected
git-sift --fail-on security,dependency
# Install the Claude Code /git-sift skill
git-sift --install-skill
Risk categories
Files are assigned the highest-risk (lowest number) category that matches. Both filename patterns and diff content are checked — content rules can escalate a file beyond its path-based category.
| Risk | Category | Triggers |
|---|---|---|
| 1 | Security | *auth*, *secret*, *.pem, *.key paths; removed auth checks; hardcoded secrets; eval/exec; unsafe deserialisation; unsafe yaml.load() |
| 2 | Dependencies | requirements*.txt, pyproject.toml, package.json, go.mod, Cargo.toml, etc.; version pin changes |
| 3 | Infrastructure | Dockerfile, CI/CD workflows, Terraform, Kubernetes, shell scripts |
| 4 | Database Migrations | migrations/, alembic/versions/, *.migration.sql |
| 5 | Architecture Tests | *arch*test*, tests/arch/ |
| 6 | Existing Tests | test_*.py, *.test.ts, __tests__/; removed asserts; deleted test functions; added skip/xfail |
| 7 | Existing Code | Modified source files; added # TODO/# FIXME/# HACK; raise NotImplementedError; pass or ... placeholders; commented-out code |
| 8 | New Code | Newly created files with no other classification |
| 9 | Config / Environment | .env, *.yaml, *.cfg, settings*.py, config/ |
| 10 | Docs & Formatting | *.md, *.rst, docs/, CHANGELOG, README |
Every matched rule adds a "Why this was flagged" reason shown above each file's diff so you always know what to look for before reading the code.
Interactive wizard
The wizard walks through files from risk 1 to 10, prompting for a decision on each:
| Key | Decision | Meaning |
|---|---|---|
A |
Approve | Looks correct |
C |
Concern | Worth noting but not a hard blocker |
B |
Blocker | Must be fixed before merge |
S |
Skip | Review later |
Q |
Quit | Exit the session |
? |
Help | Show this table |
After Concern or Blocker you are prompted for an optional note.
A compact status bar is pinned just above the prompt at the bottom of the screen, showing the file path, category, and risk level — so it is always visible regardless of diff length.
Interactive browser (second pass)
After the wizard completes its summary, an interactive file browser opens for a second pass:
| Key | Action |
|---|---|
A |
Approve this file |
R |
Recommend a change — launches a Claude Code session to fix it |
S |
Skip |
N / P |
Next / Previous file |
? |
Help |
Claude-assisted fixes
Pressing R on any file:
- Prompts you for a description of what needs to change
- Builds a structured prompt including the file path, risk category, the diff, and your recommendation
- Launches an interactive Claude Code session (
claude) in your terminal - When you exit Claude, the full wizard restarts with a fresh diff so the fix is reviewed from scratch
Every line Claude changes receives an inline # AI-REVIEW-FIX: <explanation> comment. Security fixes also get # AI-REVIEW-FIX(SECURITY): <vulnerability addressed>. This ensures AI-introduced changes are always visible to future reviewers.
Requires the claude CLI to be installed and on your PATH.
PR merge
Once all files are approved in the browser, git-sift offers to merge your open PR:
Merge this branch via PR? [Y/n]
Choose a merge strategy:
| Key | Strategy |
|---|---|
S |
Squash merge |
M |
Merge commit |
R |
Rebase |
C |
Cancel |
Requires the gh CLI and an open PR on the current branch. The branch is deleted after a successful merge.
Non-interactive / CI mode
git-sift --fail-on CATEGORIES
Runs the diff, categorises all files, prints a pass/fail summary, and exits with code 1 if any file matches a listed category. No prompts.
Category names (comma-separated, case-insensitive):
| Name(s) | Category |
|---|---|
security |
Security |
dependency, dependencies |
Dependencies |
infrastructure, infra |
Infrastructure |
database, migrations |
Database Migrations |
arch, arch-tests |
Architecture Tests |
tests, existing-tests |
Existing Tests |
code, existing-code |
Existing Code |
new, new-code |
New Code |
config, config-env, env |
Config / Environment |
docs, docs-formatting, formatting |
Docs & Formatting |
You can also use the numeric risk level directly (1–10).
# Fail on security or dependency changes (by name)
git-sift --fail-on security,dependency
# Same using risk levels
git-sift --fail-on 1,2
# Combine with a specific diff source
git-sift --staged --fail-on security
git-sift --ref-a main --ref-b HEAD --fail-on security,infrastructure,migrations
# In a CI pipeline
git-sift --fail-on security,dependency || exit 1
Exit codes:
| Code | Meaning |
|---|---|
0 |
No files matched the fail-on categories (or no diff) |
1 |
At least one file matched a fail-on category; or a blocker found in interactive mode |
2 |
Operational error (not in a git repo, git command failed) |
Claude Code skill
Install the /git-sift slash command into Claude Code:
git-sift --install-skill
This writes ~/.claude/commands/git-sift.md so you can type /git-sift inside any Claude Code session to run the wizard, interpret results, and get help addressing blockers.
Detected patterns for incomplete AI code
git-sift specifically watches for signs that an AI left work unfinished or disabled existing functionality:
- Added
# TODO,# FIXME,# HACK, or# XXXcomments - Added
raise NotImplementedError - Added a standalone
passor...(ellipsis placeholder) - Added comments containing words like
disabled,not implemented,placeholder,temporary,workaround,for now - Commented-out code: lines like
# return something(),# validate_input(data)
These appear as reasons in the "Why this was flagged" panel even when a higher-risk rule (like SECURITY) already governs the file's category.
Requirements
- Python 3.11+
- Git
claudeCLI — for Claude-assisted fixes (brew install claudeor see claude.ai/code)ghCLI — for PR merge (brew install gh)
License
Project details
Release history Release notifications | RSS feed
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 git_sift-0.1.0.tar.gz.
File metadata
- Download URL: git_sift-0.1.0.tar.gz
- Upload date:
- Size: 39.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb5e7c755b1ea11aecba0694d3a20d44d14f3afcb827cc9b6db0a24be8bd8a00
|
|
| MD5 |
8c49e660dcb812bd50faa81ff16e07d0
|
|
| BLAKE2b-256 |
a0ae6f2ac6960b3a62168f90eea76a898011e36d9fe2f92f5b6cb8ba0e51a7a3
|
Provenance
The following attestation bundles were made for git_sift-0.1.0.tar.gz:
Publisher:
workflow.yml on eamonnfaherty/git-sift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_sift-0.1.0.tar.gz -
Subject digest:
cb5e7c755b1ea11aecba0694d3a20d44d14f3afcb827cc9b6db0a24be8bd8a00 - Sigstore transparency entry: 1173972990
- Sigstore integration time:
-
Permalink:
eamonnfaherty/git-sift@61ee84f60deaa6b1bc8d05ea76ddee7233a0ee32 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/eamonnfaherty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@61ee84f60deaa6b1bc8d05ea76ddee7233a0ee32 -
Trigger Event:
release
-
Statement type:
File details
Details for the file git_sift-0.1.0-py3-none-any.whl.
File metadata
- Download URL: git_sift-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32017198cdd051610faaa584f3b25d96f36104a802ff42032ff43e0f1693ce14
|
|
| MD5 |
fa0229424a458e7245c039668cf102b7
|
|
| BLAKE2b-256 |
24f5c6031c8f27f45d49ac26c0d8e8f04cf939bd2775ad72101f3db107083e02
|
Provenance
The following attestation bundles were made for git_sift-0.1.0-py3-none-any.whl:
Publisher:
workflow.yml on eamonnfaherty/git-sift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
git_sift-0.1.0-py3-none-any.whl -
Subject digest:
32017198cdd051610faaa584f3b25d96f36104a802ff42032ff43e0f1693ce14 - Sigstore transparency entry: 1173973001
- Sigstore integration time:
-
Permalink:
eamonnfaherty/git-sift@61ee84f60deaa6b1bc8d05ea76ddee7233a0ee32 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/eamonnfaherty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
workflow.yml@61ee84f60deaa6b1bc8d05ea76ddee7233a0ee32 -
Trigger Event:
release
-
Statement type: