Connectors

Antigravity

Antigravity (`agy`) connector registers all five 2.0 lifecycle hooks in ~/.gemini/config/hooks.json; the empirically verified PreToolUse event provides native ask/deny decisions that override --dangerously-skip-permissions.

The Antigravity connector wires DefenseClaw into Google's Antigravity CLI (binary name agy) via all five Antigravity 2.0 lifecycle hooks installed in ~/.gemini/config/hooks.json using the Claude-Code-compatible nested schema agy v1.0.x evaluates at runtime. DefenseClaw installs the hooks globally so every Antigravity session on the host reports into the same DefenseClaw gateway, while Antigravity continues to talk directly to its configured upstream model provider.

Three scenarios end-to-end against the same agy session: (1) benign `echo` flows through with action=allow / severity=NONE; (2) `cat ~/.ssh/known_hosts` lands on PATH-SSH-DIR HIGH → DefenseClaw returns decision=ask → agy surfaces its native approval prompt and the operator declines; (3) writing a Stripe secret to `.env` matches SEC-STRIPE + PATH-ENV-FILE CRITICAL → DefenseClaw returns decision=deny → agy refuses without prompting. Each verdict appears live in the Splunk pane on the left, including the unmasked `sk_live_…` value because privacy.disable_redaction=true for the demo.

Why ~/.gemini/config/hooks.json and not ~/.gemini/antigravity-cli/hooks.json? The marketing-facing path printed by agy --help (~/.gemini/antigravity-cli/) is silently ignored by agy v1.0.x at runtime — agy actually reads PreToolUse hooks from ~/.gemini/config/hooks.json in a Claude-Code-compatible nested schema. This was determined empirically during the v0.5.0 smoke test: tracer hooks installed at the marketing path never fired; the same entries at the canonical path fired reliably on every tool call. DefenseClaw writes only the canonical path. defenseclaw doctor will surface a migration warning if a stale entry is left behind from a pre-v0.5.0 install at the legacy path.

Setup

defenseclaw setup antigravity                # observe (default) - record only
defenseclaw setup antigravity --mode action  # block on policy hits via hook deny

This connector is global/user-scoped only. DefenseClaw writes a single Antigravity hook entry into ~/.gemini/config/hooks.json and installs the shared hook script at ~/.defenseclaw/hooks/antigravity-hook.sh. Antigravity merges every discovered hooks.json it finds (the canonical ~/.gemini/config/hooks.json, project-local <workspace>/.antigravitycli/hooks.json, and the legacy ~/.gemini/hooks.json), so writing to more than one location causes the same hook to fire multiple times per tool call. To keep the audit trail clean and to avoid double-billing policy evaluations, DefenseClaw deliberately writes only the global file.

There is no proxy-enforcement path for Antigravity — blocking happens hook-side using Antigravity's documented JSON deny response.

The Antigravity connector is hook-only. defenseclaw setup antigravity defaults to observability-only mode=observe, and defenseclaw setup antigravity --mode action enables hook-native blocking. Antigravity still talks directly to its configured upstream model provider in both modes; DefenseClaw never inserts an LLM proxy.

What setup antigravity actually does

The wrapper accepts the same hook-alias flags as the other hook connectors. The underlying guardrail config falls back to the values DefenseClaw ships with — schema-defined in internal/config/config.go and documented on the Defaults page.

FlagDefaultWhat it does
--yes / -yoffSkip the confirmation prompt.
--mode observe|actionobserveobserve records only; action returns Antigravity's documented deny response on policy hits.
--restart / --no-restart--restartBounce defenseclaw-gateway after applying changes so the new hooks wire in.
--with-local-stack / --no-local-stack--no-local-stackAlso bring up the bundled Prom/Loki/Tempo/Grafana stack via setup local-observability up.

setup antigravity is shorthand for setup guardrail --connector antigravity: it adds or reconfigures Antigravity, defaults the connector to observe mode, and can join an existing hook-connector roster when you choose Add. claw.workspace_dir is always cleared — Antigravity setup is global by design. guardrail.mode changes to action only when --mode action is passed. To tune Antigravity after install, keep using defenseclaw setup guardrail --connector antigravity.

Version contract

DefenseClaw validates the installed Antigravity CLI version during setup using the trusted agy --version probe. The Antigravity connector pins a minimum-inclusive version of 1.0.0 and intentionally leaves the upper bound open: agy auto-updates in the background, so a strict ceiling would create a brittle compatibility window. The agy --version output is a bare semver string (e.g. 1.0.1) parsed with the standard semver range matcher.

The current contract is antigravity-hooks-v2 (hook script v7), which expanded coverage from the v1 PreToolUse-only baseline to the full Antigravity 2.0 lifecycle (PreInvocation, PreToolUse, PostToolUse, PostInvocation, Stop). PreToolUse is the only event empirically verified to fire on agy v1.0.1; the other four event branches are spec-conformant but gated on upstream agy implementation parity. Registering all five up front is intentional: when agy starts emitting a previously-quiet event, DefenseClaw handles it with zero redeploy.

Lifecycle events

DefenseClaw registers the full Antigravity 2.0 hook lifecycle. Only PreToolUse is currently advertised through the runtime capability gate as block/ask-capable; the remaining registrations preserve spec parity and telemetry without claiming enforcement that has not been verified.

