Skip to content

feat(adapters): add Antigravity CLI (agy) adapter profile#67

Merged
pbean merged 3 commits into
bmad-code-org:mainfrom
dracic:feat/antigravity-agy-adapter
Jul 6, 2026
Merged

feat(adapters): add Antigravity CLI (agy) adapter profile#67
pbean merged 3 commits into
bmad-code-org:mainfrom
dracic:feat/antigravity-agy-adapter

Conversation

@dracic

@dracic dracic commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What

Adds an antigravity adapter profile so the orchestrator can drive Google's Antigravity CLI (agy) alongside claude/codex/gemini/copilot.

Profiles are auto-discovered, so the only new logic is a hook dialect. agy keys .agents/hooks.json by a top-level hook-name group and stores a flat Stop handler list (no matcher/hooks wrapper), with second-based timeouts — different enough from the existing dialects to need its own antigravity-hooks-json branch. Only the Stop turn-end event is registered; agy fires no SessionStart/SessionEnd hooks.

Details

  • antigravity.toml-i interactive launch, --dangerously-skip-permissions, --model, skills in .agents/skills, hooks in .agents/hooks.json.
  • antigravity-hooks-json dialectmerge_hooks/_hook_entry write the flat handler under a bmad-loop group; idempotent and preserves any user/plugin hook groups.
  • Token accounting deferred — ships usage_parser = "none"; agy conversations are binary SQLite and the per-workspace transcript.jsonl schema isn't captured yet. A parser follows once a live transcript exists.
  • Marked experimental / probe-required — all flags/paths verified against agy v1.0.16 and its shipped docs, but end-to-end behavior (Stop under the multiplexer, worktree trust) still needs a live smoke via probe-adapter antigravity.

Second commit is a standalone robustness fix: the merge_hooks idempotency check crashed with TypeError if a pre-existing hook entry carried a non-string command (present-but-null). Guarded at both dedupe walks — pre-existing across all dialects, surfaced by the new branch.

Tests

New merge_hooks cases for the antigravity shape (entry shape, idempotency, append-beside-existing, preserve-other-groups, non-string command); probe parametrize extended. ruff check clean; full suite green. init --cli antigravity and probe-adapter antigravity runtime-verified against real agy v1.0.16.

Closes #66

Summary by CodeRabbit

  • New Features

    • Added support for the experimental Antigravity CLI as an additional option for setup, profile selection, and hook configuration.
    • Included a new ready-to-use Antigravity profile with guidance for interactive use and unattended runs.
  • Documentation

    • Updated setup and adapter docs to list the new supported CLI and its required configuration format.

dracic added 2 commits July 5, 2026 11:55
Google's `agy` joins claude/codex/gemini/copilot as a driven CLI. It reuses
the auto-discovered profile system; the only new logic is a hook dialect
(`antigravity-hooks-json`) because agy keys `.agents/hooks.json` by a top-level
hook-name group and stores a flat `Stop` handler list (no matcher/hooks
wrapper), with second-based timeouts. Only the `Stop` turn-end event is
registered — agy fires no SessionStart/SessionEnd hooks.

Token accounting ships as `usage_parser = "none"`; a parser is deferred until a
live transcript.jsonl schema is captured. Flags/paths verified against agy
v1.0.16; marked experimental/probe-required pending an end-to-end smoke.

Closes bmad-code-org#66
The idempotency check in merge_hooks used `HOOK_MARKER in handler.get("command", "")`,
which raises TypeError when a pre-existing hook entry carries a non-string command
(e.g. an explicit null). The default only applies to an absent key, not a present
None. Guard both dedupe walks with an isinstance check so a slightly malformed
hooks.json no longer crashes `init`. Pre-existing across all dialects; surfaced by
the new antigravity branch, fixed at the shared site too.
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@dracic, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b91c2f6-11b6-4174-9c20-dfad1c441e19

📥 Commits

Reviewing files that changed from the base of the PR and between 88703fa and 38acbeb.

📒 Files selected for processing (6)
  • README.md
  • docs/setup-guide.md
  • src/bmad_loop/cli.py
  • src/bmad_loop/data/skills/bmad-loop-setup/SKILL.md
  • src/bmad_loop/install.py
  • tests/test_install.py

Walkthrough

This PR adds support for Google's Antigravity CLI (agy) as a new adapter. It introduces a new antigravity-hooks-json hook dialect, an antigravity.toml profile, install.py logic to merge hooks under an agy-specific group, corresponding tests, and documentation/CLI help updates.

Changes

Antigravity adapter support

