diff --git a/README.md b/README.md
index 362d9c5e1..8b78b5bef 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ Why not just write your own commands? β [FAQ](docs/FAQ.md#-why-aidd-instead-of
## β
Prerequisites
-- **An AI coding tool** β Claude Code (native), or Cursor / Copilot / Codex / OpenCode / Kilo Code (see [Compatibility](#-compatibility)).
+- **An AI coding tool** β Claude Code (native), or Cursor / Copilot / Codex / OpenCode / Kilo Code / Antigravity CLI (see [Compatibility](#-compatibility)).
- **[Node](https://nodejs.org) 22 or later** on your `PATH`, only for the plugin that ships hooks ([what they do](docs/ARCHITECTURE.md#-bundled-hooks)); the workflows themselves are markdown and need nothing.
## π Compatibility
@@ -50,6 +50,7 @@ Why not just write your own commands? β [FAQ](docs/FAQ.md#-why-aidd-instead-of
| **Codex** | β
Supported | Marketplace Β· Flat |
| **OpenCode** | β
Supported | Flat |
| **Kilo Code** | β
Supported | Flat |
+| **Antigravity CLI** | β
Supported | Flat |
| **Gemini Β· Mistral** | π§ In progress | β |
**Marketplace** = installed and updated through your tool's plugin manager. **Flat** = files copied directly into your project, no plugin manager involved. Install steps per tool β [Other tools](#other-tools).
@@ -185,6 +186,18 @@ codex plugin add aidd-context@aidd-framework # per plugin
+
+Antigravity CLI β Flat only
+
+1. Unzip the `antigravity-flat` archive into your project root β `.agents/`: skills, agents, and the memory hook in `.agents/hooks.json`.
+2. Start `agy` in the project. A hook already in `.agents/hooks.json` under another name is kept.
+
+Codex flat also writes `.agents/skills/`: removing one of the two from a project that has both deletes skills the other still uses.
+
+[Docs](https://antigravity.google/docs/cli/overview)
+
+
+
## π Quick start
Three ways in β pick one:
diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md
index c6448f792..50726156e 100644
--- a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md
+++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/phase-5.md
@@ -1,5 +1,5 @@
---
-status: pending
+status: done
---
diff --git a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md
index f634dcd76..3a67151d4 100644
--- a/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md
+++ b/aidd_docs/tasks/2026_10/2026_10_02_antigravity-flat-host/plan.md
@@ -1,6 +1,6 @@
---
objective: "`aidd setup --ai antigravity` and `aidd translate --to antigravity --as flat` write AIDD skills, the memory hook and agents under `.agents/`, which `agy` loads, without touching files AIDD did not write."
-status: in-progress
+status: implemented
---
diff --git a/cli/README.md b/cli/README.md
index eca3691d9..be9c7ca68 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -3,7 +3,7 @@
`@ai-driven-dev/cli` installs AI tool runtime configs, IDE integrations, and plugins from an AIDD marketplace into a project.
Every file it writes is hash-tracked in a manifest, so drift is detected and owned files can be restored.
-Supported AI tools: Claude Code, Cursor, GitHub Copilot, Codex, OpenCode, Kilo Code. Supported IDE: VS Code.
+Supported AI tools: Claude Code, Cursor, GitHub Copilot, Codex, OpenCode, Kilo Code, Antigravity CLI. Supported IDE: VS Code.
Requires Node.js >= 22.12, and `git` to fetch marketplace plugins.
## Install
@@ -153,8 +153,9 @@ Two output layouts, chosen by `--as`:
| `codex` | yes | yes | `.codex/` |
| `opencode` | no | yes | `.opencode/` |
| `kilo` | no | yes | `.kilo/` |
+| `antigravity` | no | yes | `.agents/` |
-OpenCode and Kilo Code declare no marketplace contract, so they are flat only. Every other target accepts both layouts.
+OpenCode, Kilo Code and Antigravity CLI declare no marketplace contract, so they are flat only. Every other target accepts both layouts.
## Environment variables
diff --git a/cli/package.json b/cli/package.json
index fff9fdb34..a716ec8fd 100644
--- a/cli/package.json
+++ b/cli/package.json
@@ -54,6 +54,7 @@
"smoke:full": "pnpm build && SMOKE_REMOTE=1 bash scripts/smoke-tools.sh",
"smoke:real": "pnpm build && bash scripts/smoke-real.sh",
"smoke:collision": "pnpm build && bash scripts/smoke-collision.sh",
+ "smoke:antigravity": "pnpm build && bash scripts/smoke-antigravity.sh",
"typecheck": "tsc --noEmit",
"lint": "biome check .",
"format": "biome format --write .",
diff --git a/cli/scripts/smoke-antigravity.sh b/cli/scripts/smoke-antigravity.sh
new file mode 100755
index 000000000..34c4bec63
--- /dev/null
+++ b/cli/scripts/smoke-antigravity.sh
@@ -0,0 +1,130 @@
+#!/usr/bin/env bash
+# Runtime smoke against a real, logged-in `agy`: after `aidd setup --ai antigravity`, the host
+# loads and fires the project memory hook, expands an AIDD skill, and lists an AIDD agent.
+# Local only, never in CI or lefthook: a turn needs a Google login. `pnpm smoke:antigravity`.
+#
+# The hook sessions run interactive under a pty, killed after a bound: older `agy` fired no hook in
+# print mode (`-p`), and a print turn waits on every user MCP server. Its log and the files it
+# touched are the evidence. HOME stays real for the login; `AIDD_USER_CONFIG_DIR` is relocated so
+# setup never touches the real aidd profile.
+set -uo pipefail
+
+ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+FRAMEWORK="$(cd "$ROOT/.." && pwd)"
+CLI="$ROOT/dist/cli.js"
+TURN_SECONDS="${SMOKE_AGY_TIMEOUT:-60}"
+
+SKILL="aidd-context-11-explore"
+AGENT="aidd-dev-executor"
+GHOST_AGENT="aidd-dev-ghost"
+
+command -v agy >/dev/null 2>&1 || { echo "FATAL: agy not on PATH β install Antigravity CLI and log in"; exit 1; }
+[[ -f "$CLI" ]] || { echo "FATAL: $CLI missing β run 'pnpm build' first"; exit 1; }
+
+TMP="$(mktemp -d)"
+WS="$TMP/project"
+SESSION_PID=""
+cleanup() {
+ if [[ -n "$SESSION_PID" ]]; then
+ pkill -P "$SESSION_PID" 2>/dev/null
+ kill "$SESSION_PID" 2>/dev/null
+ fi
+ rm -rf "$TMP"
+}
+trap cleanup EXIT
+
+export AIDD_USER_CONFIG_DIR="$TMP/aidd-config"
+export AIDD_SKIP_UPDATE_CHECK=1
+
+# Under a pseudo-terminal: util-linux script(1) takes the command as one -c string, BSD as arguments.
+pty_run() {
+ if script --version >/dev/null 2>&1; then
+ script -qec "$(printf '%q ' "$@")" /dev/null
+ else
+ script -q /dev/null "$@"
+ fi
+}
+
+# How many named hooks agy loads, from its log: user-global hooks included.
+hook_count() { grep -Eo 'loaded [0-9]+ named hooks' "$1" 2>/dev/null | head -1 | grep -Eo '[0-9]+'; }
+
+FAIL=0
+pass() { echo " PASS $1"; echo " $2"; }
+fail() { echo " FAIL $1"; FAIL=$((FAIL + 1)); }
+
+echo "agy $(agy --version 2>&1 | head -1), $(date '+%Y-%m-%d %H:%M %Z')"
+
+# A project with a memory bank and an empty memory block, so the hook has something to fill.
+mkdir -p "$WS/aidd_docs/memory"
+printf '# Architecture\n' >"$WS/aidd_docs/memory/architecture.md"
+printf '# Project\n\n## Memory Management\n\n\n\n' >"$WS/AGENTS.md"
+git -C "$WS" init -q
+git -C "$WS" -c user.email=smoke@aidd -c user.name=smoke commit -q --allow-empty -m init
+
+if ! (cd "$WS" && node "$CLI" setup --source local --path "$FRAMEWORK" --ai antigravity --plugins recommended --yes) >"$TMP/setup.log" 2>&1; then
+ echo "FATAL: aidd setup failed"; tail -5 "$TMP/setup.log"; exit 1
+fi
+for f in ".agents/skills/$SKILL/SKILL.md" ".agents/hooks.json" ".agents/agents/$AGENT/agent.md"; do
+ [[ -f "$WS/$f" ]] || { echo "FATAL: setup did not write $f"; exit 1; }
+done
+
+# One interactive session logging to $1, killed once `$2β¦` succeeds or the bound runs out.
+session() {
+ local log="$1"; shift
+ (cd "$WS" && pty_run agy -i "reply OK" --mode plan --add-dir "$WS" --log-file "$log") >"$log.out" 2>&1 &
+ SESSION_PID=$!
+ for ((i = 0; i < TURN_SECONDS; i++)); do
+ "$@" && break
+ sleep 1
+ done
+ pkill -P "$SESSION_PID" 2>/dev/null
+ kill "$SESSION_PID" 2>/dev/null
+ wait "$SESSION_PID" 2>/dev/null
+ SESSION_PID=""
+}
+
+LOG="$TMP/agy-session.log"
+session "$LOG" grep -q 'aidd_docs/memory/architecture.md' "$WS/AGENTS.md"
+
+# Startup logs "not logged into Antigravity" before the stored login is read, so only a missing
+# success line means no login.
+if ! grep -q "OAuth: authenticated successfully" "$LOG" 2>/dev/null; then
+ echo "FATAL: agy is not logged in β run 'agy' once and sign in"; exit 1
+fi
+
+# The log never names a hook, and user-global hooks count too, so the project's own are proven by
+# difference: the same session, in the same mode, without .agents/hooks.json must load fewer.
+BASE_LOG="$TMP/agy-baseline.log"
+[[ -f "$WS/.agents/hooks.json" ]] && mv "$WS/.agents/hooks.json" "$TMP/hooks.json"
+session "$BASE_LOG" grep -qs 'named hooks' "$BASE_LOG"
+[[ -f "$TMP/hooks.json" ]] && mv "$TMP/hooks.json" "$WS/.agents/hooks.json"
+with="$(hook_count "$LOG")"
+without="$(hook_count "$BASE_LOG")"
+if [[ -n "$with" && -n "$without" && "$with" -gt "$without" ]]; then
+ pass "project hooks loaded" "$with named hooks with .agents/hooks.json, $without without"
+else
+ fail "hooks: .agents/hooks.json adds no loaded hook (${with:-?} with, ${without:-?} without)"
+fi
+
+line="$(grep -m1 'aidd_docs/memory/architecture.md' "$WS/AGENTS.md")"
+[[ -n "$line" ]] && pass "memory refreshed at the repo root" "AGENTS.md: $line" || fail "memory: AGENTS.md block still empty, the SessionStart hook did not run at the repo root"
+
+# The expansion is logged before the model answers, so a short bound is enough.
+SKILL_LOG="$TMP/agy-skill.log"
+(cd "$WS" && agy --add-dir "$WS" --mode plan --print-timeout 20s --log-file "$SKILL_LOG" -p "/$SKILL") >/dev/null 2>&1
+line="$(grep -o "expanded slash command \"$SKILL\" (skill)" "$SKILL_LOG" 2>/dev/null | head -1)"
+[[ -n "$line" ]] && pass "skill expanded" "$line" || fail "skill: no 'expanded slash command \"$SKILL\"' line in the agy log"
+
+# Print mode answers /agents without the model.
+AGENTS_JSON="$TMP/agents.json"
+(cd "$WS" && agy --add-dir "$WS" --output-format json --print-timeout "${TURN_SECONDS}s" -p "/agents") >"$AGENTS_JSON" 2>&1
+line="$(grep -o "\"$AGENT\"" "$AGENTS_JSON" | head -1)"
+if [[ -n "$line" ]] && ! grep -q "\"$GHOST_AGENT\"" "$AGENTS_JSON"; then
+ pass "agent listed" "/agents: $line, $GHOST_AGENT absent"
+else
+ fail "agents: /agents does not list \"$AGENT\" (or lists the invented $GHOST_AGENT)"
+fi
+
+echo
+[[ "$FAIL" -eq 0 ]] && { echo "smoke-antigravity: all passed"; exit 0; }
+echo "smoke-antigravity: $FAIL failed"; exit 1
diff --git a/docs/FAQ.md b/docs/FAQ.md
index f7e4ae3e8..33bff5069 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -11,7 +11,7 @@ You can write your own Claude Code skills β nothing stops you. AIDD exists bec
- **Install / first run** β [Quick start](../README.md#-quick-start).
- **Update plugins** β `/plugin marketplace update aidd-framework`, or see [Versioning & updates](MARKETPLACE.md#-versioning--updates).
- **Private repo?** Yes β `/plugin marketplace add` just needs GitHub read access (via `gh auth login` or a PAT).
-- **Cursor / Copilot / Codex / OpenCode / Kilo Code?** Each other tool installs via its own native mechanism (project files, local plugins, or a plugin command) from the [release](https://github.com/ai-driven-dev/framework/releases/latest) archives. Steps per tool β [Other tools](../README.md#other-tools).
+- **Cursor / Copilot / Codex / OpenCode / Kilo Code / Antigravity CLI?** Each other tool installs via its own native mechanism (project files, local plugins, or a plugin command) from the [release](https://github.com/ai-driven-dev/framework/releases/latest) archives. Steps per tool β [Other tools](../README.md#other-tools).
## πΈ Cost and quotas
diff --git a/docs/MAINTAINERS.md b/docs/MAINTAINERS.md
index 6ae24b5c2..d6881336b 100644
--- a/docs/MAINTAINERS.md
+++ b/docs/MAINTAINERS.md
@@ -148,6 +148,7 @@ Roles, promotion, and inactivity rules β [`GOVERNANCE.md`](../GOVERNANCE.md#-r
- The marketplace is Claude Code native.
- Other tools are served by per-release archives the `aidd-cli` builds; this repo stays Claude-authored and tool-agnostic in its prose.
- Keep tool-specific detail in plugin READMEs.
+- Antigravity CLI has no runtime check in CI: a turn needs a Google login. Before a release that touches its profile, run `cd cli && pnpm smoke:antigravity` on a machine where `agy` is logged in. It installs AIDD into a throwaway project, then checks the `agy` log for a skill expansion and the loaded hooks, the project memory for the hook's refresh, and `/agents` for an AIDD agent.
## π§± Build your own plugin
diff --git a/plugins/aidd-context/hooks/update_memory.js b/plugins/aidd-context/hooks/update_memory.js
index 2cfb4ba01..2f7677272 100644
--- a/plugins/aidd-context/hooks/update_memory.js
+++ b/plugins/aidd-context/hooks/update_memory.js
@@ -42,6 +42,7 @@ const TOOL_FILES = {
codex: "AGENTS.md",
cursor: "AGENTS.md",
opencode: "AGENTS.md",
+ antigravity: "AGENTS.md",
copilot: ".github/copilot-instructions.md",
};
diff --git a/plugins/aidd-context/skills/00-onboard/references/state/detection.md b/plugins/aidd-context/skills/00-onboard/references/state/detection.md
index f66011153..a8c0d4275 100644
--- a/plugins/aidd-context/skills/00-onboard/references/state/detection.md
+++ b/plugins/aidd-context/skills/00-onboard/references/state/detection.md
@@ -10,6 +10,7 @@ A tool is used when its own dir exists, or when a file only that tool reads exis
| codex | `.codex/` | `AGENTS.md` |
| cursor | `.cursor/` or `.cursorrules` | `AGENTS.md` |
| opencode | `.opencode/` | `AGENTS.md` |
+| antigravity | `.agents/agents/`, `.agents/rules/` or `.agents/hooks.json` | `AGENTS.md` |
| copilot | `.github/copilot-instructions.md` or `.github/{instructions,agents,skills,prompts}/` | `.github/copilot-instructions.md` |
- Detected tools only. An unused optional tool is omitted, never crossed.
diff --git a/plugins/aidd-context/skills/02-project-memory/references/tools.md b/plugins/aidd-context/skills/02-project-memory/references/tools.md
index 4b90d76d1..f25dc0bbe 100644
--- a/plugins/aidd-context/skills/02-project-memory/references/tools.md
+++ b/plugins/aidd-context/skills/02-project-memory/references/tools.md
@@ -8,6 +8,7 @@ The AI tools a project can use.
| codex | `.codex/` | `AGENTS.md` |
| cursor | `.cursor/` or `.cursorrules` | `AGENTS.md` |
| opencode | `.opencode/` | `AGENTS.md` |
+| antigravity | `.agents/agents/`, `.agents/rules/` or `.agents/hooks.json` | `AGENTS.md` |
| copilot | `.github/copilot-instructions.md` or `.github/{instructions,agents,skills,prompts}/` | `.github/copilot-instructions.md` |
- A shared `AGENTS.md` is a wiring target, never a detection signal.
diff --git a/plugins/aidd-context/skills/04-skill-generate/references/tool-detect.md b/plugins/aidd-context/skills/04-skill-generate/references/tool-detect.md
index 286dbc7a3..94fbe2467 100644
--- a/plugins/aidd-context/skills/04-skill-generate/references/tool-detect.md
+++ b/plugins/aidd-context/skills/04-skill-generate/references/tool-detect.md
@@ -9,5 +9,6 @@ Which AI tools a project has installed.
| OpenCode | `.opencode/` |
| GitHub Copilot | `.github/copilot-instructions.md` |
| Codex CLI | `.codex/` |
+| Antigravity CLI | `.agents/agents/`, `.agents/rules/` or `.agents/hooks.json` |
-A bare `AGENTS.md` means Cursor, OpenCode, or Codex. Several signals can coexist.
+A bare `AGENTS.md` means Cursor, OpenCode, Codex, or Antigravity CLI. `.agents/skills/` alone is no signal: Codex and Antigravity CLI both read it. Several signals can coexist.
diff --git a/plugins/aidd-context/skills/04-skill-generate/references/tool-write.md b/plugins/aidd-context/skills/04-skill-generate/references/tool-write.md
index 2863f4ccd..852aa9f06 100644
--- a/plugins/aidd-context/skills/04-skill-generate/references/tool-write.md
+++ b/plugins/aidd-context/skills/04-skill-generate/references/tool-write.md
@@ -11,6 +11,7 @@ Where a skill tree is written, per tool.
| OpenCode | `.opencode/skills//` |
| GitHub Copilot | `.github/skills//` |
| Codex CLI | `.agents/skills//` |
+| Antigravity CLI | `.agents/skills//` |
| Plugin source | `plugins//skills//` |
## Frontmatter
@@ -23,3 +24,4 @@ Emit `description` always, `name` only where listed, drop the rest.
| Cursor, GitHub Copilot | `name`, `description`, opt `allowed-tools` |
| OpenCode | `description`, opt `permission` map |
| Codex CLI | `name`, `description` (strips the rest) |
+| Antigravity CLI | `name`, `description` |
diff --git a/plugins/aidd-context/skills/05-rule-generate/references/tool-paths.md b/plugins/aidd-context/skills/05-rule-generate/references/tool-paths.md
index b8e6338b2..7c30334b5 100644
--- a/plugins/aidd-context/skills/05-rule-generate/references/tool-paths.md
+++ b/plugins/aidd-context/skills/05-rule-generate/references/tool-paths.md
@@ -11,12 +11,13 @@ This reference covers project rule generation only. Confirm hosts explicitly; a
| GitHub Copilot | `copilot` | `.github/instructions/-.instructions.md` | comma-joined `applyTo`; `**` for all files |
| Codex | `codex` | root `AGENTS.md`, shared signed `aidd_rules` contribution | scopes are instructions to the model |
| OpenCode | `opencode` | the same contribution in root `AGENTS.md` | scopes are instructions to the model |
+| Antigravity CLI | `antigravity` | `.agents/rules/.md` | with paths: `trigger: glob`, `description`, comma-joined `globs`; without: `trigger: always_on`, `description`, no `globs` |
-Use taxonomy and `#-slug` naming in [rule-authoring.md](rule-authoring.md). Copilot drops the slug's single-digit prefix and adds the category's two-digit prefix, e.g. `01-standards/1-naming` becomes `01-naming.instructions.md`.
+Use taxonomy and `#-slug` naming in [rule-authoring.md](rule-authoring.md). Copilot drops the slug's single-digit prefix and adds the category's two-digit prefix, e.g. `01-standards/1-naming` becomes `01-naming.instructions.md`. Antigravity reads only the direct `.md` children of `.agents/rules/`, so it drops the category folder and keeps the slug, e.g. `1-naming.md`; the slug's category digit keeps that flat name unique. Measured, `agy` truncates a rule file near 23 to 25 KB, so a rendered Antigravity rule over 24,000 bytes refuses the request before writes. Whether `agy` activates a `glob` rule only on matching files is unmeasured.
Codex Markdown guidance is not a `.codex/rules` execution policy. OpenCode: write the root `AGENTS.md` only, never `.opencode/rules`. Native syntax tests prove rendering, not runtime consumption by every host. Codex/OpenCode selected together appear once in the shared file; other hosts may also discover AGENTS.md, so physical deduplication does not guarantee model-context deduplication across surfaces.
-Official contracts: [Claude Code rules](https://code.claude.com/docs/en/memory#organize-rules-with-clauderules), [Cursor rules](https://cursor.com/docs/rules) and [CLI loading](https://cursor.com/docs/cli/using#rules), [Copilot CLI instructions](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-custom-instructions), [Codex AGENTS.md](https://learn.chatgpt.com/docs/agent-configuration/agents-md), [OpenCode rules](https://opencode.ai/docs/rules/) and [instructions](https://opencode.ai/v2/docs/instructions/).
+Official contracts: [Claude Code rules](https://code.claude.com/docs/en/memory#organize-rules-with-clauderules), [Cursor rules](https://cursor.com/docs/rules) and [CLI loading](https://cursor.com/docs/cli/using#rules), [Copilot CLI instructions](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-custom-instructions), [Codex AGENTS.md](https://learn.chatgpt.com/docs/agent-configuration/agents-md), [OpenCode rules](https://opencode.ai/docs/rules/) and [instructions](https://opencode.ai/v2/docs/instructions/), [Antigravity rules](https://antigravity.google/docs/rules).
Publication does not force a running host to reload. Verify changed rules in a fresh session: Codex builds its instruction chain at startup; Copilot applies edits to a new or resumed session. OpenCode V2 refreshes ambient AGENTS.md before the next request, but already loaded nested guidance needs a new session. Claude project rules require the `project` settings source; Cursor rules concern Agent rather than Tab or Inline Edit. The writer preserves patterns without implementing each host's glob parser; a syntactically invalid or unmatched pattern can activate no files. Confirm representative matching and nonmatching files in the selected host.
@@ -41,9 +42,9 @@ Prepare a JSON request outside the project rule destinations:
Use an absolute real project directory and confirmed comma-separated script IDs:
```sh
-node "$installed_rule_script" --project "$project_root" --tools claude,cursor,copilot,codex,opencode --input "$request_json"
-node "$installed_rule_script" --project "$project_root" --tools claude,cursor,copilot,codex,opencode --publish
-node "$installed_rule_script" --project "$project_root" --tools claude,cursor,copilot,codex,opencode --delete 01-standards/1-naming
+node "$installed_rule_script" --project "$project_root" --tools claude,cursor,copilot,codex,opencode,antigravity --input "$request_json"
+node "$installed_rule_script" --project "$project_root" --tools claude,cursor,copilot,codex,opencode,antigravity --publish
+node "$installed_rule_script" --project "$project_root" --tools claude,cursor,copilot,codex,opencode,antigravity --delete 01-standards/1-naming
```
Create/update records confirmed targets in `aidd_docs/rules//.md`. Publish synchronizes the named native hosts and the complete shared contribution from canonical targets; delete also cleans the deleted rule's previous targets. Updating targets cleans removed targets. JSON accepts exactly category, slug, description, optional paths and body. Empty/omitted paths mean all files. Reject comma-containing globs (including brace alternations) rather than serialize ambiguous native lists; supply separate globs. Description is one line. Body is preserved completely and must not begin with YAML frontmatter. Scope belongs in JSON, never an arbitrary YAML parser.
diff --git a/plugins/aidd-context/skills/05-rule-generate/scripts/write-rule.cjs b/plugins/aidd-context/skills/05-rule-generate/scripts/write-rule.cjs
index e7f1d0c9c..dcbf9c019 100644
--- a/plugins/aidd-context/skills/05-rule-generate/scripts/write-rule.cjs
+++ b/plugins/aidd-context/skills/05-rule-generate/scripts/write-rule.cjs
@@ -6,7 +6,7 @@ const fs = require("node:fs");
const path = require("node:path");
const { createHash, randomUUID } = require("node:crypto");
-const TOOLS = ["claude", "cursor", "copilot", "codex", "opencode"];
+const TOOLS = ["claude", "cursor", "copilot", "codex", "opencode", "antigravity"];
const CATEGORIES = ["architecture", "standards", "programming-languages", "frameworks-and-libraries", "tooling", "testing", "design-patterns", "quality", "domain", "other"];
const SHARED = ["codex", "opencode"];
const SOURCE = "aidd_docs/rules";
@@ -36,7 +36,7 @@ function options(args) {
function tools(value) {
const selected = typeof value === "string" ? value.split(",") : value;
- if (!Array.isArray(selected) || !selected.length || new Set(selected).size !== selected.length || selected.some((tool) => !TOOLS.includes(tool))) fail("Targets must be distinct confirmed tools: claude,cursor,copilot,codex,opencode.");
+ if (!Array.isArray(selected) || !selected.length || new Set(selected).size !== selected.length || selected.some((tool) => !TOOLS.includes(tool))) fail("Targets must be distinct confirmed tools: claude,cursor,copilot,codex,opencode,antigravity.");
return [...selected].sort();
}
@@ -107,6 +107,8 @@ function nativePath(rule, tool) {
const id = identity(rule.category, rule.slug);
if (tool === "claude") return `.claude/rules/${id}.md`;
if (tool === "cursor") return `.cursor/rules/${id}.mdc`;
+ // Antigravity loads only direct children; the slug's category digit keeps the flat name unique.
+ if (tool === "antigravity") return `.agents/rules/${rule.slug}.md`;
return `.github/instructions/${rule.category.slice(0, 2)}-${rule.slug.slice(2)}.instructions.md`;
}
@@ -116,9 +118,12 @@ function renderNative(rule, tool, signed = true) {
if (tool === "claude") fields = rule.paths.length ? `paths:\n${rule.paths.map((glob) => ` - ${quote(glob)}\n`).join("")}` : "";
if (tool === "cursor") fields = `description: ${quote(rule.description)}\n${rule.paths.length ? `globs: ${quote(rule.paths.join(","))}\n` : ""}alwaysApply: ${!rule.paths.length}\n`;
if (tool === "copilot") fields = `applyTo: ${quote(rule.paths.length ? rule.paths.join(",") : "**")}\n`;
+ if (tool === "antigravity") fields = `trigger: ${rule.paths.length ? "glob" : "always_on"}\ndescription: ${quote(rule.description)}\n${rule.paths.length ? `globs: ${quote(rule.paths.join(","))}\n` : ""}`;
const text = (fields ? `---\n${fields}---\n` : "") + rule.body;
safeText(text);
- return signed ? `${text}\n\n` : text;
+ const output = signed ? `${text}\n\n` : text;
+ if (tool === "antigravity" && Buffer.byteLength(output) > 24000) fail("Antigravity rule exceeds its 24,000-byte per-file limit.");
+ return output;
}
function ownedNative(existing, prior, tool, relative) {
diff --git a/plugins/aidd-context/skills/06-agent-generate/references/tool-paths.md b/plugins/aidd-context/skills/06-agent-generate/references/tool-paths.md
index 90a1badde..a01c4f9d9 100644
--- a/plugins/aidd-context/skills/06-agent-generate/references/tool-paths.md
+++ b/plugins/aidd-context/skills/06-agent-generate/references/tool-paths.md
@@ -11,8 +11,9 @@ The per-tool agent path and the gate every run executes before writing. Agent sl
| OpenCode | `.opencode/agents/.md` | markdown + frontmatter |
| GitHub Copilot | `.github/agents/.agent.md` | markdown + frontmatter |
| Codex CLI | `.codex/agents/.toml` | TOML (converted) |
+| Antigravity CLI | `.agents/agents//agent.md` | markdown + frontmatter |
-Agents are supported on all five tools.
+Agents are supported on all six tools.
## Frontmatter per tool
@@ -25,6 +26,9 @@ The canonical agent carries `name` and `description`. Emit those a row accepts,
| OpenCode | `name`, `description`, optional `model`, `temperature`, `permission` |
| GitHub Copilot | `name`, `description`, optional `model`, `tools` |
| Codex CLI | `name`, `description` (drops `model`) |
+| Antigravity CLI | `name`, `description`, `model: inherit`, optional `tools` as a YAML list |
+
+`agy` drops in silence an agent whose `model` is not `inherit`, `flash` or `pro`, or whose `tools` is a comma-separated string.
## Codex TOML conversion
@@ -43,7 +47,8 @@ Codex agents are TOML, not markdown. Convert:
| `.opencode/` | OpenCode |
| `.codex/` | Codex CLI |
| `.github/copilot-instructions.md` | GitHub Copilot |
-| `AGENTS.md` | Cursor, OpenCode, or Codex (list all) |
+| `.agents/agents/`, `.agents/rules/` or `.agents/hooks.json` | Antigravity CLI |
+| `AGENTS.md` | Cursor, OpenCode, Codex, or Antigravity CLI (list all) |
## Write targets
diff --git a/plugins/aidd-context/skills/08-hook-generate/references/tool-paths.md b/plugins/aidd-context/skills/08-hook-generate/references/tool-paths.md
index 48b1d19ef..0757af487 100644
--- a/plugins/aidd-context/skills/08-hook-generate/references/tool-paths.md
+++ b/plugins/aidd-context/skills/08-hook-generate/references/tool-paths.md
@@ -11,6 +11,7 @@ Per-tool hook support, event names, file formats, and scopes. Hook slice only: n
| Cursor | yes | JSON config + script. |
| GitHub Copilot | yes | JSON config + script. Also reads Claude's `.claude/` config. |
| OpenCode | no | Hooks are JS/TS plugin modules, not config. Skip with the reason below. |
+| Antigravity CLI | yes | JSON config + script. Project scope only here, see below. |
**OpenCode skip reason.** OpenCode hooks are code, not a config entry plus a script. Point the user to write a plugin under `.opencode/plugins/` (project) or `~/.config/opencode/plugins/` (user), per `https://opencode.ai/docs/plugins`. This skill does not generate it.
@@ -29,6 +30,8 @@ Each tool names the same moment differently and supports a different subset. Cor
| turn stop | `Stop` | `Stop` | `stop` | `Stop` |
| session end | `SessionEnd` | `SessionEnd` | `sessionEnd` | `SessionEnd` |
+Antigravity CLI documents `PreToolUse`, `PostToolUse`, `PreInvocation`, `PostInvocation` and `Stop`; `SessionStart` works on `agy` 1.2.17 but is undocumented. Its tool names differ from Claude's, so a `matcher` never carries over.
+
Each tool exposes more moments than these. For the full list, read the tool's docs: Claude `https://code.claude.com/docs/en/hooks`, Codex `https://developers.openai.com/codex/hooks`, Cursor `https://cursor.com/docs/hooks`, Copilot `https://docs.github.com/en/copilot/reference/hooks-configuration`. Confirm a moment exists before wiring it. Copilot also accepts the camelCase names (`sessionStart`, `preToolUse`).
## File and format per tool
@@ -39,9 +42,12 @@ Each tool exposes more moments than these. For the full list, read the tool's do
| Codex CLI | `~/.codex/hooks.json` or `[hooks]` in `config.toml` | same entry shape as Claude. |
| Cursor | `.cursor/hooks.json` | `{ "version": 1, "hooks": { "": [ { "command": "..." } ] } }` |
| GitHub Copilot | `.github/hooks/*.json` or a `hooks` block in `.github/copilot/settings.json` | `{ "version": 1, "hooks": { "": [ { "type": "command", "command": "..." } ] } }` |
+| Antigravity CLI | `.agents/hooks.json` | `{ "": { "": [ { "type": "command", "command": "..." } ] } }`, no `hooks` wrapper; a `matcher` entry only for `PreToolUse` and `PostToolUse` |
A Claude `settings.json` and a plugin or standalone `hooks/hooks.json` both wrap the event map under a top-level `hooks` key, so the file is `{ "hooks": { "": [ ... ] } }`. A Codex `config.toml` uses a `[hooks]` table instead.
+An Antigravity CLI handler runs from `/.agents`, through a shell: prefix a root-relative command with `cd .. && `. `agy` rejects a Claude-style nested `[ { "hooks": [ ... ] } ]` with `command hook must specify 'command'`.
+
## Scopes per tool
Ask the user which scope, then write the matching file. A `-` means the tool has no such scope.
@@ -81,4 +87,4 @@ Written as `${VAR}` inside a command: `CLAUDE_PROJECT_DIR` (project root), `CLAU
- **Asset-access precheck.** Before writing, confirm this reference is readable. If not, stop: the plugin is not installed in this host.
- **Merge check.** Before writing, read the target file and confirm the new entry is appended to the moment's list, never overwriting a sibling.
-- **Write-target validation.** After writing, confirm the file is valid and every handler path is an approved `${VAR}` or an absolute path under the workspace (a hook command runs from an arbitrary cwd, so an absolute path or `${VAR}` is expected, not a relative one). Otherwise stop and report.
+- **Write-target validation.** After writing, confirm the file is valid and every handler path is an approved `${VAR}` or an absolute path under the workspace (a hook command runs from an arbitrary cwd, so an absolute path or `${VAR}` is expected, not a relative one; Antigravity CLI's `cd .. && ` prefix is the one relative form, since its cwd is fixed). Otherwise stop and report.
diff --git a/plugins/aidd-context/skills/10-learn/references/sync-arguments.md b/plugins/aidd-context/skills/10-learn/references/sync-arguments.md
index 5c3bc2e9a..f2f9f08b5 100644
--- a/plugins/aidd-context/skills/10-learn/references/sync-arguments.md
+++ b/plugins/aidd-context/skills/10-learn/references/sync-arguments.md
@@ -8,6 +8,7 @@ Arguments accepted by `hooks/update_memory.js`. The hook maps tool names to cont
| `codex` | `AGENTS.md` |
| `cursor` | `AGENTS.md` |
| `opencode` | `AGENTS.md` |
+| `antigravity` | `AGENTS.md` |
| `copilot` | `.github/copilot-instructions.md` |
Rules:
diff --git a/plugins/aidd-context/skills/11-explore/references/ai-mapping.md b/plugins/aidd-context/skills/11-explore/references/ai-mapping.md
index 5e0a7065d..028236d27 100644
--- a/plugins/aidd-context/skills/11-explore/references/ai-mapping.md
+++ b/plugins/aidd-context/skills/11-explore/references/ai-mapping.md
@@ -4,7 +4,7 @@ Where to look for each artifact type per AI tool. Scan-only: the paths and forma
## Presence signal
-A tool is present only when one of its own mapped surfaces below holds a file. A shared parent directory is never a signal by itself.
+A tool is present only when one of its own mapped surfaces below holds a file. A shared parent directory is never a signal by itself. `.agents/skills/` is mapped for both Codex CLI and Antigravity CLI, so alone it is no signal for either.
## AI quick map - content artifacts
@@ -15,6 +15,7 @@ A tool is present only when one of its own mapped surfaces below holds a file. A
| OpenCode | `.opencode/agents/` | `.opencode/commands/` | `aidd_docs/rules/` (canonical sources); shared `aidd_rules` contribution in root `AGENTS.md` | `.opencode/skills/` | `AGENTS.md` |
| GitHub Copilot | `.github/agents/*.agent.md` | `.github/prompts/*.prompt.md` | `.github/instructions/*.instructions.md` | `.github/skills/` | `.github/copilot-instructions.md` |
| Codex CLI | `.codex/agents/{name}.toml` | **Not supported** | `aidd_docs/rules/` (canonical sources); shared `aidd_rules` contribution in root `AGENTS.md`, not execution policies | `.agents/skills/aidd-{name}/SKILL.md` | `AGENTS.md` |
+| Antigravity CLI | `.agents/agents/{name}/agent.md` | Not mapped | `.agents/rules/.md`, flat | `.agents/skills/aidd-{name}/SKILL.md` | `AGENTS.md` |
## AI quick map - hooks, plugins
@@ -25,6 +26,7 @@ A tool is present only when one of its own mapped surfaces below holds a file. A
| OpenCode | JS/TS module under `.opencode/plugins/` (parse as JS, not JSON) | Not supported |
| GitHub Copilot | `.github/hooks/*.json` (workspace), `~/.copilot/hooks` (user), `/hooks.json` or `/hooks/hooks.json` (plugin) | `plugin.json` at plugin root |
| Codex CLI | `.codex/hooks.json` (project / user) OR `[hooks]` table in `.codex/config.toml` | `.codex-plugin/plugin.json` |
+| Antigravity CLI | `.agents/hooks.json` (project), keyed by hook name | `plugin.json` at plugin root |
## MCP config per tool
@@ -57,3 +59,4 @@ Where to scan when enumerating installed plugins (not the plugin manifest path i
| OpenCode | `~/.config/opencode/plugins/` (global JS/TS modules); `~/.cache/opencode/node_modules/` (npm-installed); project `.opencode/plugins/` |
| GitHub Copilot | macOS: `~/Library/Application Support/Code/agentPlugins/` ; Linux: `~/.config/Code/agentPlugins/` ; Windows: `%APPDATA%\Code\agentPlugins\` ; CLI-installed: `~/.copilot/installed-plugins/` |
| Codex CLI | `~/.codex/plugins/cache/$MARKETPLACE/$PLUGIN/$VERSION/` |
+| Antigravity CLI | Unmeasured: `~/.gemini/config/plugins//` (`agy plugin install`) and project `.agents/plugins/` are assumed, not observed |
diff --git a/scripts/__tests__/rule-generation.test.js b/scripts/__tests__/rule-generation.test.js
index a387f554f..5b8621ec2 100644
--- a/scripts/__tests__/rule-generation.test.js
+++ b/scripts/__tests__/rule-generation.test.js
@@ -65,11 +65,12 @@ for (const paths of [[], ["src/domain/**/*.ts", 'tests/quoted"name/**/*.ts']]) t
const f = fixture(t);
const description = 'Review "domain": naΓ―ve \\ conventions #1';
const body = "# Review\r\n\r\n- Preserve exact text: cafΓ© β.\r\n";
- assert.equal(f.run({ ...rule, description, paths, body }, "claude,cursor,copilot").status, 0);
+ assert.equal(f.run({ ...rule, description, paths, body }, "claude,cursor,copilot,antigravity").status, 0);
const documents = [
[".claude/rules/01-standards/1-naming.md", paths.length ? { paths } : null],
[".cursor/rules/01-standards/1-naming.mdc", { description, ...(paths.length ? { globs: paths.join(",") } : {}), alwaysApply: !paths.length }],
[".github/instructions/01-naming.instructions.md", { applyTo: paths.length ? paths.join(",") : "**" }],
+ [".agents/rules/1-naming.md", paths.length ? { trigger: "glob", description, globs: paths.join(",") } : { trigger: "always_on", description }],
];
for (const [name, expected] of documents) {
const text = f.read(name);
@@ -309,6 +310,13 @@ for (const target of ["aidd_docs/rules", ".claude/rules", "AGENTS.md"]) test(`sy
assert.deepEqual(f.snapshot(), before);
});
+test("Antigravity's 24,000-byte rule file limit refuses prospective writes", (t) => {
+ const f = fixture(t);
+ const before = f.snapshot();
+ assert.notEqual(f.run({ ...rule, body: "x".repeat(24000) }, "antigravity").status, 0);
+ assert.deepEqual(f.snapshot(), before);
+});
+
test("Codex override and local 32 KiB limit refuse prospective writes", (t) => {
const f = fixture(t);
f.put("AGENTS.override.md", "override");
diff --git a/scripts/__tests__/update-memory.test.js b/scripts/__tests__/update-memory.test.js
index fc9440cf4..2f38a170f 100644
--- a/scripts/__tests__/update-memory.test.js
+++ b/scripts/__tests__/update-memory.test.js
@@ -167,6 +167,17 @@ test("an unknown tool name is rejected", () => {
assert.match(result.stderr, /unknown tool emacs/u);
});
+test("antigravity refreshes AGENTS.md, the context file agy reads", () => {
+ const result = run({
+ context: `${OPEN}\n${CLOSE}\n`,
+ contextAt: "AGENTS.md",
+ args: ["antigravity"],
+ });
+
+ assert.equal(result.status, 0);
+ assert.match(result.content, /^\[aidd_docs\/memory\/architecture\.md\]\(aidd_docs\/memory\/architecture\.md\)$/mu);
+});
+
test("a new-marker pair quoted in prose above the block does not hijack the splice", () => {
const quote = `Upgrade note: the block now uses \`${OPEN}\` and \`${CLOSE}\`.`;
const result = run({ context: `${quote}\n\n${OPEN}\n${CLOSE}\n` });