code-aide 1.15.6__tar.gz → 1.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {code_aide-1.15.6 → code_aide-1.16.0}/PKG-INFO +37 -29
- {code_aide-1.15.6 → code_aide-1.16.0}/README.md +35 -27
- {code_aide-1.15.6 → code_aide-1.16.0}/pyproject.toml +1 -1
- code_aide-1.16.0/script-archive/antigravity-install.sh +239 -0
- code_aide-1.16.0/specs/antigravity-cli-integration.md +35 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/__init__.py +1 -1
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/commands_actions.py +11 -4
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/config.py +21 -1
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/data/tools.json +26 -3
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/install.py +49 -13
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/operations.py +7 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/prereqs.py +9 -14
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/status.py +15 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/versions.py +40 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_commands_actions.py +64 -1
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_config.py +63 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_install.py +16 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_operations.py +21 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_prereqs.py +3 -9
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_status.py +18 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_versions.py +69 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/.github/workflows/ci.yml +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/.github/workflows/publish.yml +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/.gitignore +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/.gitlab-ci.yml +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/.pre-commit-config.yaml +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/AGENTS.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/CLAUDE.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/LICENSE +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/TODO.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/script-archive/README.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/script-archive/amp-install.sh +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/script-archive/claude-install.sh +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/script-archive/cursor-install.sh +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/2026-05-03-qwen3.6-code-quality-analysis-original.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/2026-05-03-qwen3.6-code-quality-analysis.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/auto-migrate-deprecated-installs.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/claude-native-installer-migration.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/missing-coding-llm-cli-tools.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/pre-commit-uv-setup.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/remove-bundled-version-baseline.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/specs/unify-upgrade-eligibility-with-shared-evaluator.md +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/__main__.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/commands_tools.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/console.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/constants.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/detection.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/detection_types.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/entry.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/install_types.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/operation_handlers.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/package_info.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/package_managers.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/src/code_aide/status_print.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_commands_tools.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_console.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_constants.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_detection.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_entry.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_error_paths.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_install_types.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/tests/test_package_managers.py +0 -0
- {code_aide-1.15.6 → code_aide-1.16.0}/uv.lock +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-aide
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary: Manage AI coding CLI tools (Claude, Copilot, Cursor, Gemini, Amp, Codex)
|
|
3
|
+
Version: 1.16.0
|
|
4
|
+
Summary: Manage AI coding CLI tools (Claude, Antigravity, Copilot, Cursor, Gemini, Amp, Codex)
|
|
5
5
|
Project-URL: Homepage, https://github.com/dajobe/code-aide
|
|
6
6
|
Project-URL: Repository, https://github.com/dajobe/code-aide
|
|
7
7
|
Project-URL: Issues, https://github.com/dajobe/code-aide/issues
|
|
@@ -30,7 +30,8 @@ Description-Content-Type: text/markdown
|
|
|
30
30
|
An aide for your AI coding tools.
|
|
31
31
|
|
|
32
32
|
Manages installation, upgrade, removal, and version tracking of AI coding CLI
|
|
33
|
-
tools: Claude Code, Copilot, Cursor, Gemini, Amp, Codex, OpenCode,
|
|
33
|
+
tools: Claude Code, Antigravity, Copilot, Cursor, Gemini, Amp, Codex, OpenCode,
|
|
34
|
+
and Kilo.
|
|
34
35
|
|
|
35
36
|
## Installation
|
|
36
37
|
|
|
@@ -58,7 +59,7 @@ code-aide status
|
|
|
58
59
|
code-aide status -l
|
|
59
60
|
|
|
60
61
|
# Install specific tools
|
|
61
|
-
code-aide install claude
|
|
62
|
+
code-aide install claude antigravity
|
|
62
63
|
|
|
63
64
|
# Install all default tools
|
|
64
65
|
code-aide install
|
|
@@ -83,15 +84,19 @@ code-aide update-versions -y
|
|
|
83
84
|
|
|
84
85
|
| Tool | Command | Install Type | Default |
|
|
85
86
|
|:-------------------------|:-----------|:----------------|:--------|
|
|
86
|
-
| Cursor CLI | `agent` | Direct download |
|
|
87
|
+
| Cursor CLI | `agent` | Direct download | No |
|
|
87
88
|
| Claude CLI (Claude Code) | `claude` | Script | Yes |
|
|
88
|
-
|
|
|
89
|
+
| Antigravity CLI | `agy` | Script | Yes |
|
|
90
|
+
| Gemini CLI | `gemini` | npm | No |
|
|
89
91
|
| OpenCode | `opencode` | npm | No |
|
|
90
92
|
| Kilo CLI | `kilo` | npm | No |
|
|
91
93
|
| Amp (Sourcegraph) | `amp` | Script | No |
|
|
92
94
|
| Codex CLI | `codex` | npm | No |
|
|
93
95
|
| Copilot CLI | `copilot` | npm | No |
|
|
94
96
|
|
|
97
|
+
Command aliases are also accepted: `agy` resolves to `antigravity`, and `agent`
|
|
98
|
+
resolves to `cursor`.
|
|
99
|
+
|
|
95
100
|
## How Version Data Works
|
|
96
101
|
|
|
97
102
|
code-aide uses a two-layer version data model:
|
|
@@ -113,29 +118,32 @@ Each entry in `tools.json` describes one managed tool. Required fields are
|
|
|
113
118
|
`name`, `command`, and `install_type`; the others are optional and only
|
|
114
119
|
consulted when the relevant install method or platform applies.
|
|
115
120
|
|
|
116
|
-
| Field
|
|
117
|
-
|
|
118
|
-
| `name`
|
|
119
|
-
| `command`
|
|
120
|
-
| `
|
|
121
|
-
| `
|
|
122
|
-
| `
|
|
123
|
-
| `
|
|
124
|
-
| `
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
121
|
+
| Field | Required | Notes |
|
|
122
|
+
|:--------------------------------|:---------|:---------------------------------------------------------------------------------------------|
|
|
123
|
+
| `name` | Yes | Display name for status output |
|
|
124
|
+
| `command` | Yes | Binary name (looked up in `PATH`) |
|
|
125
|
+
| `aliases` | No | Alternate names accepted by commands and resolved to the canonical tool key |
|
|
126
|
+
| `install_type` | Yes | One of `npm`, `script`, `direct_download`, `pkg` |
|
|
127
|
+
| `version_args` | No | List of arguments passed to the binary to print its version (default: `["--version"]`) |
|
|
128
|
+
| `version_url` | No | URL queried by `update-versions` to discover the latest upstream version |
|
|
129
|
+
| `version_manifest_url_template` | No | JSON manifest URL template with `{platform}`; reads its `version` field |
|
|
130
|
+
| `latest_version` | Cache | Last known upstream version (filled by `update-versions`) |
|
|
131
|
+
| `latest_date` | Cache | Release date for `latest_version` |
|
|
132
|
+
| `prerequisites` | No | List of required external commands (e.g. `["npm"]`) |
|
|
133
|
+
| `min_node_version` | No | Minimum major Node.js version required |
|
|
134
|
+
| `npm_package` | npm | npm package name (e.g. `@anthropic-ai/claude-code`) |
|
|
135
|
+
| `install_url` | script | URL of the install script that will be downloaded and piped to `bash` |
|
|
136
|
+
| `install_sha256` | script | SHA-256 of the install script body — required for verified installs |
|
|
137
|
+
| `install_script_path_prepend` | script | Extra directories prepended to `PATH` when the install script runs (e.g. `["~/.local/bin"]`) |
|
|
138
|
+
| `download_url_template` | direct | URL template with `{version}`, `{os}`, `{arch}` placeholders |
|
|
139
|
+
| `install_dir` | direct | Directory to extract into; supports `{version}` |
|
|
140
|
+
| `bin_dir` | direct | Directory where symlinks for `command` are created (e.g. `~/.local/bin`) |
|
|
141
|
+
| `symlinks` | direct | Map of `link_name` → relative path inside `install_dir` to symlink into `bin_dir` |
|
|
142
|
+
| `freebsd_port` | FreeBSD | FreeBSD ports/pkg name (used when running on FreeBSD) |
|
|
143
|
+
| `freebsd_pkg_repo` | FreeBSD | Optional non-default pkg repository name (passed via `pkg install -r <repo>`) |
|
|
144
|
+
| `next_steps` | No | Free-form text printed after a successful install |
|
|
145
|
+
| `docs_url` | No | Documentation URL printed after install |
|
|
146
|
+
| `self_updates` | No | Tool updates itself when run; excludes it from managed upgrade actions |
|
|
139
147
|
|
|
140
148
|
## Features
|
|
141
149
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
An aide for your AI coding tools.
|
|
4
4
|
|
|
5
5
|
Manages installation, upgrade, removal, and version tracking of AI coding CLI
|
|
6
|
-
tools: Claude Code, Copilot, Cursor, Gemini, Amp, Codex, OpenCode,
|
|
6
|
+
tools: Claude Code, Antigravity, Copilot, Cursor, Gemini, Amp, Codex, OpenCode,
|
|
7
|
+
and Kilo.
|
|
7
8
|
|
|
8
9
|
## Installation
|
|
9
10
|
|
|
@@ -31,7 +32,7 @@ code-aide status
|
|
|
31
32
|
code-aide status -l
|
|
32
33
|
|
|
33
34
|
# Install specific tools
|
|
34
|
-
code-aide install claude
|
|
35
|
+
code-aide install claude antigravity
|
|
35
36
|
|
|
36
37
|
# Install all default tools
|
|
37
38
|
code-aide install
|
|
@@ -56,15 +57,19 @@ code-aide update-versions -y
|
|
|
56
57
|
|
|
57
58
|
| Tool | Command | Install Type | Default |
|
|
58
59
|
|:-------------------------|:-----------|:----------------|:--------|
|
|
59
|
-
| Cursor CLI | `agent` | Direct download |
|
|
60
|
+
| Cursor CLI | `agent` | Direct download | No |
|
|
60
61
|
| Claude CLI (Claude Code) | `claude` | Script | Yes |
|
|
61
|
-
|
|
|
62
|
+
| Antigravity CLI | `agy` | Script | Yes |
|
|
63
|
+
| Gemini CLI | `gemini` | npm | No |
|
|
62
64
|
| OpenCode | `opencode` | npm | No |
|
|
63
65
|
| Kilo CLI | `kilo` | npm | No |
|
|
64
66
|
| Amp (Sourcegraph) | `amp` | Script | No |
|
|
65
67
|
| Codex CLI | `codex` | npm | No |
|
|
66
68
|
| Copilot CLI | `copilot` | npm | No |
|
|
67
69
|
|
|
70
|
+
Command aliases are also accepted: `agy` resolves to `antigravity`, and `agent`
|
|
71
|
+
resolves to `cursor`.
|
|
72
|
+
|
|
68
73
|
## How Version Data Works
|
|
69
74
|
|
|
70
75
|
code-aide uses a two-layer version data model:
|
|
@@ -86,29 +91,32 @@ Each entry in `tools.json` describes one managed tool. Required fields are
|
|
|
86
91
|
`name`, `command`, and `install_type`; the others are optional and only
|
|
87
92
|
consulted when the relevant install method or platform applies.
|
|
88
93
|
|
|
89
|
-
| Field
|
|
90
|
-
|
|
91
|
-
| `name`
|
|
92
|
-
| `command`
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
94
|
+
| Field | Required | Notes |
|
|
95
|
+
|:--------------------------------|:---------|:---------------------------------------------------------------------------------------------|
|
|
96
|
+
| `name` | Yes | Display name for status output |
|
|
97
|
+
| `command` | Yes | Binary name (looked up in `PATH`) |
|
|
98
|
+
| `aliases` | No | Alternate names accepted by commands and resolved to the canonical tool key |
|
|
99
|
+
| `install_type` | Yes | One of `npm`, `script`, `direct_download`, `pkg` |
|
|
100
|
+
| `version_args` | No | List of arguments passed to the binary to print its version (default: `["--version"]`) |
|
|
101
|
+
| `version_url` | No | URL queried by `update-versions` to discover the latest upstream version |
|
|
102
|
+
| `version_manifest_url_template` | No | JSON manifest URL template with `{platform}`; reads its `version` field |
|
|
103
|
+
| `latest_version` | Cache | Last known upstream version (filled by `update-versions`) |
|
|
104
|
+
| `latest_date` | Cache | Release date for `latest_version` |
|
|
105
|
+
| `prerequisites` | No | List of required external commands (e.g. `["npm"]`) |
|
|
106
|
+
| `min_node_version` | No | Minimum major Node.js version required |
|
|
107
|
+
| `npm_package` | npm | npm package name (e.g. `@anthropic-ai/claude-code`) |
|
|
108
|
+
| `install_url` | script | URL of the install script that will be downloaded and piped to `bash` |
|
|
109
|
+
| `install_sha256` | script | SHA-256 of the install script body — required for verified installs |
|
|
110
|
+
| `install_script_path_prepend` | script | Extra directories prepended to `PATH` when the install script runs (e.g. `["~/.local/bin"]`) |
|
|
111
|
+
| `download_url_template` | direct | URL template with `{version}`, `{os}`, `{arch}` placeholders |
|
|
112
|
+
| `install_dir` | direct | Directory to extract into; supports `{version}` |
|
|
113
|
+
| `bin_dir` | direct | Directory where symlinks for `command` are created (e.g. `~/.local/bin`) |
|
|
114
|
+
| `symlinks` | direct | Map of `link_name` → relative path inside `install_dir` to symlink into `bin_dir` |
|
|
115
|
+
| `freebsd_port` | FreeBSD | FreeBSD ports/pkg name (used when running on FreeBSD) |
|
|
116
|
+
| `freebsd_pkg_repo` | FreeBSD | Optional non-default pkg repository name (passed via `pkg install -r <repo>`) |
|
|
117
|
+
| `next_steps` | No | Free-form text printed after a successful install |
|
|
118
|
+
| `docs_url` | No | Documentation URL printed after install |
|
|
119
|
+
| `self_updates` | No | Tool updates itself when run; excludes it from managed upgrade actions |
|
|
112
120
|
|
|
113
121
|
## Features
|
|
114
122
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "code-aide"
|
|
3
3
|
dynamic = ["version"]
|
|
4
|
-
description = "Manage AI coding CLI tools (Claude, Copilot, Cursor, Gemini, Amp, Codex)"
|
|
4
|
+
description = "Manage AI coding CLI tools (Claude, Antigravity, Copilot, Cursor, Gemini, Amp, Codex)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
7
7
|
{ name = "Dave Beckett" },
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Antigravity CLI - Unix Bootstrapper Script (Bash/Zsh/Fish)
|
|
4
|
+
#
|
|
5
|
+
# Downloads, staging-verifies, and installs the Antigravity CLI flat native build.
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
# 1. Default Setup & Constants
|
|
11
|
+
DOWNLOAD_BASE_URL="https://antigravity-cli-auto-updater-974169037036.us-central1.run.app"
|
|
12
|
+
TARGET_DIR="$HOME/.local/bin"
|
|
13
|
+
CUSTOM_DIR=""
|
|
14
|
+
|
|
15
|
+
# Helper: Display usage instructions
|
|
16
|
+
show_usage() {
|
|
17
|
+
echo "Usage: install.sh [options]"
|
|
18
|
+
echo ""
|
|
19
|
+
echo "Options:"
|
|
20
|
+
echo " -d, --dir <path> Specify a custom directory to install the binary"
|
|
21
|
+
echo " -h, --help Display this help menu"
|
|
22
|
+
echo ""
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# Parse Arguments
|
|
26
|
+
while [ "$#" -gt 0 ]; do
|
|
27
|
+
case $1 in
|
|
28
|
+
-d|--dir)
|
|
29
|
+
if [ -z "${2:-}" ]; then
|
|
30
|
+
echo "[ERROR] Missing path for --dir parameter" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
CUSTOM_DIR="$2"
|
|
34
|
+
shift
|
|
35
|
+
;;
|
|
36
|
+
-h|--help)
|
|
37
|
+
show_usage
|
|
38
|
+
exit 0
|
|
39
|
+
;;
|
|
40
|
+
*)
|
|
41
|
+
echo "[ERROR] Unknown parameter: $1" >&2
|
|
42
|
+
show_usage
|
|
43
|
+
exit 1
|
|
44
|
+
;;
|
|
45
|
+
esac
|
|
46
|
+
shift
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
# Resolve dynamic installation target directory
|
|
50
|
+
if [ -n "$CUSTOM_DIR" ]; then
|
|
51
|
+
TARGET_DIR="$CUSTOM_DIR"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
BINARY_PATH="$TARGET_DIR/agy"
|
|
55
|
+
|
|
56
|
+
# 2. STEP 1: Pre-existence & Dynamic Path Check
|
|
57
|
+
if [ -f "$BINARY_PATH" ]; then
|
|
58
|
+
echo "Notice: 'agy' is already installed at $BINARY_PATH."
|
|
59
|
+
echo "The Antigravity CLI automatically self-updates in the background during regular runs."
|
|
60
|
+
echo ""
|
|
61
|
+
echo "If you want to perform a fresh installation, delete the binary first:"
|
|
62
|
+
echo " rm \"$BINARY_PATH\""
|
|
63
|
+
exit 0
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
echo "⠋ Detecting system environment..."
|
|
67
|
+
|
|
68
|
+
# 3. Detect Platform
|
|
69
|
+
case "$(uname -s)" in
|
|
70
|
+
Darwin) os="darwin" ;;
|
|
71
|
+
Linux) os="linux" ;;
|
|
72
|
+
*) echo "Fatal: Unsupported operating system: $(uname -s). Antigravity CLI currently supports 64-bit Windows, macOS, and Linux." >&2; exit 1 ;;
|
|
73
|
+
esac
|
|
74
|
+
|
|
75
|
+
case "$(uname -m)" in
|
|
76
|
+
x86_64|amd64) arch="amd64" ;;
|
|
77
|
+
arm64|aarch64) arch="arm64" ;;
|
|
78
|
+
*) echo "Fatal: Unsupported architecture: $(uname -m). Antigravity CLI currently supports 64-bit Windows, macOS, and Linux." >&2; exit 1 ;;
|
|
79
|
+
esac
|
|
80
|
+
|
|
81
|
+
# musl libc detection on Linux
|
|
82
|
+
platform=""
|
|
83
|
+
if [ "$os" = "linux" ]; then
|
|
84
|
+
if [ -f /lib/libc.musl-x86_64.so.1 ] || [ -f /lib/libc.musl-aarch64.so.1 ] || ldd /bin/ls 2>&1 | grep -q musl; then
|
|
85
|
+
platform="linux_${arch}_musl"
|
|
86
|
+
else
|
|
87
|
+
platform="linux_${arch}"
|
|
88
|
+
fi
|
|
89
|
+
else
|
|
90
|
+
platform="${os}_${arch}"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
echo "✓ Platform detected: $platform"
|
|
94
|
+
|
|
95
|
+
# 4. Manifest Query & JSON Parsing (POSIX-Compliant)
|
|
96
|
+
echo "⠋ Querying release repository..."
|
|
97
|
+
|
|
98
|
+
# Construct Platform JSON Manifest URL
|
|
99
|
+
MANIFEST_URL="$DOWNLOAD_BASE_URL/manifests/$platform.json"
|
|
100
|
+
|
|
101
|
+
DOWNLOADER=""
|
|
102
|
+
if command -v curl >/dev/null 2>&1; then
|
|
103
|
+
DOWNLOADER="curl"
|
|
104
|
+
elif command -v wget >/dev/null 2>&1; then
|
|
105
|
+
DOWNLOADER="wget"
|
|
106
|
+
else
|
|
107
|
+
echo "Fatal: Either curl or wget is required but neither is installed." >&2
|
|
108
|
+
exit 1
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
fetch_manifest() {
|
|
112
|
+
if [ "$DOWNLOADER" = "curl" ]; then
|
|
113
|
+
curl -fsSL "$1"
|
|
114
|
+
else
|
|
115
|
+
wget -q -O - "$1"
|
|
116
|
+
fi
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
manifest_json=$(fetch_manifest "$MANIFEST_URL" 2>/dev/null || true)
|
|
120
|
+
if [ -z "$manifest_json" ]; then
|
|
121
|
+
echo "Fatal: Could not connect to the release server to download the manifest. Please check your internet connection or firewall settings." >&2
|
|
122
|
+
exit 1
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# POSIX-compliant JSON parser (no jq or grep -o dependencies)
|
|
126
|
+
parse_json_key() {
|
|
127
|
+
local payload="$1"
|
|
128
|
+
local key="$2"
|
|
129
|
+
echo "$payload" | sed -n 's/.*"'"$key"'"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
version=$(parse_json_key "$manifest_json" "version")
|
|
133
|
+
url=$(parse_json_key "$manifest_json" "url")
|
|
134
|
+
sha512=$(parse_json_key "$manifest_json" "sha512")
|
|
135
|
+
|
|
136
|
+
if [ -z "$url" ] || [ -z "$sha512" ]; then
|
|
137
|
+
echo "Fatal: Failed to parse release manifest. The manifest may be corrupted or malformed." >&2
|
|
138
|
+
exit 1
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
echo "✓ Latest available version: $version"
|
|
142
|
+
|
|
143
|
+
# 5. Download & SHA512 Checksum Verification
|
|
144
|
+
STAGING_DIR="$HOME/.cache/antigravity/staging"
|
|
145
|
+
if ! mkdir -p "$STAGING_DIR" 2>/dev/null; then
|
|
146
|
+
echo "Error: Failed to create staging directory at $STAGING_DIR. Please check your home directory write permissions." >&2
|
|
147
|
+
exit 1
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
is_tar_gz=false
|
|
151
|
+
case "$url" in
|
|
152
|
+
*.tar.gz*) is_tar_gz=true ;;
|
|
153
|
+
esac
|
|
154
|
+
|
|
155
|
+
if [ "$is_tar_gz" = true ]; then
|
|
156
|
+
staging_payload="$STAGING_DIR/agy.tar.gz"
|
|
157
|
+
extracted_binary="$STAGING_DIR/antigravity"
|
|
158
|
+
else
|
|
159
|
+
staging_payload="$STAGING_DIR/agy"
|
|
160
|
+
extracted_binary="$staging_payload"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
# Robust cleanup trap to ensure staging files are reaped on any exit (success or failure)
|
|
164
|
+
cleanup() {
|
|
165
|
+
rm -f "${staging_payload:-}" "${extracted_binary:-}" 2>/dev/null || true
|
|
166
|
+
}
|
|
167
|
+
trap cleanup EXIT
|
|
168
|
+
|
|
169
|
+
download_file() {
|
|
170
|
+
local src="$1"
|
|
171
|
+
local dst="$2"
|
|
172
|
+
if [ "$DOWNLOADER" = "curl" ]; then
|
|
173
|
+
curl -fsSL -o "$dst" "$src"
|
|
174
|
+
else
|
|
175
|
+
wget -q -O "$dst" "$src"
|
|
176
|
+
fi
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
echo "⠋ Downloading release package..."
|
|
180
|
+
if ! download_file "$url" "$staging_payload"; then
|
|
181
|
+
echo "Fatal: Failed to download release package from $url. Please check your internet connection or firewall settings." >&2
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Compute OS-Specific SHA512 Checksum
|
|
186
|
+
actual_hash=""
|
|
187
|
+
if [ "$os" = "darwin" ]; then
|
|
188
|
+
actual_hash=$(shasum -a 512 "$staging_payload" | cut -d' ' -f1 || true)
|
|
189
|
+
else
|
|
190
|
+
actual_hash=$(sha512sum "$staging_payload" | cut -d' ' -f1 || true)
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
if [ "$actual_hash" != "$sha512" ]; then
|
|
194
|
+
echo "Security Halt: The downloaded payload checksum does not match the manifest. The file may be corrupted or compromised. Installation aborted." >&2
|
|
195
|
+
exit 1
|
|
196
|
+
fi
|
|
197
|
+
echo "✓ Download complete and checksum verified."
|
|
198
|
+
|
|
199
|
+
# 6. Direct Binary Extraction & Write Permission Validation
|
|
200
|
+
if ! mkdir -p "$TARGET_DIR" 2>/dev/null; then
|
|
201
|
+
echo "Write Error: Permission denied when attempting to create $TARGET_DIR. Please re-run the installer using the '--dir' flag to specify a writable custom directory." >&2
|
|
202
|
+
exit 1
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
if [ "$is_tar_gz" = true ]; then
|
|
206
|
+
echo "⠋ Extracting binary from archive..."
|
|
207
|
+
if ! tar -xzf "$staging_payload" -C "$STAGING_DIR" antigravity 2>/dev/null; then
|
|
208
|
+
echo "Extraction Error: Failed to extract binary from archive." >&2
|
|
209
|
+
exit 1
|
|
210
|
+
fi
|
|
211
|
+
else
|
|
212
|
+
echo "⠋ Copying binary directly to destination..."
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
if ! cp "$extracted_binary" "$BINARY_PATH" 2>/dev/null; then
|
|
216
|
+
echo "Write Error: Permission denied when attempting to write binary to $BINARY_PATH. Please re-run the installer using the '--dir' flag to specify a writable custom directory." >&2
|
|
217
|
+
exit 1
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# Ensure Executable Permission Bit (soft fallback if filesystem doesn't support chmod)
|
|
221
|
+
chmod +x "$BINARY_PATH" || echo "Warning: Could not set executable permission bit on $BINARY_PATH. You may need to ensure the partition supports execution." >&2
|
|
222
|
+
|
|
223
|
+
# Clear macOS Gatekeeper Quarantine attribute to prevent unidentified developer blocks
|
|
224
|
+
if [ "$os" = "darwin" ]; then
|
|
225
|
+
xattr -d com.apple.quarantine "$BINARY_PATH" 2>/dev/null || true
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
# 7. Native Setup Handoff (Go-Native Setup Trigger - POSIX /bin/sh Compliant)
|
|
229
|
+
echo "⠋ Configuring shell environment..."
|
|
230
|
+
|
|
231
|
+
if [ -n "$CUSTOM_DIR" ]; then
|
|
232
|
+
# Run with custom directory and absorb non-fatal soft warning exits
|
|
233
|
+
"$BINARY_PATH" install --dir "$CUSTOM_DIR" || true
|
|
234
|
+
else
|
|
235
|
+
# Run standard configuration and absorb non-fatal soft warning exits
|
|
236
|
+
"$BINARY_PATH" install || true
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Add Antigravity CLI support
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
Google transitioned consumer Gemini CLI access to Antigravity CLI on June 18,
|
|
6
|
+
2026. Gemini CLI remains valid for enterprise, Google Cloud, and supported API
|
|
7
|
+
key authentication, so code-aide must manage the two commands separately and
|
|
8
|
+
must not remove or migrate existing Gemini installations.
|
|
9
|
+
|
|
10
|
+
## Design
|
|
11
|
+
|
|
12
|
+
- Add Antigravity as the default tool key `antigravity`, using command `agy`.
|
|
13
|
+
- Accept `agy` as a command-line alias for the canonical `antigravity` key.
|
|
14
|
+
- Install it through Google's native script and verify the archived script's
|
|
15
|
+
SHA-256 before execution.
|
|
16
|
+
- Query the installer's official platform manifest and read its `version` field
|
|
17
|
+
when refreshing the latest-version cache.
|
|
18
|
+
- Record that `agy` uses its native background self-updater, so code-aide does
|
|
19
|
+
not repeatedly invoke an installer that intentionally exits when the binary
|
|
20
|
+
already exists.
|
|
21
|
+
- Keep Gemini CLI available as an opt-in npm tool with updated authentication
|
|
22
|
+
guidance.
|
|
23
|
+
- Do not infer a user's Google subscription or automatically migrate Gemini.
|
|
24
|
+
|
|
25
|
+
The manifest URL uses `{platform}` values such as `darwin_arm64` and
|
|
26
|
+
`linux_amd64`. The formatter supports the macOS and Linux architectures that the
|
|
27
|
+
upstream Unix installer supports.
|
|
28
|
+
|
|
29
|
+
## Verification
|
|
30
|
+
|
|
31
|
+
1. Confirm the archived installer exactly matches the configured SHA-256.
|
|
32
|
+
2. Test manifest URL formatting and JSON version extraction.
|
|
33
|
+
3. Run `uv run pytest` and `pre-commit run --all-files`.
|
|
34
|
+
4. Dry-run `code-aide update-versions` and confirm Antigravity reports the
|
|
35
|
+
manifest version.
|
|
@@ -37,6 +37,7 @@ from code_aide.config import (
|
|
|
37
37
|
load_bundled_tools,
|
|
38
38
|
load_versions_cache,
|
|
39
39
|
merge_cached_versions,
|
|
40
|
+
resolve_tool_names,
|
|
40
41
|
save_updated_versions,
|
|
41
42
|
)
|
|
42
43
|
|
|
@@ -65,6 +66,7 @@ def cmd_install(args: argparse.Namespace) -> None:
|
|
|
65
66
|
f"{', '.join(tools_to_install)}"
|
|
66
67
|
)
|
|
67
68
|
|
|
69
|
+
tools_to_install = resolve_tool_names(tools_to_install, TOOLS)
|
|
68
70
|
validate_tools(tools_to_install)
|
|
69
71
|
|
|
70
72
|
if not dryrun:
|
|
@@ -73,6 +75,7 @@ def cmd_install(args: argparse.Namespace) -> None:
|
|
|
73
75
|
)
|
|
74
76
|
|
|
75
77
|
installed = []
|
|
78
|
+
installed_bin_dirs = []
|
|
76
79
|
failed = []
|
|
77
80
|
|
|
78
81
|
for tool in tools_to_install:
|
|
@@ -82,8 +85,10 @@ def cmd_install(args: argparse.Namespace) -> None:
|
|
|
82
85
|
else:
|
|
83
86
|
info(f"=== Installing {tool} ===")
|
|
84
87
|
|
|
85
|
-
|
|
88
|
+
outcome = install_tool(tool, dryrun=dryrun)
|
|
89
|
+
if outcome:
|
|
86
90
|
installed.append(tool)
|
|
91
|
+
installed_bin_dirs.extend(outcome.bin_dirs)
|
|
87
92
|
else:
|
|
88
93
|
failed.append(tool)
|
|
89
94
|
|
|
@@ -120,7 +125,7 @@ def cmd_install(args: argparse.Namespace) -> None:
|
|
|
120
125
|
print(f" {tool_config['next_steps']}")
|
|
121
126
|
|
|
122
127
|
print()
|
|
123
|
-
check_path_directories(
|
|
128
|
+
check_path_directories(installed_bin_dirs)
|
|
124
129
|
success("All installations completed successfully!")
|
|
125
130
|
|
|
126
131
|
|
|
@@ -141,6 +146,7 @@ def cmd_upgrade(args: argparse.Namespace) -> None:
|
|
|
141
146
|
info("All installed tools are up to date")
|
|
142
147
|
return
|
|
143
148
|
|
|
149
|
+
tools_to_upgrade = resolve_tool_names(tools_to_upgrade, TOOLS)
|
|
144
150
|
validate_tools(tools_to_upgrade)
|
|
145
151
|
|
|
146
152
|
updated = []
|
|
@@ -201,6 +207,7 @@ def cmd_remove(args: argparse.Namespace) -> None:
|
|
|
201
207
|
tools_to_remove = list(TOOLS.keys())
|
|
202
208
|
info(f"No tools specified, removing all: {', '.join(tools_to_remove)}")
|
|
203
209
|
|
|
210
|
+
tools_to_remove = resolve_tool_names(tools_to_remove, TOOLS)
|
|
204
211
|
validate_tools(tools_to_remove)
|
|
205
212
|
|
|
206
213
|
removed = []
|
|
@@ -250,12 +257,12 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
|
|
|
250
257
|
config: Dict[str, Any] = {"tools": tools}
|
|
251
258
|
|
|
252
259
|
if args.tools:
|
|
253
|
-
|
|
260
|
+
tool_names = resolve_tool_names(args.tools, tools)
|
|
261
|
+
invalid = [tool for tool in tool_names if tool not in tools]
|
|
254
262
|
if invalid:
|
|
255
263
|
error(f"Unknown tool(s): {', '.join(invalid)}")
|
|
256
264
|
print(f"Available: {', '.join(tools.keys())}", file=sys.stderr)
|
|
257
265
|
sys.exit(1)
|
|
258
|
-
tool_names = args.tools
|
|
259
266
|
else:
|
|
260
267
|
tool_names = list(tools.keys())
|
|
261
268
|
|
|
@@ -118,6 +118,23 @@ def load_tools_config() -> dict:
|
|
|
118
118
|
return tools
|
|
119
119
|
|
|
120
120
|
|
|
121
|
+
def resolve_tool_names(
|
|
122
|
+
names: list[str], tools: Mapping[str, Dict[str, Any]]
|
|
123
|
+
) -> list[str]:
|
|
124
|
+
"""Resolve configured aliases to canonical tool names, preserving order."""
|
|
125
|
+
aliases = {
|
|
126
|
+
alias: tool_name
|
|
127
|
+
for tool_name, tool_config in tools.items()
|
|
128
|
+
for alias in tool_config.get("aliases", [])
|
|
129
|
+
}
|
|
130
|
+
resolved = []
|
|
131
|
+
for name in names:
|
|
132
|
+
canonical = aliases.get(name, name)
|
|
133
|
+
if canonical not in resolved:
|
|
134
|
+
resolved.append(canonical)
|
|
135
|
+
return resolved
|
|
136
|
+
|
|
137
|
+
|
|
121
138
|
def save_updated_versions(tools: Mapping[str, Dict[str, Any]]) -> None:
|
|
122
139
|
"""Save only dynamic version fields to the user's cache.
|
|
123
140
|
|
|
@@ -158,7 +175,10 @@ def versions_cache_is_fresh(tools: Mapping[str, Dict[str, Any]]) -> bool:
|
|
|
158
175
|
if not tool_config.get("latest_version"):
|
|
159
176
|
return False
|
|
160
177
|
elif install_type in (InstallType.SCRIPT, InstallType.DIRECT_DOWNLOAD):
|
|
161
|
-
|
|
178
|
+
has_version_source = tool_config.get("version_url") or tool_config.get(
|
|
179
|
+
"version_manifest_url_template"
|
|
180
|
+
)
|
|
181
|
+
if has_version_source and not tool_config.get("latest_version"):
|
|
162
182
|
return False
|
|
163
183
|
return True
|
|
164
184
|
|