Layer / File(s) Summary
Profile and hook dialect contract
src/bmad_loop/adapters/profile.py, src/bmad_loop/data/profiles/antigravity.toml
Adds antigravity-hooks-json to HOOK_DIALECTS and introduces the new antigravity TOML profile with launch args, model flag, usage parser disabled, prompt template, skill path, and hook mapping.
merge_hooks implementation
src/bmad_loop/install.py
Adds ANTIGRAVITY_HOOK_TIMEOUT_SEC/ANTIGRAVITY_HOOK_GROUP constants, extends _hook_entry for the agy handler shape, adds a dialect-specific merge_hooks branch, and hardens the generic idempotency check with a typed command extraction.
Tests for hook merging and probing
tests/test_install.py, tests/test_probe.py
Adds merge_hooks regression tests for antigravity entry shape, idempotency, appending, non-string command tolerance, and group preservation; updates probe test parametrization and assertions.
Documentation and CLI help
README.md, docs/FEATURES.md, docs/adapter-authoring-guide.md, docs/setup-guide.md, src/bmad_loop/data/skills/bmad-loop-setup/SKILL.md, src/bmad_loop/cli.py
Documents the antigravity adapter, its limitations, and the new hook dialect across README, feature docs, adapter-authoring guide, setup guide, setup skill, and CLI help text.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Installer as install.py
  participant HookEntry as _hook_entry
  participant Merge as merge_hooks
  participant Config as hooks.json

  Installer->>HookEntry: build handler for antigravity-hooks-json
  HookEntry-->>Installer: agy-shaped handler object
  Installer->>Merge: merge registrations for Stop event
  Merge->>Config: write under ANTIGRAVITY_HOOK_GROUP
  Merge-->>Installer: preserve other groups, dedupe by command marker
Loading

Poem

A new CLI hops into view,
Antigravity, agy, right on cue! 🐇
Hooks now nest in bmad-loop's bed,
No usage_parser — that's fine, instead,
Docs and tests all lined up neat,
This rabbit's stack is now complete! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding the Antigravity (agy) adapter profile.
Linked Issues check ✅ Passed The new antigravity profile, hook dialect, Stop mapping, skills path, and merge logic align with the linked issue's core requirements.
Out of Scope Changes check ✅ Passed The docs, tests, profile, and merge fix all support the Antigravity adapter work and are not unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@augmentcode