EventWhen it firesDefenseClaw roleAction verdict → wire shape
PreInvocationJust before the agent calls the LLMRegistered for spec parity and telemetry; not currently advertised as block/ask-capableNon-blocking until upstream event behavior is empirically verified
PreToolUseRight before a tool (run_command, replace_file_content, etc.) executesValidate tool args; intercept risky commandsblock{decision: "deny"}, confirm{decision: "ask"}, alert{systemMessage}; empirically verified on agy v1.0.1
PostToolUseImmediately after a tool finishes executionCapture diagnostics; flag PII / secrets in tool output. Cannot block — tool already ran.alert{additionalContext: "..."} for next-turn ingestion
PostInvocationAfter the LLM call + all associated tool calls finishPost-process model output; flag policy violations in the response. Cannot block — response already generated.alert{additionalContext: "..."}
StopWhen the agent's main execution loop is about to terminateRegistered for spec parity and telemetryNon-blocking until upstream Stop behavior is empirically verified

Post* events never emit deny or ask because the inspected action has already executed at the agent layer. If agy emits those registered events, DefenseClaw's response shaper uses additionalContext for the next turn.

Hook schema

DefenseClaw writes the Claude-Code-compatible nested schema agy v1.0.x evaluates at runtime. The file is a JSON object whose top-level keys are stable, DefenseClaw-owned hook identifiers — one per lifecycle event. Each value is an object keyed by event name, mapping to a list of (matcher, hooks[]) tuples, and each hook in the inner list is a {type, command} record:

{
  "defenseclaw-antigravity-preinvocation": {
    "PreInvocation": [
      { "matcher": "*", "hooks": [ { "type": "command", "command": "/Users/<you>/.defenseclaw/hooks/antigravity-hook.sh" } ] }
    ]
  },
  "defenseclaw-antigravity-pretooluse": {
    "PreToolUse": [
      { "matcher": "*", "hooks": [ { "type": "command", "command": "/Users/<you>/.defenseclaw/hooks/antigravity-hook.sh" } ] }
    ]
  },
  "defenseclaw-antigravity-posttooluse": {
    "PostToolUse": [
      { "matcher": "*", "hooks": [ { "type": "command", "command": "/Users/<you>/.defenseclaw/hooks/antigravity-hook.sh" } ] }
    ]
  },
  "defenseclaw-antigravity-postinvocation": {
    "PostInvocation": [
      { "matcher": "*", "hooks": [ { "type": "command", "command": "/Users/<you>/.defenseclaw/hooks/antigravity-hook.sh" } ] }
    ]
  },
  "defenseclaw-antigravity-stop": {
    "Stop": [
      { "matcher": "*", "hooks": [ { "type": "command", "command": "/Users/<you>/.defenseclaw/hooks/antigravity-hook.sh" } ] }
    ]
  }
}

The command field is a bare absolute path — agy v1.0.x invokes hooks via direct exec() (not through a shell), so any embedded quote characters would be interpreted as literal path bytes and the hook would silently no-fire. Operators with whitespace in their home path should set DEFENSECLAW_HOME to a whitespace-free directory before setup.

When DefenseClaw blocks on the verified PreToolUse event, the hook script returns a flat JSON envelope on stdout:

{ "decision": "deny", "reason": "policy denied" }

On the verified PreToolUse surface, Antigravity recognizes a native "ask" decision that pauses the agent and prompts the operator. A returned "ask" decision bypasses --dangerously-skip-permissions. DefenseClaw maps eligible confirm verdicts to {"decision":"ask"} on that event. The literal string "force_ask" is intentionally not emitted because agy v1.0.0 does not recognize it; the conceptual distinction is preserved in internal raw_action telemetry only.

The response shaper contains the spec-conformant Stop {"decision":"block"} form, but the current capability gate does not classify Stop as blockable. That keeps the docs and advertised enforcement contract pinned to empirically verified behavior.

Local surfaces

hooks.json
mcp_config.json

Antigravity now publishes MCP, skills, rules, and plugin customization surfaces in addition to hooks. DefenseClaw writes hooks only to the global ~/.gemini/config/hooks.json path, reads and writes MCP servers from ~/.gemini/config/mcp_config.json and <workspace>/.agents/mcp_config.json, and supports the AgentSkills folder form under skills/<skill>/SKILL.md. CLI direct-markdown skills, rules, plugins, and plugin-contained agents are treated as discovery/scan surfaces until Google publishes enough install and lifecycle semantics for DefenseClaw to mutate them safely.

claw.workspace_dir is intentionally not honored by Antigravity hook setup. Antigravity merges discovered hooks.json files from the global, project, and legacy locations, so layering DefenseClaw hooks across multiple files would cause duplicate hook firings. Workspace MCP and asset discovery still use the workspace paths above when a workspace is explicitly selected.

The resolved paths are captured in ~/.defenseclaw/hook_contract_lock.json under locations, so defenseclaw doctor can report both the hook contract and the concrete hook location it is using.

Hook capabilities

Block events

  • PreToolUse

Native ask events

  • PreToolUse

Antigravity's verified PreToolUse event has a native unbypassable ask primitive. Returning decision=ask there overrides --dangerously-skip-permissions, so eligible confirm verdicts cannot be silently auto-approved. Do not assume that guarantee for the other four registered lifecycle events until their upstream behavior is verified.

Disable

defenseclaw setup guardrail --disable

Teardown removes all DefenseClaw-owned defenseclaw-antigravity-* entries (one per lifecycle event) from ~/.gemini/config/hooks.json and leaves unrelated hooks untouched. If the file becomes empty after teardown, it is deleted. Teardown does not modify the legacy ~/.gemini/antigravity-cli/hooks.jsondefenseclaw doctor will surface a separate migration warning if a stale entry from a pre-v0.5.0 install is detected there, prompting the operator to remove the file or the obsolete keys manually.