Connectors

Antigravity

Antigravity (`agy`) connector registers all five 2.0 lifecycle hooks. PreInvocation and PreToolUse are ask-capable; PreInvocation, PreToolUse, and Stop are block-capable in the current contract.

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) a benign command flows through with action=allow / severity=NONE; (2) a sensitive-file read lands on a HIGH finding → DefenseClaw returns decision=ask → agy surfaces its native approval prompt and the operator declines; (3) writing a synthetic secret to an environment file matches a CRITICAL finding → DefenseClaw returns decision=deny → agy refuses without prompting. Each verdict appears live in the Splunk pane on the left. This historical demo used an unredacted destination projection; current v8 deployments select an explicit redaction profile per destination or route.

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

Antigravity setup is supported on macOS and Linux. The DefenseClaw connector is not certified on native Windows x64, so setup rejects it there.

This connector is global/user-scoped only. DefenseClaw writes five owned entries—one per lifecycle event—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 global file, project-local <workspace>/.antigravitycli/hooks.json, and legacy ~/.gemini/hooks.json), so writing the same handlers to more than one location causes duplicate firings. 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 the event's declared native deny/block 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 run setup local-observability up; follow the command's printed gateway-restart step after it writes the export destination.

setup antigravity is the dedicated Antigravity alias. It uses the shared guardrail setup backend, defaults to observe mode, and can join an existing hook-connector roster when you choose Add. claw.workspace_dir is cleared because Antigravity hook setup is global by design. See the quick-alias reference for the common options and full guardrail setup for advanced scanner and judge configuration.

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. After setup selects antigravity-hooks-v2, that pinned runtime profile advertises PreInvocation and PreToolUse as ask-capable, and PreInvocation, PreToolUse, and Stop as block-capable. Only PreToolUse has been empirically verified against agy v1.0.1; the other four branches follow the published contract but still depend on upstream agy implementation parity.

Use hook_contract_lock.json or defenseclaw doctor to identify the contract actually pinned on a host.

EventWhen it firesDefenseClaw roleAction verdict → wire shape
PreInvocationJust before the agent calls the LLMInspect the prompt before the model callblock{decision: "deny"}, eligible confirm{decision: "ask"}; spec-conformant, not yet 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 terminateRecord the stop reason and honor a block verdictblock{decision: "block"}; spec-conformant, not yet 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 a pre-action event, the hook script returns a flat JSON envelope on stdout:

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

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 PreInvocation and PreToolUse; only the latter has been empirically verified against agy v1.0.1. The literal string "force_ask" is intentionally not emitted because agy v1.0.0 does not recognize it; the conceptual distinction is preserved in raw_action telemetry.

Stop uses the spec-conformant {"decision":"block"} form rather than the "deny" verb used by pre-action events. PostToolUse and PostInvocation never block.

Local surfaces

hooks.json
mcp_config.json

Antigravity 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 read/write installation of the AgentSkills folder form under skills/<skill>/SKILL.md. Rules and plugins are discovery/scan-only: DefenseClaw reads plugin roots under ~/.gemini/config/plugins/, <workspace>/.agents/plugins/, and the CLI-managed ~/.gemini/antigravity-cli/plugins/, but does not install or disable Antigravity plugins. CLI direct-markdown skills and plugin-contained agents are also discovery/scan-only.

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

The authoritative contract is antigravity-hooks-v2: ask on PreInvocation and PreToolUse; block on PreInvocation, PreToolUse, and Stop; fail-closed transport is not supported. PostToolUse and PostInvocation are observe/context-only.

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. PreInvocation has the same advertised ask shape but has not yet been empirically verified against agy v1.0.1.

Disable

defenseclaw guardrail disable --connector antigravity --yes

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.