augmentcode Bot commented Jul 5, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Adds an experimental antigravity adapter profile so bmad-loop can drive Google’s Antigravity CLI (agy).
Profile: New antigravity.toml wires interactive launch (-i), model flag, bypass flag, and .agents/skills + .agents/hooks.json paths.
Hooks: Adds an antigravity-hooks-json dialect that merges a flat Stop-handler list under a top-level bmad-loop group.
Robustness: merge_hooks idempotency now tolerates pre-existing handlers with non-string/NULL command fields.
Docs: Updates README/features/setup/authoring guide to mention antigravity and its probe-required status.
Tests: Adds merge-hook coverage for the new shape and extends probe parametrization to include antigravity.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/bmad_loop/cli.py Outdated
Comment thread src/bmad_loop/install.py
Comment thread docs/setup-guide.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/setup-guide.md`:
- Around line 93-95: Update the setup-guide text to match the expanded adapter
list so the prompts no longer contradict the supported options. In the relevant
setup prompt sections, make sure the wording and any examples reference the full
set of adapters used by the setup flow, including antigravity, and keep the same
list consistent wherever the adapter choices are described so users aren’t told
only claude, codex, and gemini are valid.

In `@src/bmad_loop/data/skills/bmad-loop-setup/SKILL.md`:
- Around line 135-137: Update the onboarding prompt in SKILL.md to match the
rest of the setup instructions by making the supported coding CLI list
consistent everywhere; the prompt near the CLI selection section should align
with the later validation text and any other references in this skill. Use the
existing CLI-selection wording and symbols in the setup flow to locate it, and
ensure the accepted names are reconciled so `/bmad-loop-setup` does not present
conflicting options.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08d83263-e8ad-4a75-833e-a1d81ee90fd4

📥 Commits

Reviewing files that changed from the base of the PR and between abd09d6 and 88703fa.

📒 Files selected for processing (11)
  • README.md
  • docs/FEATURES.md
  • docs/adapter-authoring-guide.md
  • docs/setup-guide.md
  • src/bmad_loop/adapters/profile.py
  • src/bmad_loop/cli.py
  • src/bmad_loop/data/profiles/antigravity.toml
  • src/bmad_loop/data/skills/bmad-loop-setup/SKILL.md
  • src/bmad_loop/install.py
  • tests/test_install.py
  • tests/test_probe.py

Comment thread docs/setup-guide.md Outdated
Comment thread src/bmad_loop/data/skills/bmad-loop-setup/SKILL.md
- install.py: raise a clear ProfileError when a pre-existing .agents/hooks.json
  has a non-table `bmad-loop` group or a non-list event value, instead of an
  opaque AttributeError during init (augment)
- cli.py: list `copilot` in the `init --cli` help (was omitted)
- setup-guide.md / bmad-loop-setup SKILL.md: reconcile the "valid names" notes
  with the full profile set (copilot + antigravity); mark antigravity
  experimental in the choose-CLIs section (augment, coderabbit)
- README.md: prettier table re-alignment (the widened antigravity row)
- test: malformed-shape hooks.json now asserts a clear ProfileError
@dracic

dracic commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Addressed review + fixed the prettier CI failure in 38acbeb:

  • install.py:148 (augment, medium) — a malformed pre-existing .agents/hooks.json (non-table bmad-loop group or non-list event) now raises a clear ProfileError instead of an opaque AttributeError; covered by a new test.
  • cli.py:1209 (augment, low)init --cli help now lists copilot too.
  • setup-guide.md & bmad-loop-setup SKILL.md (augment + coderabbit) — reconciled the "valid names" notes with the full set (added copilot + antigravity) and marked antigravity experimental in the choose-CLIs section.
  • README.md — prettier re-aligned the profile table after the widened antigravity row.

Not changed: the HOOK_MARKER substring dedupe and the malformed-config fragility on the shared (non-antigravity) hooks path are pre-existing across all dialects — out of scope for this PR. @pbean check this.

@pbean pbean left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated end-to-end — approving. ✅

Safe for the core and the other adapters. All new write-logic is gated behind if dialect == "antigravity-hooks-json" and returns early; the claude/codex/gemini/copilot paths are untouched except the one hardening line in merge_hooks, which is behaviour-preserving for every valid config (identical result for string commands, only stops a TypeError on a null one). No OS-seam edits — agy isn't claude-settings-json, so the hook command bakes its absolute path through the existing ProcessHost.hook_interpreter()/shell_quote() seam, exactly like codex/gemini/copilot, so it's portable with zero new platform code. Profile-name enumeration is fully dynamic (load_profiles()), so the new TOML registers everywhere automatically — nothing hardcoded was missed.

merge_hooks branch is correct: idempotent (the dedupe walk tolerates both flat and wrapped shapes), raises a clear ProfileError on a malformed pre-existing group/event, and preserves other user/plugin hook groups. Test coverage is thorough.

External agy facts verified against live sources (Antigravity CLI post-dates my usual references, so I checked each): binary agy, -i = --prompt-interactive, --dangerously-skip-permissions, project hooks in .agents/hooks.json keyed by a top-level named group, second-based timeouts, skills in .agents/skills/, and agy 1.0.16 all check out. The load-bearing one — that Stop is a flat handler with no matcher/hooks wrapper (what _hook_entry writes) — is confirmed: agy treats Stop/PreInvocation/PostInvocation as matcher-less flat lists, unlike the wrapped PreToolUse/PostToolUse shape. So the profile is right.

The experimental — probe-required labeling correctly fences the one thing not verifiable from a code read (live Stop firing under the multiplexer + worktree-trust re-prompt), which you've runtime-checked against real agy 1.0.16 and gated behind probe-adapter antigravity.

Replied separately on the two items you flagged for me. Nice, tidy addition.

@pbean

pbean commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

On the two you tagged me about — both fine to leave as-is here:

  1. HOOK_MARKER substring dedupe — agreed, pre-existing across all dialects and orthogonal to this PR. Leave it.
  2. Malformed-config fragility on the shared (non-antigravity) hooks path — correct call to scope it out. Worth noting it's also unreachable via the antigravity path: agy hooks live under the bmad-loop top-level group, and strip_legacy_hooks only ever walks config["hooks"], so it never touches them. The only remaining null-command TypeError is in strip_legacy_hooks itself (lines 179/188), which is genuinely pre-existing and untouched by this PR.

I'll pick up that strip_legacy_hooks guard (same isinstance(..., str) shape you landed in merge_hooks) in a small follow-up PR, together with a probe.py FAMILY_GLOBS entry for agy so probe-adapter antigravity can auto-discover a transcript and unblock the deferred token parser. No changes needed here — approving.

@pbean pbean merged commit a471267 into bmad-code-org:main Jul 6, 2026
9 checks passed
pbean added a commit that referenced this pull request Jul 6, 2026
…d agy probe glob (#70)

* fix(install): guard strip_legacy_hooks against a non-string command

A pre-existing hook handler whose `command` is present-but-null crashed
strip_legacy_hooks with `TypeError: argument of type 'NoneType' is not
iterable` at both dedupe walks (the flat copilot entry and the nested
claude/codex/gemini handler). Mirror the isinstance-str guard PR #67 landed
in merge_hooks so a malformed hand-edited config is tolerated (a non-string
command simply isn't a bmad_auto hook, so it's kept). Regression test covers
both walks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(probe): add antigravity transcript family glob for agy discovery

Give `probe-adapter antigravity` a fallback transcript location so it can
auto-discover an agy conversation transcript.jsonl — the step that unblocks
writing the deferred token parser (the antigravity profile ships
usage_parser = "none"). The path is community-doc-sourced (agy 1.0.x) and
degrades safely to the existing "no convention" note if wrong; confirm
against a live build with `probe-adapter antigravity --probe`.

Companion to #67 — the glob activates once the antigravity profile lands.
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.

Add agy (Google Antigravity CLI) adapter profile — Gemini CLI is EOL

2 participants