Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 | — |

<sub>**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).</sub>
Expand Down Expand Up @@ -185,6 +186,18 @@ codex plugin add aidd-context@aidd-framework # per plugin

</details>

<details>
<summary><strong>Antigravity CLI</strong> — Flat only</summary>

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)

</details>

## 🚀 Quick start

Three ways in — pick one:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
status: pending
status: done
---

<!-- Fill or omit these sections; never add, rename, or reorder one. -->
Expand Down
Original file line number Diff line number Diff line change
@@ -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
---

<!-- Fill or omit these sections; never add, rename, or reorder one. -->
Expand Down
5 changes: 3 additions & 2 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 .",
Expand Down
130 changes: 130 additions & 0 deletions cli/scripts/smoke-antigravity.sh
Original file line number Diff line number Diff line change
@@ -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<!-- aidd_project_memory:start -->\n<!-- aidd_project_memory:end -->\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
2 changes: 1 addition & 1 deletion docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions docs/MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions plugins/aidd-context/hooks/update_memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const TOOL_FILES = {
codex: "AGENTS.md",
cursor: "AGENTS.md",
opencode: "AGENTS.md",
antigravity: "AGENTS.md",
copilot: ".github/copilot-instructions.md",
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Where a skill tree is written, per tool.
| OpenCode | `.opencode/skills/<name>/` |
| GitHub Copilot | `.github/skills/<name>/` |
| Codex CLI | `.agents/skills/<name>/` |
| Antigravity CLI | `.agents/skills/<name>/` |
| Plugin source | `plugins/<plugin>/skills/<name>/` |

## Frontmatter
Expand All @@ -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` |
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ This reference covers project rule generation only. Confirm hosts explicitly; a
| GitHub Copilot | `copilot` | `.github/instructions/<NN>-<name>.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/<slug>.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.

Expand All @@ -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/<category>/<slug>.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.
Expand Down
Loading
Loading