Antigravity CLI (agy) as a Paseo provider: streaming turns, tool rows with diffs, images, structured output, skills and slash commands, question cards for ask_question, conversation import, opt-in MCP sharing, and multiple accounts with per-account usage quota.
From the plugin's README
--sandbox is not demonstrated. The flag is accepted and the turn runs, but with permissive
Antigravity settings a write outside the workspace still succeeded, so the plugin does not claim the
restriction holds.code: "unavailable", and an error result ends the CLI
process, which the next turn relaunches on the same conversation. A 503 that agy retried mid-turn
does not fail the turn: agy still reports such a turn as an error, but when its last step is a
finished answer after the 503, the turn completes, with an info notice.code: "credits_exhausted",
never as retryable, and a notice suggests adding credits or starting a session under another
account: an account is fixed for the life of a session.session.list, but their earlier turns are not replayed.npmjs · Paseo 0.9+
paseo plugin add npm:paseo-plugin-antigravity-cli@0.11.0GitHub · Paseo 0.8 fallback
paseo plugin add lefos13/paseo-plugin-antigravity-cli --ref 1d43a3855cf62e1bdb1ea334e7fc36941a357e35Git security status and fallback installation are pinned to commit 1d43a3855cf6.
From the plugin's README
From npm, from GitHub, or by pasting either source into Settings → Plugins → Plugin source:
paseo plugin install npm:paseo-plugin-antigravity-cli
paseo plugin install github:lefos13/paseo-plugin-antigravity-cli
Check it with paseo plugin ls; antigravity-cli should be running. agy --version must print and
agy must be signed in, and then pick Antigravity when you start a new agent. The sidebar entry
Antigravity accounts picks which account new agents run under — see
Multiple accounts.
Unlike agy-provider, which adapts Antigravity's ACP
server through Paseo's ACP shim, this plugin drives the agy CLI directly over its documented
stream-json mode. The agy it launches is the first of providerOptions.agyPath,
PASEO_ANTIGRAVITY_BIN, the installer's location — ~/.local/bin/agy, or on Windows
%LOCALAPPDATA%\agy\bin\agy.exe — (checked explicitly, because a daemon started by a GUI app often
has no such directory on PATH), then agy from PATH.
README
Runs Google's official Antigravity CLI (agy) as a Paseo provider: Paseo owns the session, the CLI
does the work, and every turn, tool call, and message is rendered from the CLI's stream-json
protocol. Nothing about Antigravity is reimplemented — the plugin spawns the agy binary that is
already installed and signed in on your machine.
antigravity-cli/compact and Auto mode need 1.3.5). The plugin also ships a client
entry (the accounts screen), so the connected Paseo app must satisfy the
same minimum — a compatible daemon does not make an older app compatible.
From npm, from GitHub, or by pasting either source into Settings → Plugins → Plugin source:
paseo plugin install npm:paseo-plugin-antigravity-cli
paseo plugin install github:lefos13/paseo-plugin-antigravity-cli
Check it with paseo plugin ls; antigravity-cli should be running. agy --version must print and
agy must be signed in, and then pick Antigravity when you start a new agent. The sidebar entry
Antigravity accounts picks which account new agents run under — see
Multiple accounts.
Unlike agy-provider, which adapts Antigravity's ACP
server through Paseo's ACP shim, this plugin drives the agy CLI directly over its documented
stream-json mode. The agy it launches is the first of providerOptions.agyPath,
PASEO_ANTIGRAVITY_BIN, the installer's location — ~/.local/bin/agy, or on Windows
%LOCALAPPDATA%\agy\bin\agy.exe — (checked explicitly, because a daemon started by a GUI app often
has no such directory on PATH), then agy from PATH.
One agy process per session: each prompt is one NDJSON turn and exactly one result back, and a
prompt sent while a turn runs is queued by the CLI as the next turn. Model, tier, mode, and settings
are launch flags, so a change restarts the CLI on the next turn and resumes the same conversation;
Antigravity conversations can be imported read-only, the conversation id agy reports is persisted,
each subagent becomes a child session (Subagents), and permission covers plan approval
and the questions agy cannot ask (Questions). Images and uploaded files go
over by file, because a stream-json turn carries text only.
Models come from agy models (cached ten minutes; force rediscovers), so the composer offers one
model per family with the tiers that family has — High, Medium and Low today. providerOptions.effort
is described in the table below.
Modes are Default (review file writes before they run), Accept edits, Auto, and Plan; tool rows cover shell commands, file edits with a diff, searches, web fetches, and MCP tool calls.
Auto (agy 1.3.5) approves edits and safe commands and asks before irreversible actions. agy offers
it only to some accounts and runs any other in its default mode with a warning; the plugin then moves
the selector back to Default and says so. How Auto's question before an irreversible action behaves
in stream-json mode is untested.
agy's own --mode plan is never passed: on 1.2.11 it either has no effect, while slash-command
expansion is disabled, or approves its own plan review — nobody can answer that in a headless run —
and implements in the same turn. Plan mode is therefore the plugin's own: a plan-mode turn is prefixed
with a <plan_mode> block telling the model to investigate read-only and end with a plan, and its last
answer is then offered as a plan (kind: "plan" permission) with Implement and Keep planning.
Implement switches a Plan-mode session to Accept edits and sends The plan is approved. Implement it now.; Keep planning, or another message, withdraws it. It is an instruction, not a sandbox: a
model that ignores it can still write files.
/plan <task> is the same plan turn in whatever mode the session is in, and never agy's own /plan
workflow, which approves its own plan review headless and implements straight away. Its Implement
keeps the session's mode.
ask_question)Headless agy never shows an ask_question dialog. It answers the call itself with User Skipped and
the model carries on, making the choice on its own. That is what happens to /teamwork-preview's
team-scale question, /grill-me's interview, /schedule's time, and any question the model decides
to ask. The stream reports the call only as an unknown step, so the plugin reads the question from
the conversation's transcript. It then stops the CLI before the model acts on the skip, completes the
turn, and offers the questions as Paseo's question card (kind: "question"): single or multi-select,
always with a write-in answer.
In Plan mode the question comes first and the plan card follows the answer turn.
When the model starts a long-running command in the background, agy holds back every later step until it exits. After 5 s of that the plugin reads the conversation's own transcript and publishes the held steps, so the turn keeps showing progress.
If the model's answer is only "waiting for it to finish" (agy's own instruction right after the launch, even when the model checks on the task or reads its log first), the turn stays running: agy waits for the command itself (up to 30 minutes), hands the model its result, and the model finishes the same turn. Once the command ends the plugin goes back to the stream. A message sent meanwhile is queued behind the turn, as with any running turn.
If the model answers after doing other work, such as a dev server started and then checked, the turn completes as soon as the transcript shows that answer. The CLI holding the command is left running, so the server stays up (a notice says so), but it cannot take another turn: your next message stops it, and the command with it, and resumes the conversation in a fresh CLI. When that command finishes later, agy hands its result to the model, which carries on in the answered turn; the plugin stops the CLI at the first step past the answer, with a notice, so nothing runs that you cannot see. Send a message such as "continue" to pick up from there.
invoke_subagent starts each subagent as its own conversation while the parent turn stays open. The
plugin shows a row per subagent in the parent timeline (type, role, prompt, running until it
finishes) and a child session per subagent following the transcript agy names for it: the prompt,
each tool call with its result, the errors agy recorded in the subagent's run, where its context was
compacted, and the final answer. A child spawned with Workspace: branch runs in
its own git worktree, which becomes that child session's working directory; a Workspace: inherit
child keeps the parent's.
A subagent that starts subagents of its own nests them: its timeline gets a row per grandchild, and
each grandchild is a child session of that subagent, to any depth. agy's stream only names the
conversations the parent started, so these are read from the subagent's own transcript (the result of
its invoke_subagent call). A subagent's session stays open while the subagents it started still run.
The transcript is agy-internal and undocumented, so a child session is best-effort: a missing, unreadable, or unrecognised transcript leaves the row above in place and never affects the parent turn. Following stops when the subagent finishes, the session closes, or the turn is interrupted or fails.
The composer's picker lists the commands this plugin has verified the CLI expands in stream-json
turns; a command is a turn on a CLI launched without --disable-slash-commands, and the next plain
turn relaunches with it.
| Command | Source |
|---|---|
/plan |
Paseo's plan turn, run by the plugin rather than the CLI (Plan mode). |
/goal, /grill-me, /teamwork-preview, /learn, /schedule, /boost, /browser, /compact |
The CLI's own workflows. /learn records a behaviour in the workspace's GEMINI.md, /schedule sets up a recurring run, and /boost and /browser are the deep-thinking and browser-agent flows. /compact (agy 1.3.5) summarizes the conversation to free context, shown as a compaction row; alone it ends the turn without an answer, and text after it is answered once compacted. |
/<name> |
A skill, either in the workspace's customization roots (.agents/skills/<name>/SKILL.md, and the same under .agent/, _agents/, _agent/) or installed for every workspace under ~/.gemini/antigravity-cli/skills/, ~/.gemini/config/skills/, ~/.gemini/skills/, in that precedence. The name is the skill's frontmatter name, and the CLI's own built-ins are listed too. |
<plugin>:<name> |
A plugin's skill, under ~/.gemini/config/plugins/<plugin>/skills/. A plugin holding one skill directly in skills/ is addressed with a .. placeholder: /android-cli-plugin:..:android-cli. A frontmatter name that already starts with <plugin>: is addressed with the prefix once, as agy does: name: firebase:basics is /firebase:basics. |
agy plugin list --json (agy 1.3.4+)
and offers only the skills of enabled plugins that agy reports as loading, so manifests in
.antigravity-plugin/ or .gemini-plugin/, Plugin.json, the manifest's skills field and
skills.json exclusions all count. If the CLI cannot list its plugins, disabled ones are still
left out: "enabled": false in ~/.gemini/config/config.json, or "disabled": true in a root
plugin.json with no config.json entry (an entry there always wins).skills.json (.agents/skills.json, the same file under the other workspace roots, and
~/.gemini/config/skills.json) loads the items directly inside its path, one level deep;
include_only and exclude name those items exactly, a nested one is named by its relative path in
include_only (nested/deep), and a relative path resolves from the repository root. As in
agy 1.2.16, a workspace skills.json is read from every directory between the session's
directory and the repository root, so a session in a monorepo package also lists the root's;
skills/ directories are read from the session's own directory only./compact, /review and /owl are gated server-side, and
commands the CLI answers itself (/skills, /model, …) end a stream-json turn, so both stay out."queuedMessages": "send-immediately", which agy 1.2.14 applies in its terminal UI
only — so Paseo replaces the active turn instead of offering to steer it.--json-schema whose root is not
"type": "object", so such a prompt fails with code: "schema_unsupported" before the CLI is
touched. A root that lists properties without a type gets "type": "object" added.toolPermission setting. Choose the behaviour in session settings./rewind is interactive-only; nothing in stream-json exposes it.~/.agents/skills/) are offered and expanded by the plugin, not the
CLI: the turn is sent the SKILL.md body, capped at 64 KiB (a larger one fails with
code: "skill_too_large").| Setting | Behaviour |
|---|---|
| Tool approval | Default Use Antigravity setting, no flag; Skip all permissions passes --dangerously-skip-permissions. |
| Sandbox | Off/On; On passes --sandbox. |
| Share Paseo tools with Antigravity | Off/On, Off by default — see MCP sharing. |
| Agent profile | An optional select of the custom agents agy has here; Default passes no --agent. |
The select only offers what agy will launch: agents under the workspace's .agents/agents/ and its
global agent roots, <name>.md or <name>/agent.md, with a frontmatter name and description, plus
those an agents.json names — in any workspace root (.agents/agents.json, …) and
~/.gemini/config/agents.json — in the skills.json shape, where a filter names an agent with or
without its .md, an entry may name a single agent file, and ~/ paths are not expanded.
As in agy 1.2.16, the workspace roots of every directory between the session's directory and the
repository root are read, nearest first; outside a repository, only the session's directory.
mainAgent: false agents are skipped, hidden ones are offered, and workspace agents (from either
source) need that exact workspace trusted in antigravity-cli/settings.json (trustedWorkspaces) —
on 1.2.14 a parent directory, the home directory included, trusts nothing below it — using the real
~/.gemini/antigravity-cli/settings.json for the Default account, and each other account's own copy
(Multiple accounts). The agents of an enabled plugin are offered as
agy plugin list --json names them, by their bare name and without workspace trust (agy 1.4.3).
An unknown --agent name
silently runs the default agent, and so does a profile picked after the conversation's first turn:
agy 1.2.14 ignores --agent when it resumes a conversation that started without it. The two Off/On
settings are selects rather than toggles, because a Paseo plugin toggle has no visible state; older
true/false values read as On/Off.
| Option | Effect |
|---|---|
agyPath |
Absolute path to the CLI binary for this session. |
extraArgs, addDirs |
Extra argv appended after the plugin's own flags, and absolute paths each passed as an extra --add-dir (anything else is dropped with a warning notice). |
agent |
Custom agent persona to pass as --agent <name>. The Agent profile setting wins over it. |
effort |
Reasoning effort: the selected model family's tier when it has that tier, the --effort flag when no model is selected, and otherwise dropped with one log line. Never passed alongside --model. |
Your own responsibility. Using the plugin with the Default account — the one sign-in
agyalready has — stays within the terms of service as described there. Whether running several Antigravity accounts side by side is allowed is not clear from the published terms. Use multiple accounts at your own risk.
The sidebar entry Antigravity accounts manages a host-wide active account: the account every new
agent runs under. The screen lists the accounts and marks the active one; pressing an account shows
its settings in the pane below, and that account's Use button makes it the active account — the
active row shows the active badge in place of the button. It also adds, signs in and removes
accounts, and edits the two per-account settings below.
agy ignores HOME (it reads USERPROFILE) and keeps its
sign-in in Windows Credential Manager under one fixed entry, so a second account would share — and
overwrite — Default's sign-in. The screen hides Add account on a Windows daemon.~/.gemini — the account agy already uses in a normal
terminal. It is always listed first, has no directory of its own, and cannot be removed; the plugin
reads and writes about it exactly as it did before multiple accounts existed.agy with HOME pointing at the active account's own home. A
running agent keeps the account it started with: switching changes the next spawn only.HOME set to the account's home; the launcher is sign-in.command in the account's directory, run
with open. Off macOS, or when that hand-off fails, nothing is launched and the screen shows the
exact HOME=… agy line to run on that host instead.agy owns the real file.Each account's card shows what that account has left: one row per pool the CLI reports — for the
accounts seen here, Gemini models and Claude and GPT models, each with a weekly and a 5-hour pool —
with the share left, a bar, the reset time, and a checked HH:MM line (local clock) under the rows.
The figures come from the account's own run of the CLI's print-mode command, spawned under that
account's HOME (Default: the daemon's environment unchanged) from the temp directory:
HOME=<account home> agy -p /usage --output-format json
agy 1.1.11 added non-interactive answers for the read-only slash commands, so the binary answers
/usage without starting an agent turn, without spending quota and without leaving a conversation
behind; the plugin additionally refuses any answer whose num_turns is not 0. The argv is exactly
-p /usage --output-format json — never --disable-slash-commands, which session launches pass
unless slash commands are allowed, and which would stop /usage from expanding and turn it into a
real agent turn that spends quota — and the plugin parses only that command's output. One read takes
a few seconds to about twenty, and writes a normal agy log file in the account's
.gemini/antigravity-cli/log/.
A card reads when the screen is opened and when Refresh is pressed; nothing polls in the
background. The daemon keeps a successful answer for 5 minutes per account and merges concurrent
reads into one process, so reopening the screen is free. While a read runs the card shows Checking
quota…; a signed-out account shows a hint; agy reporting an error is shown with its own message
(for example an account with no quota summary); anything else is an error with Refresh beside it.
The shape of that JSON is not in Antigravity's documentation — it comes from agy's changelog and
observed output — so a future agy may change it, and the card then shows an error instead of wrong
numbers.
An account is a shadow home: a directory that looks like a home directory to the CLI. Its top level
is links into your real home, so the agent's shell keeps seeing your dotfiles, and .gemini is a real
directory whose shared parts link back to the real ~/.gemini:
| Shared with the real home (links) | Per account (its own files and directories) |
|---|---|
Every top-level entry — ~/.ssh, ~/.gitconfig, ~/.npmrc, ~/.agents, … |
.gemini/antigravity-cli/: history, brain, conversation index, and any other state agy writes |
Library (a real directory) minus Keychains, and inside it Library/Preferences minus com.apple.security.plist |
The sign-in, written by agy into the account's own Library/Keychains/account.keychain-db |
.gemini/config — MCP servers, plugins and config/skills |
settings.json — a copy seeded from the real file, edited in the accounts screen |
.gemini/skills and .gemini/antigravity-cli/{skills,agents} |
agy loads and saves its sign-in through the macOS Keychain, and the login Keychain is one slot per
macOS user: a shadow home that could reach it would sign the account in as whoever that Keychain
holds. Each account therefore gets a keychain of its own —
Library/Keychains/account.keychain-db, created with an empty password, made that home's default and
unlocked before every launch. Library/Keychains and Library/Preferences/com.apple.security.plist
(the file that names the default keychain) are the two entries a shadow home never links, so the real
login keychain cannot be reached from an account. The plugin creates and unlocks that keychain; it
never reads or writes what agy puts in it.
Limitations:
gh, or git's osxkeychain helper — finds the
account's (empty) keychain instead and reports no credentials.HOME, but agy sees no keychain of its own.~/.gemini/config/config.json. That is the same file, through the same link, that the Default
account already writes; plain agy is unaffected.Antigravity reads MCP servers from ~/.gemini/config/mcp_config.json and from
<dir>/.agents/mcp_config.json for each directory it was given. With Share Paseo tools with
Antigravity on, the plugin writes Paseo's mcpServers into <cwd>/.agents/mcp_config.json as
paseo-<name> entries before the CLI starts.
.git/info/exclude: git add . then treats it like a .gitignore line and the token in it cannot
be committed by accident. The plugin never edits .gitignore and removes its lines when the last
Paseo session there closes; outside a git work tree, keep the file out of your commits yourself.session.close the plugin removes only its own entries, deletes the file only if it
created it, never overwrites one that is not valid JSON, and agy mcp list will not show these
entries because it reads only your global config — look at <cwd>/.agents/mcp_config.json.Under $PASEO_HOME (default ~/.paseo), in plugin-data/antigravity-cli/:
| Path | Contents |
|---|---|
transcripts/<conversationId>.jsonl |
Timeline rows of a conversation — a subagent's child session under its own id — so history: "replay" can restore them. Not written with persist: false. |
attachments/<sessionId>/ |
Images decoded from prompts, and each uploaded file placed there (a hard link, or a copy across volumes), because a headless agy without allowNonWorkspaceAccess refuses to read a file outside the directories it was given; deleted on session.close, which never touches Paseo's own upload. |
schemas/<sessionId>.json |
The JSON Schema a structured-output turn was launched with; deleted on session.close. |
accounts.json |
The account store: the active account's id and every account's id and name. Missing or unparsable means Default only. |
accounts/<id>/home/ |
The account's shadow home: its links into the real home, its own .gemini (sign-in, history, brain), its keychain and its settings.json. |
accounts/<id>/sign-in.command |
The macOS sign-in launcher written when an account is added or signed in again: export HOME=<shadow home>, unlock the account's keychain, exec agy. Mode 0700. |
It reads, read-only: each account's antigravity-cli/settings.json (~/.gemini for Default, the
shadow home otherwise) and its conversation index antigravity-cli/conversation_summaries.db, plus a
running subagent's transcript.
--sandbox is not demonstrated. The flag is accepted and the turn runs, but with permissive
Antigravity settings a write outside the workspace still succeeded, so the plugin does not claim the
restriction holds.code: "unavailable", and an error result ends the CLI
process, which the next turn relaunches on the same conversation. A 503 that agy retried mid-turn
does not fail the turn: agy still reports such a turn as an error, but when its last step is a
finished answer after the 503, the turn completes, with an info notice.code: "credits_exhausted",
never as retryable, and a notice suggests adding credits or starting a session under another
account: an account is fixed for the life of a session.session.list, but their earlier turns are not replayed.@<subagent>
prompt syntax is terminal-UI only: over stream-json it is an ordinary turn to the parent, which
the parent model may or may not relay, so the plugin offers no way to message a subagent directly.User Skipped, so any tool the model called in the same step as the question has already run. The
card lives in memory: a plugin reload or daemon restart drops it, and you answer in chat instead.
Questions asked inside a subagent, and on a structured-output turn, are not relayed, so agy settles
them itself. The relay reads agy's undocumented transcript file, like subagents do.The Antigravity Additional Terms of Service (checked 2026-09-23) say, in clause 6:
You must not abuse, harm, interfere with, or disrupt the Service. This includes, but is not limited to, using the Service in connection with products not provided by us. Using third party software, tools, or services to access the Service (e.g. using OpenClaw with Antigravity OAuth) is a breach of this Agreement. Such actions may be grounds for suspension or termination of your Antigravity and/or Gemini CLI accounts.
What this plugin does about that: it only launches the official agy binary you installed, and lets
that binary use whatever session it already has. It never reads, stores, forwards, or refreshes
credentials or OAuth tokens, and never talks to Antigravity's APIs itself. Multiple accounts do not
change that: the plugin only chooses which HOME the official agy runs with, and on macOS creates
an empty keychain in that home (empty password, made default and unlocked before each launch) for
agy to write its own sign-in into — the plugin never reads from it. Quota figures are the same
stance: they come from the official binary's own /usage command output
(Usage quota), and the plugin does not read the sign-in token or contact any Google
endpoint for them — unlike a tool that sends the stored token to Google's internal quota API or talks
to the CLI's local language-server port, which this plugin deliberately does not do. The plugin does
read the toolPermission preference and trusted-workspace list, the read-only conversation index,
subagent transcripts, and the output of the agy -p /usage command it runs.
Default account vs. multiple accounts. Using the plugin with only the Default account — the
single sign-in agy already has on your machine — is the case the paragraph above covers: the
official binary, its own session, nothing added. Multiple accounts are a different matter, and it is
not clear whether they comply with the terms. The mechanism is the same (the official binary, a
different HOME, no token handling), but the terms do not say whether one person may run several
Antigravity accounts side by side. Moving between accounts when one runs low could also be read as
getting around usage limits. The Google APIs Terms (§2.d) and
the Google Cloud Acceptable Use Policy both forbid circumventing limits or quotas. The feature is
provided as is. Adding and using more than one account is your own decision and your own
responsibility, including any consequence for the accounts involved.
Access through Gemini Enterprise (Google Cloud), Gemini Enterprise for Business, a Google Workspace subscription on the Google Cloud Pre-GA Offering Terms, or a Gemini Enterprise Agent Platform API Key is governed by the terms your administrator accepted instead, and the clause above does not apply; check with your administrator or Google. This is a description of the terms as published, not legal advice.
Scanned 20 Oct 2026, 12:25 UTC from lefos13/paseo-plugin-antigravity-cli.