feat(ai-tools): migrate Gemini CLI → Antigravity CLI + OpenCode#5
Conversation
Gemini CLI consumer access ends 2026-06-18; Google's official successor is Antigravity CLI (`agy`). OpenCode (OSS, multi-provider, homebrew/core) is installed alongside as a model-agnostic option. - helpers.sh: install_gemini_cli → install_opencode (core formula) + install_antigravity_cli (cask antigravity-cli; Linux = manual per curl|bash policy) - install.sh / config.sh / update-ai-tools / ai-check: swap Gemini → OpenCode + Antigravity; drop Coven + Crazytieguy/tap (third-party tap violates no-new-taps policy) - auto_commit_worker + ai_automation: backend order codex,gemini → codex,opencode - scripts: sync_claude_to_gemini.sh → sync_claude_to_antigravity.sh (skills → ~/.gemini/antigravity-cli/skills; AGENTS.md; permission sync to settings.json) - supply-chain-security.md: two-gate modernity/adoption selection rule - remove GEMINI.md + gemini/GEMINI.md (AGENTS.md is the successor instruction file) - README: Gemini CLI section → Antigravity CLI + OpenCode Verified against formulae.brew.sh: antigravity-cli cask (ships `agy`), opencode in homebrew/core. Runtime behavior (agy permission load, glob semantics) still pending Mac verification — see sync script header TODO. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughWalkthroughGemini CLI is retired and replaced with Antigravity CLI (its successor) and OpenCode across the dotfiles. A new ChangesGemini CLI → Antigravity CLI + OpenCode
Sequence Diagram(s)sequenceDiagram
participant User
participant SyncScript as sync_claude_to_antigravity.sh
participant SkillsFS as Antigravity Skills Dir
participant Python as Embedded Python
participant AntigravityJSON as settings.json
User->>SyncScript: run script
SyncScript->>SkillsFS: remove stale/broken symlinks
SyncScript->>SkillsFS: create skill entries from Claude skills
SyncScript->>Python: pass Claude settings.json path
Python->>Python: map Claude permissions → command()/read_file() entries
Python->>AntigravityJSON: merge mapped block (preserving user rules)
Python->>SyncScript: write/clear unmapped sidecar
SyncScript->>User: print completion + TODO notes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🤖 Hi @yulonglin, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
|
🤖 I'm sorry @yulonglin, but I was unable to process your request. Please see the logs for more details. |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@claude/hooks/auto_commit_worker.sh`:
- Around line 249-252: In the opencode case block, update the run_with_timeout
command to include the --dir flag that specifies the working directory for the
opencode run command. Modify the line containing run_with_timeout 240 opencode
run "$prompt" to add --dir "$REPO_ROOT" before the output redirection, so the
opencode command executes in the correct repository directory and avoids relying
on the PWD environment variable which may not be set correctly in script
execution contexts.
In `@config.sh`:
- Line 36: The ai-tools install component description on line 36 includes
"Antigravity CLI" in its tool list, but the ai-update deploy component
description on line 67 omits "Antigravity CLI", creating an inconsistency.
Update the ai-update component description on line 67 to include "Antigravity
CLI" in the tool list so that both the ai-tools and ai-update descriptions
reference the same set of tools.
In `@custom_bins/update-ai-tools`:
- Around line 172-174: The brew upgrade command for the antigravity-cli cask is
missing the --greedy flag, which causes Homebrew to skip updates since this cask
declares auto_updates: true. Add the --greedy flag to the brew upgrade command
line between --cask and the cask name antigravity-cli to ensure the upgrade
actually proceeds rather than being silently skipped.
In `@README.md`:
- Line 291: The README.md note at line 291 incorrectly states that permission
sync is not yet ported, but the actual script
`scripts/sync_claude_to_antigravity.sh` now includes permissions mapping and
merge functionality. Update the note to accurately reflect that the script
currently performs both skills and permissions sync, replacing the outdated
statement about permission sync not being ported with current details about how
permissions are handled (including what was adapted or any remaining caveats).
- Line 278: The wording in the Gemini CLI retirement statement uses past tense
("was retired on") for a date in the future, which is inaccurate. Change the
tense from past to future by replacing "was retired on" with future-tense
phrasing such as "will be retired on" or "access ends on" while keeping the date
2026-06-18 unchanged. This ensures the statement correctly reflects that the
retirement has not yet occurred.
In `@scripts/sync_claude_to_antigravity.sh`:
- Around line 1-2: The shell script is missing strict error handling mode which
can cause failed commands to be silently ignored during filesystem mutations and
JSON writes. Add `set -euo pipefail` as a new line immediately after the
`#!/bin/bash` shebang at the start of the script. This enables the script to
exit on errors, treat undefined variables as errors, and properly handle pipe
failures, ensuring that any command failures are caught and prevent silent
failures.
- Line 42: Add a shellcheck directive comment immediately before the `source
"$HELPER"` statement to address the SC1090 warning about dynamic source paths.
Include a comment line that tells shellcheck how to handle the dynamic sourcing
(typically `# shellcheck source=/dev/null` or similar) directly above the source
command to suppress the warning and keep CI/static checks clean.
- Around line 52-70: The skill synchronization logic does not handle cases where
a skill changes type between sync runs, which can cause symlinks to point to old
targets or fail to replace existing directories. Before executing the ln or
mkdir commands in each case statement (user_skill, standalone_skill,
plugin_skill, agent_skill), add logic to remove any existing target at
$TARGET_DIR/$name if it exists and is incompatible with the current skill type
(e.g., remove a symlink when a directory is needed, or remove a directory when a
symlink is needed). This normalization of the destination shape per skill type
should happen before any ln or mkdir operations to ensure clean transitions.
- Around line 112-114: The BEGIN and END marker strings (lines 112-114) violate
Antigravity's permission schema by being inserted as literal array elements into
permissions.allow/deny/ask arrays at line 248, when the schema expects only
"action(target)" formatted strings. Replace the marker-based tracking approach
with sidecar metadata (already initialized at line 108) to track which entries
are managed by the script. Modify the merge_bucket() logic (lines 217-240) and
the final permissions write (line 248) to use set-difference filtering instead
of searching for BEGIN and END sentinel strings, removing old managed entries by
comparing against stored metadata rather than marker positions. Test the output
on a real Antigravity configuration before merging to validate the new approach
works correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d6b75dc4-8010-43da-a2fa-6f68d1e00dfc
📒 Files selected for processing (15)
GEMINI.mdREADME.mdclaude/hooks/auto_commit_worker.shclaude/rules/supply-chain-security.mdconfig.shconfig/ai_automation.shconfig/aliases.shcustom_bins/update-ai-toolsgemini/GEMINI.mdinstall.shscripts/cleanup/setup_ai_update.shscripts/cloud/setup.shscripts/shared/helpers.shscripts/sync_claude_to_antigravity.shscripts/sync_claude_to_gemini.sh
💤 Files with no reviewable changes (3)
- GEMINI.md
- scripts/sync_claude_to_gemini.sh
- gemini/GEMINI.md
| opencode) | ||
| command -v opencode >/dev/null 2>&1 || return 1 | ||
| run_with_timeout 240 opencode run "$prompt" >> "$log_file" 2>&1 | ||
| ;; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check opencode CLI for working directory flags
if command -v opencode &>/dev/null; then
echo "=== opencode help output ==="
opencode --help 2>&1 | head -50
echo ""
echo "=== opencode run help ==="
opencode run --help 2>&1 | head -30
else
echo "opencode not installed"
fiRepository: yulonglin/dotfiles
Length of output: 85
🌐 Web query:
opencode CLI working directory --cd flag documentation
💡 Result:
The OpenCode CLI does not use a --cd flag to specify the working directory. Instead, it provides the following flags to set the working directory [1][2]: --cwd: Sets the current working directory (often with the short alias -c) [1][2]. --dir: Specifies the working directory to start the TUI in [3][4]. In some versions or documentation, the flag --cwd is explicitly listed with the short alias -c (e.g., opencode -c /path/to/project) [1][2][5]. Additionally, you can often simply pass the path as an argument directly when starting the command, such as opencode /path/to/project [6]. Please check your specific version's help documentation by running opencode --help to confirm which flag is available in your installation [1][2].
Citations:
- 1: https://github.com/opencode-ai/opencode/blob/main/README.md
- 2: https://github.com/opencode-ai/opencode?referrer=medium-article
- 3: https://opencode.ai/docs/cli/
- 4: https://github.com/sst/opencode/blob/9ad6588f/packages/web/src/content/docs/cli.mdx
- 5: https://opencode-ai-opencode.mintlify.app/reference/commands
- 6: https://opencode.ai/docs/tui/
🏁 Script executed:
#!/bin/bash
# Check the context around lines 249-252 and the function signature
cat -n claude/hooks/auto_commit_worker.sh | sed -n '240,260p'Repository: yulonglin/dotfiles
Length of output: 1085
🏁 Script executed:
#!/bin/bash
# Look at the run_backend function signature and how REPO_ROOT is used
cat -n claude/hooks/auto_commit_worker.sh | sed -n '35,70p'Repository: yulonglin/dotfiles
Length of output: 1522
🏁 Script executed:
#!/bin/bash
# Check how codex backend uses --cd and the full context
cat -n claude/hooks/auto_commit_worker.sh | sed -n '240,260p'Repository: yulonglin/dotfiles
Length of output: 1085
🌐 Web query:
opencode run command syntax working directory --cwd flag example
💡 Result:
In the OpenCode CLI, the --cwd flag is primarily used for configuring the working directory when starting a server process (e.g., listening on a host/port) [1][2][3]. To specify the working directory for a standard opencode run command, you should use the --dir flag [1][2][3]. Example usage: opencode run "list the files" --dir /path/to/your/project Key details: - --dir: Specifies the directory to run in or the path on a remote server when attaching [1][2]. - --cwd: Used in the context of server startup configurations, such as setting the working directory for the server process, defining the hostname, or enabling mDNS [1][2][3]. Note that when running opencode run programmatically (e.g., from a Python subprocess), there is a known issue where the tool may prefer the environment's PWD variable over the process's actual working directory [4]. If you experience unexpected path behavior in scripts, explicitly providing the --dir flag is the recommended workaround [4].
Citations:
- 1: https://dev.opencode.ai/docs/cli/
- 2: https://github.com/anomalyco/opencode/blob/dev/packages/web/src/content/docs/cli.mdx
- 3: https://opencode.ai/docs/cli/
- 4: opencode run prefers stale PWD over subprocess cwd anomalyco/opencode#27392
Pass working directory to the opencode run command using the --dir flag.
The opencode backend at line 251 invokes opencode run "$prompt" without specifying a working directory, while the codex backend explicitly uses --cd "$REPO_ROOT". The OpenCode CLI uses the --dir flag (not --cd) to set the working directory for the run command. Without this flag, opencode may execute in an incorrect directory, causing auto-commit operations to fail or run against the wrong repository.
Additionally, OpenCode has a known issue where it may prefer the environment's PWD variable over the process's actual working directory when run from scripts, making explicit --dir specification the recommended workaround.
Update line 251 to:
run_with_timeout 240 opencode run "$prompt" --dir "$REPO_ROOT" >> "$log_file" 2>&1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@claude/hooks/auto_commit_worker.sh` around lines 249 - 252, In the opencode
case block, update the run_with_timeout command to include the --dir flag that
specifies the working directory for the opencode run command. Modify the line
containing run_with_timeout 240 opencode run "$prompt" to add --dir "$REPO_ROOT"
before the output redirection, so the opencode command executes in the correct
repository directory and avoids relying on the PWD environment variable which
may not be set correctly in script execution contexts.
| "zsh|ZSH + oh-my-zsh + powerlevel10k theme|all|true" | ||
| "tmux|Terminal multiplexer|all|true" | ||
| "ai-tools|Claude Code, Gemini CLI, Codex CLI|all|true" | ||
| "ai-tools|Claude Code, Codex CLI, OpenCode, Antigravity CLI|all|true" |
There was a problem hiding this comment.
Inconsistent tool list between install and update component descriptions.
Line 36 (ai-tools install description) includes "Antigravity CLI", but line 67 (ai-update deploy description) omits it, listing only "Claude, Codex, OpenCode". According to the update script header (context snippet), the actual update functionality does include Antigravity CLI. The description should match.
📝 Suggested fix to align descriptions
- "ai-update|Daily auto-update: Claude, Codex, OpenCode|all|true"
+ "ai-update|Daily auto-update: Claude, Codex, OpenCode, Antigravity|all|true"Also applies to: 67-67
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@config.sh` at line 36, The ai-tools install component description on line 36
includes "Antigravity CLI" in its tool list, but the ai-update deploy component
description on line 67 omits "Antigravity CLI", creating an inconsistency.
Update the ai-update component description on line 67 to include "Antigravity
CLI" in the tool list so that both the ai-tools and ai-update descriptions
reference the same set of tools.
| # NOTE: if the cask declares `auto_updates true`, brew skips it unless --greedy. | ||
| # Verify on a real Mac whether --greedy is needed for `agy` to actually move. | ||
| NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade --cask antigravity-cli 2>&1 \ |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check antigravity-cli cask auto_updates setting
if ! command -v brew &>/dev/null; then
echo "brew not available - check requires macOS"
exit 0
fi
echo "Fetching antigravity-cli cask metadata..."
brew info --cask antigravity-cli
echo ""
echo "Look for 'auto_updates' in the output above."
echo "If set to 'true', line 174 should use:"
echo " brew upgrade --cask --greedy antigravity-cli"Repository: yulonglin/dotfiles
Length of output: 104
🏁 Script executed:
cat -n custom_bins/update-ai-tools | sed -n '160,180p'Repository: yulonglin/dotfiles
Length of output: 1027
🌐 Web query:
antigravity-cli brew cask auto_updates
💡 Result:
The Homebrew cask for antigravity-cli explicitly includes the auto_updates true directive in its configuration [1]. This enables automatic updates for the application when managing it via Homebrew, allowing it to integrate with standard Homebrew Cask update workflows [1][2]. The official Homebrew Cask definition for antigravity-cli is maintained in the Homebrew/homebrew-cask repository [1]. Because it is defined as a cask, users can install it using the command brew install --cask antigravity-cli [3][4][5]. The inclusion of auto_updates true is standard practice for casks that provide their own internal update mechanisms, which in this case leverages a JSON-based manifest to track and apply updates [1].
Citations:
- 1: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/a/antigravity-cli.rb
- 2: https://blog.davep.org/2026/05/21/antigravity-cli-now-on-homebrew.html
- 3: https://formulae.brew.sh/cask/antigravity-cli
- 4: https://ksml4.com/how-to-install-google-antigravity-via-brew-for-macos/
- 5: https://learn.arm.com/install-guides/antigravity/
Add --greedy flag to brew upgrade command for antigravity-cli.
The antigravity-cli cask declares auto_updates: true, which means Homebrew will skip updates unless --greedy is specified. Without this flag, line 174's upgrade command will silently fail to update the tool.
Update to:
NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade --cask --greedy antigravity-cli 2>&1 \
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@custom_bins/update-ai-tools` around lines 172 - 174, The brew upgrade command
for the antigravity-cli cask is missing the --greedy flag, which causes Homebrew
to skip updates since this cask declares auto_updates: true. Add the --greedy
flag to the brew upgrade command line between --cask and the cask name
antigravity-cli to ensure the upgrade actually proceeds rather than being
silently skipped.
| ### Antigravity CLI (Google) + OpenCode | ||
|
|
||
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) can sync with Claude Code configurations: | ||
| Gemini CLI was retired by Google on **2026-06-18**; [Antigravity CLI](https://antigravity.google/docs/cli-features) (`agy`) is its official successor. [OpenCode](https://opencode.ai) is installed alongside as a model-agnostic OSS option. Both are installed by the `ai-tools` component. |
There was a problem hiding this comment.
Fix the retirement tense/date wording.
As of June 17, 2026, "was retired on 2026-06-18" is premature. Use future-tense phrasing (e.g., "access ends on June 18, 2026") until that date.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` at line 278, The wording in the Gemini CLI retirement statement
uses past tense ("was retired on") for a date in the future, which is
inaccurate. Change the tense from past to future by replacing "was retired on"
with future-tense phrasing such as "will be retired on" or "access ends on"
while keeping the date 2026-06-18 unchanged. This ensures the statement
correctly reflects that the retirement has not yet occurred.
| - Project instructions come from `AGENTS.md` (Antigravity reads it natively) | ||
|
|
||
| **Note:** Gemini CLI uses a different skills format. The sync script adapts Claude's configuration but some features may not translate directly. | ||
| **Note:** Antigravity CLI is closed-source and brand-new; its skills/permissions schema differs from Claude's. The skills sync is adapted but untested end-to-end — permission sync is not yet ported (see the script header). |
There was a problem hiding this comment.
Documentation contradicts current script behavior on permission sync.
This line says permission sync is not ported, but scripts/sync_claude_to_antigravity.sh now performs permissions mapping + merge. Please align the README note with the actual current behavior and caveats.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` at line 291, The README.md note at line 291 incorrectly states
that permission sync is not yet ported, but the actual script
`scripts/sync_claude_to_antigravity.sh` now includes permissions mapping and
merge functionality. Update the note to accurately reflect that the script
currently performs both skills and permissions sync, replacing the outdated
statement about permission sync not being ported with current details about how
permissions are handled (including what was adapted or any remaining caveats).
| #!/bin/bash | ||
|
|
There was a problem hiding this comment.
Add strict shell mode at script start.
The script performs filesystem mutation and JSON writes; without strict mode, failed commands can be silently ignored and still print success.
As per coding guidelines, "Shell scripts must use #!/bin/bash shebang with set -euo pipefail at the start".
Suggested patch
#!/bin/bash
+set -euo pipefail📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #!/bin/bash | |
| #!/bin/bash | |
| set -euo pipefail |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/sync_claude_to_antigravity.sh` around lines 1 - 2, The shell script
is missing strict error handling mode which can cause failed commands to be
silently ignored during filesystem mutations and JSON writes. Add `set -euo
pipefail` as a new line immediately after the `#!/bin/bash` shebang at the start
of the script. This enables the script to exit on errors, treat undefined
variables as errors, and properly handle pipe failures, ensuring that any
command failures are caught and prevent silent failures.
Source: Coding guidelines
| echo "Error: enumerate_claude_skills.sh not found at $HELPER" >&2 | ||
| exit 1 | ||
| fi | ||
| source "$HELPER" |
There was a problem hiding this comment.
Address shellcheck SC1090 for dynamic source.
Add an explicit shellcheck source directive before source "$HELPER" so CI/static checks stay clean.
As per coding guidelines, "Run shellcheck path/to/script.sh before shipping shell scripts".
Suggested patch
+# shellcheck source=scripts/helpers/enumerate_claude_skills.sh
source "$HELPER"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| source "$HELPER" | |
| # shellcheck source=scripts/helpers/enumerate_claude_skills.sh | |
| source "$HELPER" |
🧰 Tools
🪛 Shellcheck (0.11.0)
[warning] 42-42: ShellCheck can't follow non-constant source. Use a directive to specify location.
(SC1090)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/sync_claude_to_antigravity.sh` at line 42, Add a shellcheck directive
comment immediately before the `source "$HELPER"` statement to address the
SC1090 warning about dynamic source paths. Include a comment line that tells
shellcheck how to handle the dynamic sourcing (typically `# shellcheck
source=/dev/null` or similar) directly above the source command to suppress the
warning and keep CI/static checks clean.
Sources: Coding guidelines, Linters/SAST tools
| enumerate_claude_skills "$SOURCE_DIR" | while IFS=$'\t' read -r type name path; do | ||
| case "$type" in | ||
| user_skill) | ||
| ln -sfn "$path" "$TARGET_DIR/$name" | ||
| echo " User Skill: $name" | ||
| ;; | ||
| standalone_skill) | ||
| mkdir -p "$TARGET_DIR/$name" | ||
| ln -sfn "$path" "$TARGET_DIR/$name/SKILL.md" | ||
| echo " Standalone Skill: $name" | ||
| ;; | ||
| plugin_skill) | ||
| ln -sfn "$path" "$TARGET_DIR/$name" | ||
| echo " Plugin Skill: $name" | ||
| ;; | ||
| agent_skill) | ||
| mkdir -p "$TARGET_DIR/$name" | ||
| ln -sfn "$path" "$TARGET_DIR/$name/SKILL.md" | ||
| echo " Agent Skill: $name" |
There was a problem hiding this comment.
Handle skill type transitions before writing targets.
If a skill name changes type across runs (e.g., previous plugin_skill symlink, now standalone_skill wrapper dir), current logic can write SKILL.md through an old symlink target or fail to replace existing directories cleanly. Normalize destination shape per type before ln/mkdir.
Suggested patch
+sync_skill_entry() {
+ local type="$1"
+ local name="$2"
+ local path="$3"
+ local dest="$TARGET_DIR/$name"
+
+ case "$type" in
+ user_skill|plugin_skill)
+ if [ -d "$dest" ] && [ ! -L "$dest" ]; then
+ rm -rf -- "$dest"
+ fi
+ ln -sfn "$path" "$dest"
+ ;;
+ standalone_skill|agent_skill)
+ if [ -L "$dest" ]; then
+ rm -f -- "$dest"
+ fi
+ mkdir -p "$dest"
+ ln -sfn "$path" "$dest/SKILL.md"
+ ;;
+ esac
+}
+
enumerate_claude_skills "$SOURCE_DIR" | while IFS=$'\t' read -r type name path; do
- case "$type" in
- user_skill)
- ln -sfn "$path" "$TARGET_DIR/$name"
- echo " User Skill: $name"
- ;;
- standalone_skill)
- mkdir -p "$TARGET_DIR/$name"
- ln -sfn "$path" "$TARGET_DIR/$name/SKILL.md"
- echo " Standalone Skill: $name"
- ;;
- plugin_skill)
- ln -sfn "$path" "$TARGET_DIR/$name"
- echo " Plugin Skill: $name"
- ;;
- agent_skill)
- mkdir -p "$TARGET_DIR/$name"
- ln -sfn "$path" "$TARGET_DIR/$name/SKILL.md"
- echo " Agent Skill: $name"
- ;;
- esac
+ sync_skill_entry "$type" "$name" "$path"
+ echo " ${type}: $name"
done📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| enumerate_claude_skills "$SOURCE_DIR" | while IFS=$'\t' read -r type name path; do | |
| case "$type" in | |
| user_skill) | |
| ln -sfn "$path" "$TARGET_DIR/$name" | |
| echo " User Skill: $name" | |
| ;; | |
| standalone_skill) | |
| mkdir -p "$TARGET_DIR/$name" | |
| ln -sfn "$path" "$TARGET_DIR/$name/SKILL.md" | |
| echo " Standalone Skill: $name" | |
| ;; | |
| plugin_skill) | |
| ln -sfn "$path" "$TARGET_DIR/$name" | |
| echo " Plugin Skill: $name" | |
| ;; | |
| agent_skill) | |
| mkdir -p "$TARGET_DIR/$name" | |
| ln -sfn "$path" "$TARGET_DIR/$name/SKILL.md" | |
| echo " Agent Skill: $name" | |
| sync_skill_entry() { | |
| local type="$1" | |
| local name="$2" | |
| local path="$3" | |
| local dest="$TARGET_DIR/$name" | |
| case "$type" in | |
| user_skill|plugin_skill) | |
| if [ -d "$dest" ] && [ ! -L "$dest" ]; then | |
| rm -rf -- "$dest" | |
| fi | |
| ln -sfn "$path" "$dest" | |
| ;; | |
| standalone_skill|agent_skill) | |
| if [ -L "$dest" ]; then | |
| rm -f -- "$dest" | |
| fi | |
| mkdir -p "$dest" | |
| ln -sfn "$path" "$dest/SKILL.md" | |
| ;; | |
| esac | |
| } | |
| enumerate_claude_skills "$SOURCE_DIR" | while IFS=$'\t' read -r type name path; do | |
| sync_skill_entry "$type" "$name" "$path" | |
| echo " ${type}: $name" | |
| done |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/sync_claude_to_antigravity.sh` around lines 52 - 70, The skill
synchronization logic does not handle cases where a skill changes type between
sync runs, which can cause symlinks to point to old targets or fail to replace
existing directories. Before executing the ln or mkdir commands in each case
statement (user_skill, standalone_skill, plugin_skill, agent_skill), add logic
to remove any existing target at $TARGET_DIR/$name if it exists and is
incompatible with the current skill type (e.g., remove a symlink when a
directory is needed, or remove a directory when a symlink is needed). This
normalization of the destination shape per skill type should happen before any
ln or mkdir operations to ensure clean transitions.
| BEGIN = "// BEGIN CLAUDE SYNC (auto-generated)" | ||
| END = "// END CLAUDE SYNC" | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the repository structure and locate the file
git ls-files | grep -E "(sync|antigravity)" | head -20Repository: yulonglin/dotfiles
Length of output: 873
🏁 Script executed:
# Now let's read the script to understand the issue
wc -l scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 104
🏁 Script executed:
# Read the file around lines 112-114
sed -n '105,120p' scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 570
🏁 Script executed:
# Read the file around lines 217-240
sed -n '210,245p' scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 1127
🏁 Script executed:
# Get the full context - read the entire script in sections to understand the flow
head -150 scripts/sync_claude_to_antigravity.sh | tail -50Repository: yulonglin/dotfiles
Length of output: 1800
🏁 Script executed:
# Search for Antigravity-related files and documentation
find . -type f -name "*antigravity*" -o -name "*permission*" | head -20Repository: yulonglin/dotfiles
Length of output: 176
🏁 Script executed:
# Look for any error handling or validation in the sync script
grep -n "permission\|validate\|error\|except" scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 1720
🏁 Script executed:
# Check if there's any Antigravity configuration or settings file
find . -type f \( -name "*.json" -o -name "*.rules" \) | grep -E "(antigravity|permission)" | head -10Repository: yulonglin/dotfiles
Length of output: 44
🏁 Script executed:
# Look at the codex rules mentioned in the context
cat codex/rules/claude_sync.rules 2>/dev/null || echo "File not found"Repository: yulonglin/dotfiles
Length of output: 5969
🏁 Script executed:
# Check for any documentation about permission format
find . -type f \( -name "*.md" \) -exec grep -l "permission\|Antigravity" {} \; | head -10Repository: yulonglin/dotfiles
Length of output: 1947
🏁 Script executed:
# Look for usage of sidecar_path in the script
grep -n "sidecar" scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 766
🏁 Script executed:
# Check the full merge_bucket function and surrounding context more carefully
sed -n '195,260p' scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 2395
🏁 Script executed:
# Look at the documentation comment at the top about the schema
sed -n '1,40p' scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 2213
🏁 Script executed:
# Check if there are any tests or validation of the generated permissions
find . -type f -name "*.sh" -o -name "*test*" | xargs grep -l "antigravity\|sync_claude" 2>/dev/null | head -10Repository: yulonglin/dotfiles
Length of output: 155
🏁 Script executed:
# Check if there's any actual error handling or validation feedback in the script
tail -20 scripts/sync_claude_to_antigravity.shRepository: yulonglin/dotfiles
Length of output: 1309
🏁 Script executed:
# Look for any GitHub issues or documentation about this problem
find . -type f \( -name "*.md" -o -name "ISSUE*" -o -name "TODO*" \) -exec grep -l "BEGIN\|END\|antigravity.*validation\|permission.*format" {} \; 2>/dev/null | head -5Repository: yulonglin/dotfiles
Length of output: 282
Review marker strings violate Antigravity permission schema; use sidecar metadata instead.
The BEGIN and END markers (lines 112–114) are inserted as literal array elements into permissions.allow/deny/ask (line 248), but Antigravity's documented schema expects only "action(target)" strings in these arrays. If Antigravity validates strictly, these markers may cause validation errors or be silently rejected.
Track which entries your script manages using sidecar metadata (already initialized at line 108), then recompute arrays by filtering out old entries via set-difference rather than relying on in-array sentinel strings. The script's own TODO comment (line 277) acknowledges this hasn't been validated on real Antigravity, so test the current output on a real Mac before merging.
Applies to the merge_bucket() logic at lines 217–240 and the final write at line 248.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/sync_claude_to_antigravity.sh` around lines 112 - 114, The BEGIN and
END marker strings (lines 112-114) violate Antigravity's permission schema by
being inserted as literal array elements into permissions.allow/deny/ask arrays
at line 248, when the schema expects only "action(target)" formatted strings.
Replace the marker-based tracking approach with sidecar metadata (already
initialized at line 108) to track which entries are managed by the script.
Modify the merge_bucket() logic (lines 217-240) and the final permissions write
(line 248) to use set-difference filtering instead of searching for BEGIN and
END sentinel strings, removing old managed entries by comparing against stored
metadata rather than marker positions. Test the output on a real Antigravity
configuration before merging to validate the new approach works correctly.
Post-merge cleanup for PRs #5/#6: - README/CLAUDE.md: replace remaining 'Gemini CLI' mentions with the actual installed/updated set (Codex, OpenCode, Antigravity CLI) - docs/cross-tool-extensibility.md: repoint the now-deleted sync_claude_to_gemini.sh to sync_claude_to_antigravity.sh; note Gemini CLI retirement (2026-06-18) - app-picker: descriptions containing commas (e.g. Notion) broke gum --selected pre-selection; normalise commas in labels so the CSV is unambiguous Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
Gemini CLI consumer access ends 2026-06-18. This migrates the dotfiles off Gemini CLI to its official successor Antigravity CLI (
agy) plus OpenCode (OSS, multi-provider,homebrew/core) as a model-agnostic option.Split out of #4 (part 1 of 2) — this is the higher-risk half (it changes auto-commit automation), isolated so it can be reverted independently.
Changes
helpers.sh:install_gemini_cli→install_opencode(core formula) +install_antigravity_cli(caskantigravity-cli; Linux = manual per curl|bash policy)install.sh/config.sh/update-ai-tools/ai-check: swap Gemini → OpenCode + Antigravity; drop Coven +Crazytieguy/tap(third-party tap violates the no-new-taps policy)auto_commit_worker.sh+ai_automation.sh: auto-commit backend ordercodex,gemini→codex,opencodesync_claude_to_gemini.sh→sync_claude_to_antigravity.sh(skills →~/.gemini/antigravity-cli/skills; permission sync intosettings.json, unmapped rules to a sidecar)GEMINI.md+gemini/GEMINI.md(AGENTS.md is the successor instruction file)supply-chain-security.md: two-gate (security-floor → adoption) tool-selection ruleVerification
formulae.brew.sh:antigravity-clicask exists, ships theagybinary, and zaps~/.gemini/antigravity-cli;opencodeis inhomebrew/core.agypermission-schema load, glob match semantics (see the sync script header TODO).Merge note
Shares 3 files with the app-setup PR (
install.sh,config.sh,supply-chain-security.md). Merging both is conflict-free except one trivial "keep both" conflict insupply-chain-security.md(adjacent section inserts).🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores