7.1 KiB
title, date, category, module, problem_type, component, severity, applies_when, tags
| title | date | category | module | problem_type | component | severity | applies_when | tags | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Verify a new target platform's plugin format against the CLI binary, not its docs | 2026-06-23 | conventions | converters | convention | converter-cli | medium |
|
|
Verify a new target platform's plugin format against the CLI binary, not its docs
Context
Adding a new converter Target (see adding-converter-target-providers.md for the structural 6-phase checklist) assumes you know the target's plugin format: its manifest schema, directory layout, MCP/hook config shape, and install command. The usual source for that is the platform's documentation.
When targeting Antigravity CLI (agy, Google's successor to the retired consumer Gemini
CLI) this failed: antigravity.google/docs renders as a client-side app, so WebFetch
returned only the page title — no schema, no commands, no field names. Two independent
research agents, working only from docs and training data, disagreed on concrete facts (e.g.
whether the interactive tool was ask_user, and whether remote MCP servers used url or
serverUrl). Building a converter on either guess would have shipped a format that agy
silently rejects or mis-reads.
Guidance
When a target platform ships a CLI, treat the installed binary as the authoritative format
spec and probe it empirically before writing converter code. Run a throwaway fixture plugin
through the CLI's own validate/install/list commands and read what it accepts, transforms, and
stores. Capture the findings in a docs/specs/<target>.md spec, then build the converter
against the spec — not against the docs.
The probing loop that worked for agy v1.0.10:
- Start minimal, let the validator teach you the schema. A
plugin.jsonof just{ "name", "version" }passedagy plugin validate; the validator's per-section output (skills,agents,commands,mcpServers,hooks— eachprocessedorskipped (not found)) revealed the full component surface without any docs. - Add one candidate component at a time and re-validate to learn each one's expected
location and form (
agents/<n>.md,commands/<n>.{toml,md}reported as "converted to skills", rootmcp_config.json, roothooks.json). - Let validator error messages settle field-name disputes. Feeding a remote MCP server
{ "url": ... }producedmust have either command or serverUrl— definitively resolvingserverUrloverurl/httpUrl, which docs and agents had guessed wrong. installthenlist --json, thenuninstallto learn the install model and storage without leaving residue:agy plugin install <dir>requires a local directory (no install-from-URL), and installed plugins live in an internal registry (agy plugin list --jsonshowssource ∈ {antigravity, gemini-cli, claude}), not a readableplugins/tree.- Mine the binary and its bundled assets for what probing can't surface
(
~/.gemini/antigravity-cli/builtin/skills/.../cli.mddocumented/permissionsand thetoolPermissionsetting).
Defer, don't guess, on anything the probe can't confirm. The per-event hooks.json schema
was not establishable from a fixture, so the converter emits only the { hooks: {...} }
container and the spec records the gap — rather than emitting an unverified per-event shape.
Equally, where the human operator has direct live knowledge the probe lacks, prefer it: the
ask_question tool name was confirmed by the user from live agy usage after binary
string-inspection came up empty.
Why This Matters
A converter writes files another tool ingests. A wrong field name, manifest location, or
install assumption fails silently — the target skips the section or rejects the bundle with
no error in our pipeline — and ships broken output to every user of that target. Docs are a
weaker oracle than the binary for three reasons seen here: they can be unfetchable
(client-rendered), they lag the CLI's actual behavior, and an LLM filling the gap from training
priors produces confident, wrong specifics. The CLI binary is the artifact users actually run,
so its acceptance behavior is the only spec that can't be stale or hallucinated. The cost is
low (a few validate/install cycles against a fixture) and the spec it produces is reusable
by every later converter change.
When to Apply
- Any time you add or significantly change a converter/install Target and the platform exposes a CLI you can run locally.
- Especially when the platform's docs are client-rendered, sparse, brand-new, or in flux.
- When migrating a Target to a successor platform — do not assume format continuity. Antigravity
inherited Gemini's models and reads
GEMINI.md, but its plugin format, install model, MCP field names, and permission model all differ. - Skip (or lean lighter) only when the platform publishes a machine-readable schema you can validate against directly, or ships an official converter/import you can diff against.
Examples
Antigravity facts established by probing (full record in docs/specs/antigravity.md):
| Question | Docs/agent guess | Probe result |
|---|---|---|
| Remote MCP field | url / httpUrl |
serverUrl (validator: "must have either command or serverUrl") |
| Install source | repo URL | local directory with a root plugin.json (agy plugin install <dir>) |
| Commands | a command primitive | converted to skills on install |
| Interactive tool | ask_user |
ask_question (confirmed in live use; absent from binary strings) |
| Minimal manifest | unknown | { name, version } |
Converter consequence: src/converters/claude-to-antigravity.ts maps the Claude remote-MCP
url to serverUrl, and src/targets/antigravity.ts emits the verified bundle layout. The
spec drove these mappings; the docs could not have.
Packaging consequence — committed .agy/ bundle with a symlink: because agy plugin install
resolves component dirs relative to the plugin.json location, this plugin ships a committed
.agy/ directory holding plugin.json plus a skills -> ../skills symlink (verified:
agy plugin validate ./.agy processes all skills through the symlink). This keeps the repo root
uncluttered while reusing the canonical root skills/ rather than duplicating it — and lets users
git clone … && agy plugin install ./compound-engineering-plugin/.agy. (See also the per-platform
choices in native-plugin-install-strategy.md.)
Related: GitHub issue #911 (Transition to Antigravity CLI); plan
docs/plans/2026-06-22-001-feat-antigravity-target-remove-gemini-plan.md.