Skip to content

Feat: Replace Gemini CLI with Antigravity CLI - #282

Open
Fluzko wants to merge 4 commits into
symposium-dev:mainfrom
Fluzko:antigravity-agent
Open

Feat: Replace Gemini CLI with Antigravity CLI#282
Fluzko wants to merge 4 commits into
symposium-dev:mainfrom
Fluzko:antigravity-agent

Conversation

@Fluzko

@Fluzko Fluzko commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

depends on #274
needs some work over plugins when merged #280

What does this PR do?

Adds Google's Antigravity CLI (agy) as a supported agent and retires Gemini CLI. Implements #281.

Gemini CLI's consumer sign-in is closed, "Sign in with Google" now fails with a message from Google telling you to migrate to Antigravity. That's the path our users take, so we follow.

Three commits, reviewable in order:

  1. Add the agent: skills, MCP servers and hooks
  2. Document it: reference page, agent-details page, and the usual tables
  3. Retire Gemini: remove the agent, keeping compatibility shims

Antigravity in short

Skills were free: it reads the same .agents/skills/ layout we already write for Copilot, Codex, OpenCode and Goose. MCP was easy: its own mcp_config.json, familiar mcpServers shape.

Hooks were the work. A few of its behaviours are unusual enough to shape the code, and each was verified by running agy rather than read from its docs:

  • A PreToolUse hook that returns {} denies the tool call, and exit codes are ignored entirely. Our dispatcher returns {} whenever no plugin contributes, the common case, so without care this would block every tool call. We always emit an explicit allow.
  • SessionStart exists but isn't documented. The docs list five events; the binary has six. It works, and fires once per session.
  • There's no prompt event. PreInvocation stands in, but fires before every model call, so we only act on the first of a turn.

Retiring Gemini safely

A user's config outlives the release that drops an agent, so nothing hard-fails:

  • A gemini entry in your config is reported and skipped, not fatal
  • A leftover hook registration exits cleanly instead of erroring inside a session
  • A plugin manifest declaring format = "gemini" still loads, with just that hook skipped
  • A one-shot migration clears the config entry, the hooks, and the skills we installed

One fix worth a look

sync registered hooks and MCP by passing the workspace root to the global functions. That only produces the right path when an agent's project and global locations happen to share a shape. Antigravity's don't, so project scope wrote to a file agy never reads.

The project-scoped functions already existed but had no callers. sync now uses them — which also moves Copilot's project hooks from .copilot/settings.json to .github/hooks/, where Copilot actually reads them. Copilot users on project scope get working hooks for the first time; a dead .copilot/settings.json stays behind in their repos.

Testing

462 tests pass. Beyond unit and integration coverage, the agent was driven end to end against a real agy to confirm hooks load, tool calls aren't denied, and session-start fires once per session.

Disclosure questions

AI disclosure.

  • The AI tool authored large parts of the code

Claude did the research, implementation and testing, including probing a real agy install to establish the hook contract. Direction, scope and the design calls were mine.

Questions for reviewers.

  • The Copilot path change is a fix, but it's a behaviour change riding along in a PR about a different agent. Happy to split it out if you'd rather.
  • MCP registration is covered by unit tests but hasn't been exercised against a live agy, that needs a plugin declaring an MCP server, which depends on other in-flight work.

Gemini CLI's consumer sign-in is closed -- Google's own message directs
those users to Antigravity, which symposium now supports. Removes the
agent, its hook wire format and its MCP registration.

Removing an agent also removes the code that would otherwise reap what
symposium installed for it, so the leftovers are handled rather than
abandoned:

- A `gemini` entry in the user config is reported and skipped by
  `Agent::from_configured_name` rather than failing the command. A user
  config outlives the release that drops an agent, so erroring would
  break every invocation until the file was edited by hand.
- `HookAgentArg` parses a retired name to nothing to dispatch, so a hook
  registration still sitting in `.gemini/settings.json` exits cleanly
  instead of failing inside that agent's session.
- `HookFormat::Retired` keeps a published plugin manifest declaring
  `format = "gemini"` loadable, with only that hook skipped.
- `migrations.rs` runs once per config directory, keyed by id in
  `state.toml`: it drops the config entry, unregisters those hooks, and
  reaps the marker-bearing skill directories under `~/.gemini/skills/`.
  It deliberately does not touch `~/.gemini/config/`, which is where
  Antigravity keeps its own.

Project skills lived in the shared `.agents/skills/`, which other agents
still use, so the ordinary marker-based cleanup handles those.
@Fluzko
Fluzko marked this pull request as ready for review September 7, 2026 13:10
Resolve conflicts with the per-agent MCP registration paths landed on main
(symposium-dev#274):

- Keep main's single `Agent::mcp_config_path(scope, ..)` seam plus
  `register_mcp_servers` / `unregister_mcp_servers`, and register Antigravity
  through it: `<project>/.agents/mcp_config.json` for project scope,
  `~/.gemini/config/mcp_config.json` for user scope. Its MCP file is separate
  from its `hooks.json`, so it needs no hooks-file exception in the test that
  asserts the two never coincide.
- Keep this branch's hook-scope split in `sync`: project hook files are
  genuinely different files, not the global path rooted at the workspace, so
  project scope calls `register_project_hooks`. MCP unregistration keeps
  main's both-scopes sweep.
- Docs: main's verified MCP table with the Gemini CLI row replaced by
  Antigravity, and the `McpScope` note in module-structure updated to match
  `supports_project_mcp_scope`.

Co-authored-by: Claude <claude@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant