KilimcininKorOglu/claude-code-mods/tree/main/plugins/gemini-review
gemini-review
Bash 도구에 훅을 걸어 모델이 수행하는 모든 git commit을 Gemini가 검토하게 합니다. 스테이징된 diff와 대화를 바탕으로 버그·데이터 손실·보안 문제·커밋된 비밀을 차단합니다.
이 mod 소개
gemini-review는 git commit이 포함된 명령을 실행하기 전에 Gemini 검토를 수행합니다. cd, git -C, git add, commit -a/-u/-A, 경로 지정 커밋, heredoc, --dry-run/--help를 파싱하고 읽기 전용 Git 호출로 index, 스테이징 경로와 최대 200개 신규 파일을 수집합니다. diff와 전체 대화를 generateContent로 보내 blocker/minor 구조화 결과를 받습니다. blocker는 커밋을 중단하고 수정 또는 GEMINI_REVIEW_SKIP=1을 요구합니다. 검토할 수 없으면 커밋은 실행하고 이유를 보고합니다. gemini-core가 필요하며 /gemini-review on 전에는 꺼져 있습니다.
설치
먼저 작성자의 README에서 marketplace와 플러그인 이름을 확인하세요. 저장소 구조에 따라 명령어가 달라질 수 있습니다.
claude plugin marketplace add KilimcininKorOglu/claude-code-mods claude plugin install gemini-review
원문 / README
gemini-review
The model writes code, commits it, and nobody reads the diff before it lands: a hardcoded key, a bug the change brings in, or a change that is not what you asked for goes into history. This mod has Gemini review every commit the model makes. Before a Bash git commit runs, Gemini reads the change the commit records and the conversation. A blocking finding stops the commit and the model reads why; a minor finding lets the commit run and the model reads it after the result.
What it does
- The mod hooks the Bash tool. A command with a
git commitin it (thecommitskill included) is reviewed before it runs; any other command runs untouched. - It reads the command without a shell:
cd <dir>andgit -C <dir>set the directory,git addbefore the commit in the same command says what gets staged, andcommit -a,add -uandadd -Asay that every tracked or untracked change goes in. Paths given to the commit itself (git commit -m x -- a.ts) mean git records those paths from the working tree and nothing else, and the review reads just those. A commit message in a heredoc or in quotes is not read as a command.git commit --help,-hand--dry-runrecord nothing and are not reviewed. A command that runs anything else before the commit (echo x >> f && git commit -am ...) is stopped before it runs, and the model reads that it must commit in a Bash call of its own. The review reads the change before the command runs, so what those steps change would not be in it: such a commit went through with an empty diff and no review (measured on 2.1.278). Commands after the commit (&& git push) are allowed. - It collects the change with git, run by argv in the Bash tool's directory (
$.session.cwd()follows a Bashcd, measured on 2.1.278): the index, a path the command stages from the working tree (the index still holds its older content untilgit addruns), and each new file whole, at most 200 of them. Each git call has 20 seconds. When the change is empty, the commit runs with no review and no line. - It sends the diff and the conversation in one
generateContentrequest with a schema: a list of findings, eachblockerorminor, with a file, a line and a message. The diff always goes whole. When the conversation is overmaxInputChars(2,000,000 characters by default), its longest tool outputs are cut to one common length, each keeping its head and tail. gemini-core builds the request with the key, the model and the thinking level it holds forgemini-review, and reads the answer. blockermeans a bug the change introduces, data loss, a security hole, a secret or credential in the diff, or a change that contradicts what you asked for. Everything else isminor.- The verdict:
- a blocker: the command does not run; the model reads each blocker and the minor notes, with the instruction to fix and commit again, or, when a finding is wrong, to tell you why and run the same command with
GEMINI_REVIEW_SKIP=1in front; - only minor findings: the commit runs and the model reads the notes after the result;
- no finding: the commit runs and the model reads one line saying the review found nothing.
- a blocker: the command does not run; the model reads each blocker and the minor notes, with the instruction to fix and commit again, or, when a finding is wrong, to tell you why and run the same command with
- When the review cannot answer (no key, an HTTP error, a malformed answer or one cut at the output limit, a git error, a diff over 1,500,000 characters), the commit runs, a transcript line says why, and the model reads the reason.
- Gemini answers HTTP 503 ("high demand") now and then, often after 10 seconds or more. gemini-core then has the mod ask again after 1 s, 2 s and 3 s, at most four attempts in all, and no attempt starts whose wait would end past 60 s. A hook's 10-second budget counts its
$.clockwaits but not its requests, so the waits stay short. After a 429 or a key error, gemini-core hands over the request with its next key, when it holds one.
In a live check on 2.1.278 with gemini-3.8-flash, a commit of a file with sk_live_... was stopped with sub/pay.ts:1: Hardcoded live Stripe secret key committed in source code, a git add pay.ts sub.ts && git commit after the fix ran, a GEMINI_REVIEW_SKIP=1 commit ran unreviewed, and an invalid key let the commit run with Gemini HTTP 400: API key not valid. Of eight reviews in that session, four got an answer (one after two 503s, 42.5 seconds in all) and four got only 503 answers and let the commit run.
What it shows
After each review a toast stays for 10 seconds, and /gemini-review shows the last one:
gemini-review: reviewed 1 file(s) · 1 blocker, 0 minor · 2k in, 515 out · sent to Gemini free tier
The sent to Gemini free tier part appears only on the free tier. A transcript line follows every review, so you read what the model was told. The line holds the findings alone, without the instruction:
gemini-review: commit reviewed: 2 file(s), nothing to report
gemini-review: commit reviewed with 1 minor note(s): pay.ts:12: Name the constant.
gemini-review: commit stopped: reviewed 1 file(s) · 1 blocker, 0 minor · 2k in, 515 out
gemini-review: commit ran without a review: the model used GEMINI_REVIEW_SKIP=1
The context and the line are separate channels: the model never reads the line, and you never read the context.
Command
/gemini-review on or off, the model, thinking level and tier gemini-core holds, whether a key is set, the last review
/gemini-review on | off off: commits run without a review; on is refused while gemini-core has no key
/gemini-review reset off again, the default
The review is off after an install, so nothing goes to Gemini before you set a key and turn it on.
The key, the tier, the model (default gemini-3.8-flash) and the thinking level belong to gemini-core:
/gemini-core model review gemini-3.7-flash
/gemini-core thinking review low
/gemini-core paid
Free tier or paid tier
Every review sends the diff and the conversation: your prompts, the commands the model ran and the contents of the files it read. On the free tier Google may use them and human reviewers may read them; the gemini-core README quotes the Gemini API Additional Terms. On a project you would not show to Google, use a key with billing enabled and set /gemini-core paid.
Install
claude plugin marketplace add KilimcininKorOglu/claude-code-mods
claude plugin install gemini-review@kilimcininkoroglu-mods
It depends on gemini-core, which claude plugin install adds. Function hooks are early access. Claude Code 2.1.288 and later load them by default, so there is nothing to switch on.
After installing
- Set the Gemini key and the tier in gemini-core, as its After installing section says, then restart Claude Code.
- Run
/gemini-review on. Without a key it answersstill off: gemini-core has no Gemini keyand stays off. - Run
/gemini-review. The first line readson · <model> · thinking ... · <tier> tier · key set. - When a commit runs with
commit ran without a review: Gemini HTTP 429, the model has no quota on your key. Pick another with/gemini-core model review.
After an update from 0.1.x: claude plugin update does not add gemini-core (measured on 2.1.278), so run claude plugin install gemini-core@kilimcininkoroglu-mods once. Version 0.2.0 moved the key, tier and model to gemini-core; the apiKey, tier and model options and the settings /gemini-review free|paid|model stored before are no longer read, so set them again in gemini-core. Version 0.3.0 made the review off by default: after an update from an earlier version it is off unless you ran /gemini-review on before, so run /gemini-review on once.
Options
| Option | Default | What it sets |
|---|---|---|
| maxInputChars | 2000000 | Characters of conversation sent at most, 10,000 to 4,000,000; the diff always goes whole |
A value outside the range, or one that is not a whole number, falls back to the default.
What it can reach
Validated with claude plugin validate on Claude Code 2.1.283:
❯ ./register.ts hooks: session.start, command.run{command=gemini-review}, tool.call{tool=Bash}
❯ ./register.ts calls: $.clock.now (via askGemini), $.clock.sleep (via askGemini), $.command.register, $.gemini.enroll, $.gemini.read (via askGemini), $.gemini.request (via askGemini), $.gemini.settings (via review, runCommand, storeEnabled), $.http.fetch (via askGemini), $.process.run (via collectDiff, git), $.session.cwd (via review), $.session.messages (via review), $.store.delete (via runCommand), $.store.get (via isEnabled), $.store.set (via storeEnabled), $.ui.log, $.ui.toast (via verdictOf)
Reach L3, reaches the network.
1. Reads: each Bash command; at a commit, the repository's diff and new files through git, and the conversation (messages, tool inputs and outputs); its own $.store; from gemini-core, the request with the key
2. Runs: read-only git by argv, no shell: rev-parse, diff, ls-files; at most 200 new files are read
3. Sends: the diff and the conversation, one request per commit (up to four after a 503, and once more per extra key after a 429 or a key error), to the URL gemini-core builds (generativelanguage.googleapis.com) with the key in the x-goog-api-key header, never in the URL
4. Persists: in $.store, the on/off setting; the last review line lives in memory
5. Hostile input: a diff or a conversation can steer Gemini's findings, so a hostile change can pass or a sound one be stopped; the model reads the findings as a denial or a note and can skip a wrong one; paths from the command reach git as argv after --, never through a shell
Limits
- A review is a model's opinion. It can miss a problem, and a wrong blocker is passed with the skip prefix, which the model uses by its own decision.
- Only the model's Bash commits are reviewed. A commit from your terminal, from a script the model runs, from an alias or through another tool is not.
- The command reading covers the usual forms. A
cdinside a subshell, variables in paths and globs that git expands are not resolved. - A subagent's commit sends only the diff, because which transcript
$.session.messages()answers inside a subagent was not verified. - Every review sends the whole conversation, so a long session makes each review larger and slower.
$.session.messages()answers the newest 4096 messages. - The Bash hook ran 42.5 seconds without a limit in the live check. A longer limit was not measured.
Development
make install # eslint, typescript-eslint, typescript
make lint # complexity limit 10, the build fails above it
make typecheck # needs .claude/types/ from /plugin-types
make validate
make test # claude plugin test
