Replace Gemini coding agent with Antigravity (#6900)

* Replace Gemini coding agent with Antigravity

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Remove the dead Gemini mise wrapper in the Antigravity migration

Remove Preinstalls no longer lists gemini, so the wrapper Omarchy created
would have stayed in ~/.local/bin with nothing left to clean it up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Install Antigravity when it is the default a Gemini user is migrated onto

The opt-out check skipped the install but the rewrite ran anyway, so anyone
who had removed the preinstalls was left with a default agent naming a
command that is not there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Fix Antigravity skill provisioning and Gemini wrapper migration

- Wires Omarchy's default skills into Antigravity by linking them to ~/.gemini/config/skills/ in bin/omarchy-provision-user and migrations/1786719479.sh.
- Fixes the Gemini wrapper migration in migrations/1786719479.sh to recognize and remove wrappers containing either `mise use -g "gemini"` or `mise use -g --quiet "gemini"`, while leaving hand-written wrappers intact.
- Adds regression tests for both skill provisioning and wrapper removal in test/shell.d/default-agent-test.sh and test/shell.d/provision-user-test.sh.

* Stop the provisioning test from retheming the session it runs in

The test ran the real omarchy-provision-user, which sources install/user/all.sh and so reached omarchy-theme-set: hyprctl reload against the live compositor, gsettings against the live desktop, and a global Node install, none of which the skill symlinks it asserts need. Its mocks for omarchy-done and omarchy-refresh-applications were shadowed anyway, because provisioning prepends $OMARCHY_PATH/bin ahead of them, so stubbing the install suite at its own path is what a mock cannot do here. The exit status is checked rather than discarded: the assertion held even when provisioning died outright, because the symlinks are made twenty lines before the suite runs.

* Match the Gemini default and wrapper the way Omarchy writes them

The migration decided both questions differently from the code that owns them. It read the default agent with grep -qxF, while omarchy-default-agent takes the first line through read, so a padded "  gemini  " that the launcher still resolves was left naming an agent the launcher no longer supports. The wrapper it deletes was matched anywhere in the file, so a hand-written one that only mentions the installer's line in a comment went with Omarchy's own. Reading it the launcher's way and anchoring the match settles both against whoever wrote the file. The skills loop guards its glob the way migrations/1786539345.sh does, so an empty source cannot leave a symlink named "*" behind a migration already marked complete.

Co-Authored-By: Codex XHigh <noreply@anthropic.com>

* List Antigravity among the skill directories

The manual named Claude Code, Codex, Pi and the generic location; provisioning now links ~/.gemini/config/skills too.

Co-Authored-By: Codex XHigh <noreply@anthropic.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: David Heinemeier Hansson <david@hey.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Omabot <omabot@omarchy.org>
This commit is contained in:
Sanjay
2026-08-20 22:28:31 +02:00
committed by GitHub
co-authored by Codex XHigh Copilot Autofix powered by AI David Heinemeier Hansson Omabot
parent cf29ce1867
commit ed7bae4ac5
11 changed files with 173 additions and 19 deletions
+2 -2
View File
@@ -58,8 +58,8 @@ opencode)
command=(opencode --auto)
[[ -n ${prompt:-} ]] && command+=(--prompt "$prompt")
;;
gemini)
command=(gemini --yolo)
agy)
command=(agy --dangerously-skip-permissions)
[[ -n ${prompt:-} ]] && command+=(--prompt-interactive "$prompt")
;;
copilot)
+3 -3
View File
@@ -1,7 +1,7 @@
#!/bin/bash
# omarchy:summary=Set and launch the default coding agent
# omarchy:args=[pi|omp|opencode|claude|codex|grok|gemini|copilot|crush]
# omarchy:args=[pi|omp|opencode|claude|codex|grok|agy|copilot|crush]
# omarchy:examples=omarchy default agent | omarchy default agent codex | omarchy default agent claude
installing=false
@@ -31,10 +31,10 @@ claude | claude-code) agent="claude"; name="Claude Code" ;;
codex) agent="codex"; name="Codex" ;;
crush) agent="crush"; name="Crush" ;;
grok) agent="grok"; name="Grok"; agent_package="npm:@xai-official/grok" ;;
gemini | gemini-cli) agent="gemini"; name="Gemini" ;;
agy | antigravity | antigravity-cli | gemini | gemini-cli) agent="agy"; name="Antigravity"; agent_package="antigravity-cli" ;;
copilot | github-copilot) agent="copilot"; name="GitHub Copilot" ;;
*)
echo "Usage: omarchy-default-agent <pi|omp|opencode|claude|codex|grok|gemini|copilot|crush>"
echo "Usage: omarchy-default-agent <pi|omp|opencode|claude|codex|grok|agy|copilot|crush>"
exit 1
;;
esac
+2 -1
View File
@@ -84,7 +84,7 @@ fi
# Dev-aware skill symlinks. Cannot live in /etc/skel because OMARCHY_PATH may
# point at a dev checkout (omarchy dev link) where the target differs.
# Loops every skill directory, so shipping a new one needs no edit here.
mkdir -p ~/.agents/skills ~/.claude/skills ~/.codex/skills ~/.pi/agent/skills
mkdir -p ~/.agents/skills ~/.claude/skills ~/.codex/skills ~/.pi/agent/skills ~/.gemini/config/skills
for skill in "$OMARCHY_PATH"/default/agents/skills/*/; do
skill=${skill%/}
name=${skill##*/}
@@ -92,6 +92,7 @@ for skill in "$OMARCHY_PATH"/default/agents/skills/*/; do
ln -sfn "$skill" ~/.claude/skills/"$name"
ln -sfn "$skill" ~/.codex/skills/"$name"
ln -sfn "$skill" ~/.pi/agent/skills/"$name"
ln -sfn "$skill" ~/.gemini/config/skills/"$name"
done
mkdir -p ~/Downloads ~/Pictures ~/Videos ~/.config/gtk-3.0
+1 -1
View File
@@ -13,7 +13,7 @@ if gum confirm "Are you sure you want to remove all preinstalled web apps, TUI w
hyprctl reload
# Remove mise stubs
rm -f ~/.local/bin/codex ~/.local/bin/claude ~/.local/bin/gemini ~/.local/bin/copilot \
rm -f ~/.local/bin/codex ~/.local/bin/claude ~/.local/bin/agy ~/.local/bin/copilot \
~/.local/bin/gh ~/.local/bin/opencode ~/.local/bin/playwright ~/.local/bin/playwright-cli ~/.local/bin/pi \
~/.local/bin/omp ~/.local/bin/grok ~/.local/bin/crush ~/.local/bin/ghui ~/.local/bin/hunk
+1 -1
View File
@@ -135,11 +135,11 @@
"setup.network.qr": {"icon":"󰐲","label":"QR Code","aliases":["wifi-qr"],"when":"[[ $(omarchy-network-status) == wifi* ]]","action":"omarchy-shell shell summon omarchy.wifiqr"},
"setup.default": {"icon":"","label":"Defaults","aliases":["default","defaults"]},
"setup.default.agent": {"icon":"󰚩","label":"Agent","title":"Default Agent"},
"setup.default.agent.agy": {"icon":"󰫢","label":"Antigravity","checked":"[[ \"$(omarchy-default-agent)\" == \"agy\" ]]","action":"omarchy-default-agent agy"},
"setup.default.agent.claude": {"icon":"󰛄","label":"Claude","checked":"[[ \"$(omarchy-default-agent)\" == \"claude\" ]]","action":"omarchy-default-agent claude"},
"setup.default.agent.codex": {"icon":"","iconFont":"omarchy","label":"Codex","checked":"[[ \"$(omarchy-default-agent)\" == \"codex\" ]]","action":"omarchy-default-agent codex"},
"setup.default.agent.copilot": {"icon":"","label":"Copilot","checked":"[[ \"$(omarchy-default-agent)\" == \"copilot\" ]]","action":"omarchy-default-agent copilot"},
"setup.default.agent.crush": {"icon":"󰋑","label":"Crush","checked":"[[ \"$(omarchy-default-agent)\" == \"crush\" ]]","action":"omarchy-default-agent crush"},
"setup.default.agent.gemini": {"icon":"󰫢","label":"Gemini","checked":"[[ \"$(omarchy-default-agent)\" == \"gemini\" ]]","action":"omarchy-default-agent gemini"},
"setup.default.agent.grok": {"icon":"","iconFont":"omarchy","label":"Grok","checked":"[[ \"$(omarchy-default-agent)\" == \"grok\" ]]","action":"omarchy-default-agent grok"},
"setup.default.agent.omp": {"icon":"","iconFont":"omarchy","label":"omp","checked":"[[ \"$(omarchy-default-agent)\" == \"omp\" ]]","action":"omarchy-default-agent omp"},
"setup.default.agent.opencode": {"icon":"","iconFont":"omarchy","label":"OpenCode","checked":"[[ \"$(omarchy-default-agent)\" == \"opencode\" ]]","action":"omarchy-default-agent opencode"},
+1 -1
View File
@@ -1,7 +1,7 @@
omarchy-mise-install codex
omarchy-mise-install claude
omarchy-mise-install crush
omarchy-mise-install gemini
omarchy-mise-install antigravity-cli agy
omarchy-mise-install gh
omarchy-mise-install copilot
omarchy-mise-install opencode
+2 -2
View File
@@ -7,7 +7,7 @@ Omarchy treats AI coding agents as first-class citizens, but it doesn't pick a f
| `claude` | [Claude Code](https://code.claude.com/docs/en/overview) |
| `codex` | [OpenAI Codex](https://github.com/openai/codex) |
| `opencode` | [OpenCode](https://opencode.ai/) |
| `gemini` | [Google Gemini CLI](https://github.com/google-gemini/gemini-cli) |
| `agy` | [Google Antigravity CLI](https://github.com/google-antigravity/antigravity-cli) |
| `copilot` | [GitHub Copilot CLI](https://github.com/github/copilot-cli) |
| `crush` | [Crush](https://github.com/charmbracelet/crush) |
| `grok` | Grok CLI from xAI |
@@ -46,6 +46,6 @@ Omarchy recommends two ways of running local LLM models: LM Studio and Ollama. L
### The Omarchy Skill
Agent skills help AI use specific tools in a specific way, and Omarchy ships with a default skill for tailoring the system. Like tweaking your Hyprland config, adjusting the bar, or even creating a new theme from scratch. It's symlinked into the skill directories for Claude Code (`~/.claude/skills`), Codex (`~/.codex/skills`), Pi (`~/.pi/agent/skills`), and the generic `~/.agents/skills` location, so most harnesses pick it up automatically.
Agent skills help AI use specific tools in a specific way, and Omarchy ships with a default skill for tailoring the system. Like tweaking your Hyprland config, adjusting the bar, or even creating a new theme from scratch. It's symlinked into the skill directories for Claude Code (`~/.claude/skills`), Codex (`~/.codex/skills`), Pi (`~/.pi/agent/skills`), Antigravity (`~/.gemini/config/skills`), and the generic `~/.agents/skills` location, so most harnesses pick it up automatically.
But you should treat this skill as experimental. Different models will use it to different effect. It's best to run in plan mode first, so you have an idea of what the agent would like to change. And then be ready to rollback changes or even invoking `omarchy reinstall configs`, if the agent makes a mess of everything.
+41
View File
@@ -0,0 +1,41 @@
echo "Replace the Gemini coding agent with Antigravity"
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
agent_file="$HOME/.config/omarchy/defaults/agent"
skills_source="$OMARCHY_PATH/default/agents/skills"
# Read the default the way omarchy-default-agent reads it, so this migration and
# the launcher always agree on which agent is selected.
selected_agent=""
if [[ -f $agent_file ]]; then
read -r selected_agent <"$agent_file" || true
fi
# Choosing Gemini was opting into an agent, so its replacement follows even for
# someone who removed the preinstalls. Otherwise the default rewritten below
# would name a command that is not there.
if omarchy-cmd-missing agy &&
{ [[ $selected_agent == "gemini" ]] || [[ ! -f $HOME/.local/state/omarchy/preinstalls-removed ]]; }; then
omarchy-mise-install antigravity-cli agy
fi
if [[ $selected_agent == "gemini" ]]; then
printf '%s\n' agy >"$agent_file"
fi
# Remove Preinstalls no longer lists gemini, so Omarchy's own wrapper would
# linger with nothing left to clean it up. Anchored to the line the installer
# writes, so a hand-written wrapper that merely mentions it is left alone.
if [[ -f $HOME/.local/bin/gemini ]] && grep -Eq '^mise use -g .*"gemini"' "$HOME/.local/bin/gemini"; then
rm -f "$HOME/.local/bin/gemini"
fi
if [[ -d $skills_source ]]; then
mkdir -p "$HOME/.gemini/config/skills"
for skill in "$skills_source"/*/; do
[[ -d $skill ]] || continue
name=${skill%/}
ln -sfn "$name" "$HOME/.gemini/config/skills/${name##*/}"
done
fi
+83 -6
View File
@@ -91,10 +91,12 @@ export OMARCHY_TEST_MISE_HISTORY="$mise_history"
export OMARCHY_TEST_STUB_LOG="$stub_log"
export OMARCHY_TEST_AGENT_TERMINAL_LOG="$terminal_log"
export OMARCHY_TEST_AGENT_MENU_LOG="$menu_log"
export OMARCHY_PATH="$ROOT"
grok_package="npm:@xai-official/grok"
omp_package="github:can1357/oh-my-pi"
crush_package="crush"
agy_package="antigravity-cli"
assert_lazy_stub() {
local package=$1
@@ -115,6 +117,7 @@ assert_lazy_stub "$crush_package" crush
pass "custom agent lazy stubs preserve their mise packages"
source "$ROOT/install/user/mise.sh"
grep -Fx "$agy_package agy" "$stub_log" >/dev/null || fail "user setup creates the Antigravity lazy stub"
grep -Fx "$grok_package grok" "$stub_log" >/dev/null || fail "user setup creates the Grok lazy stub"
grep -Fx "$omp_package omp" "$stub_log" >/dev/null || fail "user setup creates the Oh My Pi lazy stub"
grep -Fx "$crush_package" "$stub_log" >/dev/null || fail "user setup creates the Crush lazy stub"
@@ -130,6 +133,75 @@ grep -Fx "$omp_package omp" "$stub_log" >/dev/null || fail "agent migration repa
grep -Fx "$grok_package grok" "$stub_log" >/dev/null || fail "agent migration creates the Grok lazy stub"
grep -Fx "$crush_package" "$stub_log" >/dev/null || fail "agent migration creates the Crush lazy stub"
: >"$stub_log"
mkdir -p "$(dirname "$agent_file")"
printf '%s\n' gemini >"$agent_file"
"$ROOT/bin/omarchy-mise-install" gemini
export OMARCHY_TEST_MISSING_COMMAND=agy
source "$ROOT/migrations/1786719479.sh" >/dev/null
unset OMARCHY_TEST_MISSING_COMMAND
grep -Fx "$agy_package agy" "$stub_log" >/dev/null || fail "Antigravity migration creates its lazy stub"
[[ $(<"$agent_file") == "agy" ]] || fail "Antigravity migration replaces a Gemini default"
: >"$stub_log"
printf ' %s \n' gemini >"$agent_file"
export OMARCHY_TEST_MISSING_COMMAND=agy
source "$ROOT/migrations/1786719479.sh" >/dev/null
unset OMARCHY_TEST_MISSING_COMMAND
[[ $(<"$agent_file") == "agy" ]] ||
fail "Antigravity migration replaces a padded Gemini default the launcher would still read"
pass "Antigravity migration reads the default the way the launcher does"
for obsolete_form in 'mise use -g "gemini"' 'mise use -g --quiet "gemini"'; do
printf '#!/bin/bash\n%s || exit 1\n' "$obsolete_form" >"$test_home/.local/bin/gemini"
chmod +x "$test_home/.local/bin/gemini"
source "$ROOT/migrations/1786719479.sh" >/dev/null
[[ ! -e $test_home/.local/bin/gemini ]] ||
fail "Antigravity migration removes a wrapper built on [$obsolete_form]"
done
printf '#!/bin/bash\nexec /opt/gemini "$@"\n' >"$test_home/.local/bin/gemini"
chmod +x "$test_home/.local/bin/gemini"
source "$ROOT/migrations/1786719479.sh" >/dev/null
[[ -e $test_home/.local/bin/gemini ]] || fail "Antigravity migration leaves a hand-written gemini alone"
printf '#!/bin/bash\n# replaced: mise use -g --quiet "gemini"\nexec /opt/gemini "$@"\n' >"$test_home/.local/bin/gemini"
chmod +x "$test_home/.local/bin/gemini"
source "$ROOT/migrations/1786719479.sh" >/dev/null
[[ -e $test_home/.local/bin/gemini ]] ||
fail "Antigravity migration leaves a wrapper that only mentions the installer line"
rm -f "$test_home/.local/bin/gemini"
pass "Antigravity migration only removes the Gemini wrapper Omarchy wrote"
[[ -L "$test_home/.gemini/config/skills/omarchy" && $(readlink "$test_home/.gemini/config/skills/omarchy") == "$ROOT/default/agents/skills/omarchy" ]] ||
fail "Antigravity migration provisions the omarchy skill"
[[ -L "$test_home/.gemini/config/skills/diagnose-crash" && $(readlink "$test_home/.gemini/config/skills/diagnose-crash") == "$ROOT/default/agents/skills/diagnose-crash" ]] ||
fail "Antigravity migration provisions the diagnose-crash skill"
pass "Antigravity migration provisions Antigravity skills"
: >"$stub_log"
mkdir -p "$test_home/.local/state/omarchy"
touch "$test_home/.local/state/omarchy/preinstalls-removed"
export OMARCHY_TEST_MISSING_COMMAND=agy
source "$ROOT/migrations/1786719479.sh" >/dev/null
[[ ! -s $stub_log ]] || fail "Antigravity migration preserves removed preinstalls"
pass "Antigravity migration respects removed preinstalls"
: >"$stub_log"
printf '%s\n' gemini >"$agent_file"
source "$ROOT/migrations/1786719479.sh" >/dev/null
unset OMARCHY_TEST_MISSING_COMMAND
grep -Fx "$agy_package agy" "$stub_log" >/dev/null || fail "Antigravity migration installs the agent a Gemini default now names"
[[ $(<"$agent_file") == "agy" ]] || fail "Antigravity migration replaces a Gemini default after opt-out"
pass "Antigravity migration never leaves the default naming a missing agent"
: >"$stub_log"
rm "$test_home/.local/state/omarchy/preinstalls-removed"
source "$ROOT/migrations/1786719479.sh" >/dev/null
[[ ! -s $stub_log ]] || fail "Antigravity migration reinstalls an existing Antigravity command"
pass "Antigravity migration preserves an existing Antigravity install"
mkdir -p "$test_home/.local/state/omarchy"
touch "$test_home/.local/state/omarchy/preinstalls-removed"
"$ROOT/bin/omarchy-mise-install" oh-my-pi omp
@@ -157,10 +229,12 @@ source "$ROOT/migrations/1785846769.sh" >/dev/null
rm -f "$test_home/.local/bin/omp"
rm "$test_home/.local/state/omarchy/preinstalls-removed"
rm -f "$agent_file"
pass "agent migrations install working wrappers without overriding the preinstall opt-out"
touch "$test_home/.local/bin/agy"
omarchy-remove-preinstalls >/dev/null
for command in omp grok crush; do
for command in agy omp grok crush; do
[[ ! -e $test_home/.local/bin/$command ]] || fail "Remove Preinstalls deletes the $command lazy stub"
done
pass "Remove Preinstalls deletes every optional agent lazy stub"
@@ -216,8 +290,11 @@ declare -A expected_agents=(
[codex]="codex"
[crush]="crush"
[grok]="grok"
[gemini]="gemini"
[gemini-cli]="gemini"
[agy]="agy"
[antigravity]="agy"
[antigravity-cli]="agy"
[gemini]="agy"
[gemini-cli]="agy"
[copilot]="copilot"
[github-copilot]="copilot"
)
@@ -230,7 +307,7 @@ declare -A expected_packages=(
[codex]="codex"
[crush]="$crush_package"
[grok]="$grok_package"
[gemini]="gemini"
[agy]="$agy_package"
[copilot]="copilot"
)
@@ -373,7 +450,7 @@ assert_launch claude claude --permission-mode auto -- "Review this project"
assert_launch codex codex --approve-for-me -- "Review this project"
assert_launch crush crush run "Review this project"
assert_launch grok grok --permission-mode bypassPermissions -- "Review this project"
assert_launch gemini gemini --yolo --prompt-interactive "Review this project"
assert_launch agy agy --dangerously-skip-permissions --prompt-interactive "Review this project"
assert_launch copilot copilot --allow-all --interactive "Review this project"
pass "agent launcher adapts initial prompts for every supported agent"
@@ -384,7 +461,7 @@ assert_bypass claude claude --permission-mode auto
assert_bypass codex codex --approve-for-me
assert_bypass crush crush --yolo
assert_bypass grok grok --permission-mode bypassPermissions
assert_bypass gemini gemini --yolo
assert_bypass agy agy --dangerously-skip-permissions
assert_bypass copilot copilot --allow-all
pass "agent launcher skips permission prompts for every supported agent"
+2 -2
View File
@@ -211,13 +211,13 @@ assertEqual(
'menu lists Reset Computer last under Setup'
)
const expectedAgents = {
agy: { icon: '󰫢', label: 'Antigravity' },
pi: { icon: '\ue901', iconFont: 'omarchy', label: 'Pi' },
omp: { icon: '\ue903', iconFont: 'omarchy', label: 'omp' },
opencode: { icon: '\ue902', iconFont: 'omarchy', label: 'OpenCode' },
claude: { icon: '󰛄', label: 'Claude' },
codex: { icon: '\ue905', iconFont: 'omarchy', label: 'Codex' },
grok: { icon: '\ue904', iconFont: 'omarchy', label: 'Grok' },
gemini: { icon: '󰫢', label: 'Gemini' },
copilot: { icon: '', label: 'Copilot' },
crush: { icon: '󰋑', label: 'Crush' },
}
@@ -238,7 +238,7 @@ assertDeepEqual(
defaultItems
.filter(item => item.parent === 'setup.default.agent')
.map(item => item.label),
['Claude', 'Codex', 'Copilot', 'Crush', 'Gemini', 'Grok', 'omp', 'OpenCode', 'Pi'],
['Antigravity', 'Claude', 'Codex', 'Copilot', 'Crush', 'Grok', 'omp', 'OpenCode', 'Pi'],
'menu sorts coding agents alphabetically'
)
const expectedDefaults = {
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
set -euo pipefail
source "$(dirname "$0")/base-test.sh"
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
mock_bin="$test_tmp/bin"
mkdir -p "$mock_bin" "$test_tmp/home"
for command in xdg-user-dirs-update xdg-settings xdg-mime; do
printf '#!/bin/bash\nexit 0\n' >"$mock_bin/$command"
done
chmod +x "$mock_bin"/*
# Provisioning prepends $OMARCHY_PATH/bin, which shadows a mock for anything
# Omarchy ships, so the install suite is stubbed out at its path instead. The
# real one rethemes the session it runs in: hyprctl reload against the live
# compositor, gsettings against the live desktop, and a global Node install.
mkdir -p "$test_tmp/install/user"
: >"$test_tmp/install/user/all.sh"
HOME="$test_tmp/home" PATH="$mock_bin:$ROOT/bin:$PATH" OMARCHY_PATH="$ROOT" \
OMARCHY_INSTALL="$test_tmp/install" bash "$ROOT/bin/omarchy-provision-user" >/dev/null ||
fail "omarchy-provision-user finishes"
for skill in omarchy diagnose-crash; do
link="$test_tmp/home/.gemini/config/skills/$skill"
[[ -L $link && $(readlink "$link") == "$ROOT/default/agents/skills/$skill" ]] ||
fail "omarchy-provision-user provisions the $skill skill for Antigravity"
done
pass "omarchy-provision-user provisions Antigravity skills"