feat: add support for Gemini CLI - #150
Draft
ryzizub wants to merge 3 commits into
Draft
Conversation
Ports the enforcement layer to Gemini CLI so the plugin is not skills-only
there. Skills already load unchanged from the Agent Skills standard paths;
this adds the MCP wiring, the hooks, the reviewer subagent, and CI that
proves all three actually load.
- `.gemini/settings.json` registers the same `dart` and `very-good-cli`
servers as `.mcp.json` and runs the same hook scripts under Gemini's event
names. Generated with `gemini hooks migrate --from-claude`, then corrected
for the three things that tool leaves behind: `${CLAUDE_PLUGIN_ROOT}` (no
Gemini equivalent for settings-level hooks, so scripts resolve through
`${VGV_PLUGIN_ROOT:-$PWD}`), timeouts (Gemini reads milliseconds, Claude
reads seconds), and MCP matchers (`mcp_<server>_<tool>`, not
`mcp__<server>__<tool>`).
- The hook scripts read `hook_event_name` and emit whichever response shape
the firing harness reads, so one script serves both. Claude Code behavior
is untouched: `check-vgv-cli.sh` still auto-approves and
`block-cli-workarounds.sh` still steers the quality gates through the MCP
tools there.
- `.gemini/agents/flutter-reviewer.md` ports the reviewer. Gemini validates
agent frontmatter with a strict schema that rejects `skills:` and `hooks:`,
so it is a second port rather than a shared file. Its read-only contract is
structural instead of hook-enforced: it is granted no shell tool at all.
- A `Gemini CLI Loader` CI job asserts all 15 skills load, the subagent
passes Gemini's schema, and every hook registers and runs — no credentials
and no model call. `gemini-config_test.sh` guards the silent-failure modes
statically, and both hook suites now run every case once per harness.
Closes #125
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ryzizub
marked this pull request as draft
September 8, 2026 13:18
Matches the shape of the Codex PR (#151): the harness-specific assets are a plain `gemini/` directory of files users copy, and everything else is docs. - `.gemini/` becomes `gemini/`. It was never config for this repo's own workspace; it is the MCP + hooks settings a user merges into their own `~/.gemini/settings.json` (or a project's `.gemini/settings.json` for a whole team), and the reviewer agent they copy into `agents/` beside it. The hook path drops the `$PWD` fallback and reads `${VGV_PLUGIN_ROOT}` plainly, since the plugin is never installed at the user's project root. - Drops the Gemini CLI loader CI job and `gemini-config_test.sh`. Nothing in CI exercises Codex either; both are verified by hand, and `CONTRIBUTING.md` says how. - The two hook suites keep their original cases and gain one assertion each for the Gemini response shape, rather than running the whole matrix twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Re-checked every claim against the current release rather than the 0.52.0 that was on hand. Nothing the port depends on changed: hook event names, the milliseconds timeout, the `decision`/`reason` block shape, the absence of an auto-approve, `gemini hooks migrate --from-claude`'s mappings, the strict local agent schema, the `.agents/skills` discovery path, the agent directories, and the settings env-var interpolation regex are all byte-identical between the two. Both MCP servers connect and all 15 skills load on 0.59.0. One behavior did change and it bites the verification steps this file recommends: 0.59.0 made workspace trust fail closed, so a headless `gemini -p` in an untrusted directory now refuses to start instead of loading with workspace features disabled. That reads as "nothing loaded" unless you expect it, so the instructions now say to set `GEMINI_CLI_TRUST_WORKSPACE=true`. Also makes the README's `VGV_PLUGIN_ROOT` step say to put it in a shell profile, since Gemini resolves it when it loads settings, and labels the two agent copy targets. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Wires up MCP, hooks, and the reviewer agent for Gemini CLI. Skills were already portable after #128. Closes #125.
Gemini CLI reads the Agent Skills standard directly, scanning
.agents/skillsalongside its own.gemini/skills, sogemini skills install <repo-url> --path skillslands all 15 with no Gemini-specific file. The enforcement layer does not carry over as cleanly — different hook event names, different tool names, a stricter agent schema — sogemini/holds those three, ported.What changes:
gemini/settings.json— registers the samedartandvery-good-cliservers as.mcp.jsonand wires the same hook scripts under Gemini's event names. Generated withgemini hooks migrate --from-claude, then corrected for the three things that tool leaves behind, all of which fail silently:${CLAUDE_PLUGIN_ROOT}is not rewritten and has no Gemini equivalent for settings-level hooks (hence${VGV_PLUGIN_ROOT});timeoutis copied verbatim, but Gemini reads milliseconds where Claude Code reads seconds, so a10becomes a 10 ms budget; and MCP matchers keepmcp__<server>__<tool>when Gemini names themmcp_<server>_<tool>.hooks/scripts/vgv-cli-common.sh—deny()andallow()readhook_event_nameand emit whichever response shape the firing harness reads (hookSpecificOutput.permissionDecisionfor Claude Code, top-leveldecision/reasonfor Gemini), so one script serves both. Claude Code behavior is unchanged: a payload without that field still gets the Claude shape, andcheck-vgv-cli.shstill auto-approves there. Gemini has no auto-approve for aBeforeToolhook, so that path enforces the version gate only and"trust": trueon the MCP server covers approval.gemini/agents/flutter-reviewer.md— Gemini cannot bundle a subagent in an install, so users copy this file. It cannot be the same file asagents/flutter-reviewer.md: Gemini validates agent frontmatter against a strict allowlist and drops any agent carrying a key outside it, soskills:andhooks:are both rejected. Read-only is enforced by granting no shell tool at all rather than by the agent-scoped hook Claude Code uses — same guarantee, different mechanism, worth a look.README.md,CONTRIBUTING.md,CLAUDE.md,AGENTS.md.Everything else is shared verbatim: both harnesses put the shell command in
tool_input.commandand the edited path intool_input.file_path, soblock-cli-workarounds.sh,analyze.shandformat.shneed no payload changes.Marketplace/extension packaging is deliberately out of scope. Gemini's own
gemini extensions installwould need this repo rooted as an extension, and Gemini then readshooks/hooks.jsonandagents/with its own schemas — printingInvalid hook event name: "PreToolUse" ... Skipping.twice per session and erroring on the Claude agent file. Not worth degrading either path for.Verification
Tested against a real Gemini CLI 0.59.0 (current
lateston npm) in a throwawayHOME, installed the way a user would.gemini skills install https://github.com/VeryGoodOpenSource/vgv-ai-flutter-plugin --path skills— 15/15 installed from the real URL. Also 15/15 discovered from.agents/skills.gemini/settings.jsoninto~/.gemini/settings.jsonand copied the agent to~/.gemini/agents/: agent loads clean, zeroInvalid hook event name, zero hook failures, theSessionStarthook actually ran from${VGV_PLUGIN_ROOT}and returned its warning, andgemini mcp listshows bothdartandvery-good-cliConnected. Verified for both the user-scope and project-scope install described in the README.Unrecognized key(s) in object: 'skills', 'hooks'— which is why there are two files.claude plugin validate .clean.Cross-checked every claim in the docs against the 0.59.0 source and the official docs, not just the version that happened to be installed. Byte-identical between 0.52.0 and 0.59.0: hook event names, the milliseconds timeout, the
decision/reasonblock shape, the absence of any auto-approve forBeforeTool,gemini hooks migrate --from-claude's event and tool-name mappings, the strict local-agent schema, the.agents/skillsdiscovery path, the agent directories, the hook env vars (there is still no plugin-root variable for settings-level hooks, hence${VGV_PLUGIN_ROOT}), and the settings env-var interpolation regex.One behavior did change in 0.59.0 — workspace trust is now fail-closed, so a headless run in an untrusted directory refuses to start rather than loading with workspace features disabled. That only affects the by-hand verification steps, which now say to set
GEMINI_CLI_TRUST_WORKSPACE=true; interactive users just get the normal trust prompt.Not verified: a live
BeforeToolblock orAfterToolanalyze/format inside a real Gemini session — that needs credentials and a model call. Those paths are covered at the script level with real Gemini payloads, and the wiring that reaches them (event names, matchers, script resolution) is verified above.Type of Change
feat)fix)refactor)docs)ci)chore)🤖 Generated with Claude Code