From e9ad692418c631c1eaed8b7a69b20a7f9f9ea648 Mon Sep 17 00:00:00 2001 From: Mathias Bergqvist Date: Sun, 30 Aug 2026 08:58:34 +0200 Subject: [PATCH] feat(install): re-add Antigravity as a wiring target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Antigravity discovers skills via a path-entries JSON (~/.gemini/config/skills.json), not a symlink directory. One entry points at $AGENTS_DIR — the same managed, surfaces-filtered, collision-resolved directory Crush/OpenCode/Pi already read — so Antigravity sees exactly the same skill set as every other harness, for free. Requires jq; every other target in this script stays dependency-free on purpose, so wire_antigravity skips with a warning (not a hard failure) if jq is missing. Merges into skills.json rather than overwriting it: the file is documented as user-editable (json_configs.md — e.g. a personal skills dir), so a hand-added entry must survive a re-run. Was previously removed as "unused" (mathias/skills#41 — Antigravity usage picked back up). Mistral Vibe stays removed. Closes #41 Bump-Type: minor Co-Authored-By: Claude Sonnet 5 --- README.md | 4 +++- install.sh | 49 +++++++++++++++++++++++++++++++++++++++++-- tests/install_test.sh | 49 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 172d595..c4dacf7 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,11 @@ default to point into `~/dev`. | `AGENTS_SKILLS_DIR` | `$HOME/.agents/skills` | | `CRUSH_SKILLS_DIR` | `$HOME/.config/crush/skills` | | `OPENCODE_SKILLS_DIR` | `$HOME/.config/opencode/skills` | +| `ANTIGRAVITY_SKILLS_JSON` | `$HOME/.gemini/config/skills.json` (registers `AGENTS_SKILLS_DIR` as a path entry; needs `jq`) | | `SKILLS_EXTRA_SOURCES` | unset (colon-separated extra source directories) | -Antigravity and Mistral Vibe targets were removed — unused. +The Mistral Vibe target was removed — unused. Antigravity's was removed for +the same reason and re-added once it came back into use. ## Checking a host diff --git a/install.sh b/install.sh index d49e304..788377f 100755 --- a/install.sh +++ b/install.sh @@ -17,8 +17,8 @@ # /plugin install skills@mathias # # That path carries the hooks and MCP server definitions too, which symlinks -# cannot. This script covers the harnesses with no plugin system: Crush, Pi -# and OpenCode. +# cannot. This script covers the harnesses with no plugin system: Crush, Pi, +# OpenCode, and Antigravity. # # Wiring model — one managed directory, one link per harness: # @@ -27,6 +27,13 @@ # ~/.config/crush/skills -> ~/.agents/skills # ~/.config/opencode/skills -> ~/.agents/skills # +# Antigravity has no symlink-directory discovery — it reads a path-entries +# JSON instead (~/.gemini/config/skills.json: +# {"entries":[{"path":"..."}]}). One entry points at ~/.agents/skills, so it +# sees exactly the same surfaces-filtered, collision-resolved set every other +# harness does. Requires jq; skipped with a warning if jq is unavailable — +# every other target in this script stays dependency-free on purpose. +# # ~/.agents/skills was itself a link to this checkout until #27. That encoded # an assumption nobody had stated — that this checkout is the ONLY source of # skills on the host — and on flamingo the only way to install this library @@ -53,6 +60,7 @@ CHECKOUT_DIR="${SKILLS_CHECKOUT_DIR:-$HOME/.local/share/skills}" AGENTS_DIR="${AGENTS_SKILLS_DIR:-$HOME/.agents/skills}" CRUSH_DIR="${CRUSH_SKILLS_DIR:-$HOME/.config/crush/skills}" OPENCODE_DIR="${OPENCODE_SKILLS_DIR:-$HOME/.config/opencode/skills}" +ANTIGRAVITY_SKILLS_JSON="${ANTIGRAVITY_SKILLS_JSON:-$HOME/.gemini/config/skills.json}" EXTRA_SOURCES="${SKILLS_EXTRA_SOURCES:-}" # Recorded beside the managed directory rather than inside it: a stray file in # there would look like a skill to every harness reading the dir. @@ -213,6 +221,42 @@ link_dir() { log "linked $link → $target" } +# wire_antigravity — register $AGENTS_DIR in Antigravity's skills.json. +# Merges rather than overwrites: skills.json is a documented user-editable +# config (json_configs.md), so a hand-added entry (e.g. a personal skills +# dir) must survive a re-run untouched. +wire_antigravity() { + if ! command -v jq >/dev/null 2>&1; then + log "Antigravity: jq not found — skipping (needed to merge $ANTIGRAVITY_SKILLS_JSON safely)" + return + fi + + local existing already updated + mkdir -p "$(dirname "$ANTIGRAVITY_SKILLS_JSON")" + + if [ -s "$ANTIGRAVITY_SKILLS_JSON" ]; then + existing="$(cat "$ANTIGRAVITY_SKILLS_JSON")" + else + existing='{}' + fi + + already="$(printf '%s' "$existing" | jq --arg p "$AGENTS_DIR" \ + '[.entries // [] | .[] | select(.path == $p)] | length' 2>/dev/null)" || { + log "Antigravity: $ANTIGRAVITY_SKILLS_JSON is not valid JSON — leaving it untouched" + return 1 + } + + if [ "$already" -gt 0 ]; then + log "Antigravity: $AGENTS_DIR already registered in $ANTIGRAVITY_SKILLS_JSON" + return + fi + + updated="$(printf '%s' "$existing" | jq --arg p "$AGENTS_DIR" \ + '.entries = ((.entries // []) + [{path: $p}])')" + printf '%s\n' "$updated" > "$ANTIGRAVITY_SKILLS_JSON" + log "Antigravity: registered $AGENTS_DIR in $ANTIGRAVITY_SKILLS_JSON" +} + main() { ensure_checkout @@ -224,6 +268,7 @@ main() { link_dir "$CRUSH_DIR" "$AGENTS_DIR" link_dir "$OPENCODE_DIR" "$AGENTS_DIR" + wire_antigravity log "done — $LINKED_COUNT skill(s) linked from $(sources | wc -l | tr -d ' ') source(s), ref=$REF" log "Claude Code: install the plugin instead — /plugin marketplace add $REPO_URL" diff --git a/tests/install_test.sh b/tests/install_test.sh index e36c1c9..9e9f8f1 100644 --- a/tests/install_test.sh +++ b/tests/install_test.sh @@ -55,6 +55,7 @@ run_install() { AGENTS_SKILLS_DIR="$_f/home/.agents/skills" \ CRUSH_SKILLS_DIR="$_f/home/.config/crush/skills" \ OPENCODE_SKILLS_DIR="$_f/home/.config/opencode/skills" \ + ANTIGRAVITY_SKILLS_JSON="$_f/home/.gemini/config/skills.json" \ SKILLS_EXTRA_SOURCES="$_extra" \ bash "$SUT" 2>&1) rc=$? @@ -183,5 +184,53 @@ else no 'a source with no surfaces convention is linked as-is' "$out" fi +# --- 9. Antigravity: the managed agents dir is registered, not the raw checkout +# skills.json entries must point at $AGENTS_DIR — that's what already carries +# surfaces-filtering, collision handling and multi-source merge. Pointing at +# the checkout directly would bypass all of it and give Antigravity a +# different skill set than every other harness. +f=$(new_fixture antigravity) +out=$(run_install "$f") +AG="$f/home/.gemini/config/skills.json" +if [ ! -f "$AG" ]; then + no 'Antigravity skills.json is created' "$out" +elif ! command -v jq >/dev/null 2>&1; then + no 'jq available to verify Antigravity wiring' "(jq missing on test host)" +else + registered=$(jq -r --arg p "$f/home/.agents/skills" '[.entries[]? | select(.path == $p)] | length' "$AG") + if [ "$registered" = "1" ]; then + ok 'Antigravity registers the managed agents dir, not the raw checkout' + else + no 'Antigravity registers the managed agents dir, not the raw checkout' "$(cat "$AG")" + fi +fi + +# --- 10. Antigravity wiring is idempotent ------------------------------------ +f=$(new_fixture antigravity_idempotent) +run_install "$f" >/dev/null +out=$(run_install "$f") +AG="$f/home/.gemini/config/skills.json" +count=$(jq '.entries | length' "$AG" 2>/dev/null || echo "?") +if [ "$count" = "1" ]; then + ok 'Antigravity wiring is idempotent (no duplicate entries)' +else + no 'Antigravity wiring is idempotent (no duplicate entries)' "entries=$count"$'\n'"$out" +fi + +# --- 11. Antigravity wiring preserves entries it doesn't own ----------------- +# A user may hand-edit skills.json to point at their own personal skills dir +# (json_configs.md documents this). Our merge must not clobber it. +f=$(new_fixture antigravity_preserve) +mkdir -p "$f/home/.gemini/config" +printf '{"entries":[{"path":"/Users/mathias/personal-skills"}]}' > "$f/home/.gemini/config/skills.json" +out=$(run_install "$f") +AG="$f/home/.gemini/config/skills.json" +personal=$(jq -r '[.entries[]? | select(.path == "/Users/mathias/personal-skills")] | length' "$AG" 2>/dev/null || echo 0) +if [ "$personal" = "1" ]; then + ok 'Antigravity wiring preserves pre-existing hand-authored entries' +else + no 'Antigravity wiring preserves pre-existing hand-authored entries' "$(cat "$AG")"$'\n'"$out" +fi + printf '\ninstall: %d passed, %d failed\n' "$pass" "$fail" [ "$fail" -eq 0 ]