code-aide 1.16.2__tar.gz → 1.18.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.16.2 → code_aide-1.18.0}/.github/workflows/ci.yml +2 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/.gitlab-ci.yml +1 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/.pre-commit-config.yaml +8 -0
- code_aide-1.18.0/Makefile +29 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/PKG-INFO +56 -30
- {code_aide-1.16.2 → code_aide-1.18.0}/README.md +55 -29
- code_aide-1.18.0/TODO.md +30 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/pyproject.toml +0 -3
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/__init__.py +1 -1
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/commands_actions.py +127 -5
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/commands_tools.py +49 -74
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/config.py +38 -12
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/console.py +10 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/constants.py +33 -16
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/data/tools.json +2 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/entry.py +37 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/install.py +66 -7
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/operation_handlers.py +10 -2
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/operations.py +80 -4
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/package_managers.py +1 -1
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/prereqs.py +4 -5
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/status.py +5 -2
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/versions.py +18 -9
- code_aide-1.18.0/tests/test_commands_actions.py +732 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_config.py +54 -2
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_console.py +16 -0
- code_aide-1.18.0/tests/test_constants.py +45 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_install.py +96 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_operations.py +73 -0
- code_aide-1.18.0/tests/test_package_info.py +57 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_prereqs.py +29 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_status.py +46 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_versions.py +82 -3
- code_aide-1.16.2/TODO.md +0 -78
- code_aide-1.16.2/tests/test_commands_actions.py +0 -345
- code_aide-1.16.2/tests/test_constants.py +0 -21
- {code_aide-1.16.2 → code_aide-1.18.0}/.github/workflows/publish.yml +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/.gitignore +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/AGENTS.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/CLAUDE.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/LICENSE +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/script-archive/README.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/script-archive/amp-install.sh +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/script-archive/antigravity-install.sh +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/script-archive/claude-install.sh +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/script-archive/cursor-install.sh +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/2026-05-03-qwen3.6-code-quality-analysis-original.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/2026-05-03-qwen3.6-code-quality-analysis.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/antigravity-cli-integration.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/auto-migrate-deprecated-installs.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/claude-native-installer-migration.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/missing-coding-llm-cli-tools.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/pre-commit-uv-setup.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/remove-bundled-version-baseline.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/specs/unify-upgrade-eligibility-with-shared-evaluator.md +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/__main__.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/detection.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/detection_types.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/install_types.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/package_info.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/src/code_aide/status_print.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_commands_tools.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_detection.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_entry.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_error_paths.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_install_types.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/tests/test_package_managers.py +0 -0
- {code_aide-1.16.2 → code_aide-1.18.0}/uv.lock +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# code-aide quality checks (uv-based)
|
|
2
|
+
|
|
3
|
+
.PHONY: build install test lint format format-check typecheck hooks check
|
|
4
|
+
|
|
5
|
+
build:
|
|
6
|
+
uv build
|
|
7
|
+
|
|
8
|
+
install:
|
|
9
|
+
uv sync
|
|
10
|
+
|
|
11
|
+
test:
|
|
12
|
+
uv run pytest -n4 -q
|
|
13
|
+
|
|
14
|
+
lint:
|
|
15
|
+
uv run ruff check .
|
|
16
|
+
|
|
17
|
+
format:
|
|
18
|
+
uv run black .
|
|
19
|
+
|
|
20
|
+
format-check:
|
|
21
|
+
uv run black --check .
|
|
22
|
+
|
|
23
|
+
typecheck:
|
|
24
|
+
uv run mypy
|
|
25
|
+
|
|
26
|
+
hooks:
|
|
27
|
+
pre-commit install
|
|
28
|
+
|
|
29
|
+
check: lint format-check typecheck
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: code-aide
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.18.0
|
|
4
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
|
|
@@ -49,6 +49,9 @@ pipx install code-aide
|
|
|
49
49
|
## Usage
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
+
# Show compact one-line-per-tool status (default when no command is given)
|
|
53
|
+
code-aide
|
|
54
|
+
|
|
52
55
|
# List available tools and their status
|
|
53
56
|
code-aide list
|
|
54
57
|
|
|
@@ -67,12 +70,24 @@ code-aide install
|
|
|
67
70
|
# Install with automatic prerequisite installation (Node.js, npm)
|
|
68
71
|
code-aide install -p
|
|
69
72
|
|
|
73
|
+
# Verify checksums and show what would be installed, without installing
|
|
74
|
+
code-aide install -n
|
|
75
|
+
|
|
70
76
|
# Upgrade installed tools (no args = only out-of-date tools)
|
|
71
77
|
code-aide upgrade [NAMES]
|
|
72
78
|
|
|
73
|
-
# Remove tools
|
|
79
|
+
# Remove tools (prompts before removing all managed tools)
|
|
74
80
|
code-aide remove [NAMES]
|
|
75
81
|
|
|
82
|
+
# Preview a removal without changing anything
|
|
83
|
+
code-aide remove -n
|
|
84
|
+
|
|
85
|
+
# Remove all managed tools without prompting
|
|
86
|
+
code-aide remove -y
|
|
87
|
+
|
|
88
|
+
# Remove stale version directories of direct-download tools
|
|
89
|
+
code-aide clean [NAMES]
|
|
90
|
+
|
|
76
91
|
# Check upstream for latest versions (dry-run)
|
|
77
92
|
code-aide update-versions -n
|
|
78
93
|
|
|
@@ -106,8 +121,8 @@ code-aide uses a two-layer version data model:
|
|
|
106
121
|
versions of code-aide.
|
|
107
122
|
|
|
108
123
|
2. **User's local version cache** (`~/.config/code-aide/versions.json`): Written
|
|
109
|
-
by `code-aide update-versions`. Provides latest versions, dates,
|
|
110
|
-
SHA256 checksums.
|
|
124
|
+
by `code-aide update-versions`. Provides latest versions, dates, updated
|
|
125
|
+
SHA256 checksums, and recorded tarball checksums for direct_download tools.
|
|
111
126
|
|
|
112
127
|
Run `code-aide update-versions` to get the latest version data without waiting
|
|
113
128
|
for a new code-aide release.
|
|
@@ -118,32 +133,34 @@ Each entry in `tools.json` describes one managed tool. Required fields are
|
|
|
118
133
|
`name`, `command`, and `install_type`; the others are optional and only
|
|
119
134
|
consulted when the relevant install method or platform applies.
|
|
120
135
|
|
|
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
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
139
|
-
| `
|
|
140
|
-
| `
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
136
|
+
| Field | Required | Notes |
|
|
137
|
+
|:--------------------------------|:---------|:----------------------------------------------------------------------------------------------------------------|
|
|
138
|
+
| `name` | Yes | Display name for status output |
|
|
139
|
+
| `command` | Yes | Binary name (looked up in `PATH`) |
|
|
140
|
+
| `aliases` | No | Alternate names accepted by commands and resolved to the canonical tool key |
|
|
141
|
+
| `install_type` | Yes | One of `npm`, `script`, `direct_download`, `pkg` |
|
|
142
|
+
| `version_args` | No | List of arguments passed to the binary to print its version (default: `["--version"]`) |
|
|
143
|
+
| `version_url` | No | URL queried by `update-versions` to discover the latest upstream version |
|
|
144
|
+
| `version_manifest_url_template` | No | JSON manifest URL template with `{platform}`; reads its `version` field |
|
|
145
|
+
| `version_extract_pattern` | No | Regex applied to the install script to extract the version before generic heuristics |
|
|
146
|
+
| `latest_version` | Cache | Last known upstream version (filled by `update-versions`) |
|
|
147
|
+
| `latest_date` | Cache | Release date for `latest_version` |
|
|
148
|
+
| `prerequisites` | No | List of required external commands (e.g. `["npm"]`) |
|
|
149
|
+
| `min_node_version` | No | Minimum major Node.js version required |
|
|
150
|
+
| `npm_package` | npm | npm package name (e.g. `@anthropic-ai/claude-code`) |
|
|
151
|
+
| `install_url` | script | URL of the install script that will be downloaded and piped to `bash` |
|
|
152
|
+
| `install_sha256` | script | SHA-256 of the install script body — required for verified installs |
|
|
153
|
+
| `download_sha256` | Cache | SHA-256 of the downloaded tarball for direct_download tools; recorded by `update-versions`, verified on install |
|
|
154
|
+
| `install_script_path_prepend` | script | Extra directories prepended to `PATH` when the install script runs (e.g. `["~/.local/bin"]`) |
|
|
155
|
+
| `download_url_template` | direct | URL template with `{version}`, `{os}`, `{arch}` placeholders |
|
|
156
|
+
| `install_dir` | direct | Directory to extract into; supports `{version}` |
|
|
157
|
+
| `bin_dir` | direct | Directory where symlinks for `command` are created (e.g. `~/.local/bin`) |
|
|
158
|
+
| `symlinks` | direct | Map of `link_name` → relative path inside `install_dir` to symlink into `bin_dir` |
|
|
159
|
+
| `freebsd_port` | FreeBSD | FreeBSD ports/pkg name (used when running on FreeBSD) |
|
|
160
|
+
| `freebsd_pkg_repo` | FreeBSD | Optional non-default pkg repository name (passed via `pkg install -r <repo>`) |
|
|
161
|
+
| `next_steps` | No | Free-form text printed after a successful install |
|
|
162
|
+
| `docs_url` | No | Documentation URL printed after install |
|
|
163
|
+
| `self_updates` | No | Tool updates itself when run; excludes it from managed upgrade actions |
|
|
147
164
|
|
|
148
165
|
## Features
|
|
149
166
|
|
|
@@ -155,6 +172,15 @@ consulted when the relevant install method or platform applies.
|
|
|
155
172
|
- PATH configuration validation and warnings
|
|
156
173
|
- Supports Linux and macOS
|
|
157
174
|
|
|
175
|
+
## Configuration
|
|
176
|
+
|
|
177
|
+
- Tool definitions are bundled at `src/code_aide/data/tools.json`.
|
|
178
|
+
- The version cache lives at `~/.config/code-aide/versions.json` by default; set
|
|
179
|
+
`XDG_CONFIG_HOME` to relocate the `code-aide` config directory.
|
|
180
|
+
- Color output honors `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR_FORCE`, `CLICOLOR=0`,
|
|
181
|
+
and `TERM=dumb`, in that priority order; color is disabled when stdout is not
|
|
182
|
+
a terminal.
|
|
183
|
+
|
|
158
184
|
## Requirements
|
|
159
185
|
|
|
160
186
|
- Python 3.11+
|
|
@@ -22,6 +22,9 @@ pipx install code-aide
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
+
# Show compact one-line-per-tool status (default when no command is given)
|
|
26
|
+
code-aide
|
|
27
|
+
|
|
25
28
|
# List available tools and their status
|
|
26
29
|
code-aide list
|
|
27
30
|
|
|
@@ -40,12 +43,24 @@ code-aide install
|
|
|
40
43
|
# Install with automatic prerequisite installation (Node.js, npm)
|
|
41
44
|
code-aide install -p
|
|
42
45
|
|
|
46
|
+
# Verify checksums and show what would be installed, without installing
|
|
47
|
+
code-aide install -n
|
|
48
|
+
|
|
43
49
|
# Upgrade installed tools (no args = only out-of-date tools)
|
|
44
50
|
code-aide upgrade [NAMES]
|
|
45
51
|
|
|
46
|
-
# Remove tools
|
|
52
|
+
# Remove tools (prompts before removing all managed tools)
|
|
47
53
|
code-aide remove [NAMES]
|
|
48
54
|
|
|
55
|
+
# Preview a removal without changing anything
|
|
56
|
+
code-aide remove -n
|
|
57
|
+
|
|
58
|
+
# Remove all managed tools without prompting
|
|
59
|
+
code-aide remove -y
|
|
60
|
+
|
|
61
|
+
# Remove stale version directories of direct-download tools
|
|
62
|
+
code-aide clean [NAMES]
|
|
63
|
+
|
|
49
64
|
# Check upstream for latest versions (dry-run)
|
|
50
65
|
code-aide update-versions -n
|
|
51
66
|
|
|
@@ -79,8 +94,8 @@ code-aide uses a two-layer version data model:
|
|
|
79
94
|
versions of code-aide.
|
|
80
95
|
|
|
81
96
|
2. **User's local version cache** (`~/.config/code-aide/versions.json`): Written
|
|
82
|
-
by `code-aide update-versions`. Provides latest versions, dates,
|
|
83
|
-
SHA256 checksums.
|
|
97
|
+
by `code-aide update-versions`. Provides latest versions, dates, updated
|
|
98
|
+
SHA256 checksums, and recorded tarball checksums for direct_download tools.
|
|
84
99
|
|
|
85
100
|
Run `code-aide update-versions` to get the latest version data without waiting
|
|
86
101
|
for a new code-aide release.
|
|
@@ -91,32 +106,34 @@ Each entry in `tools.json` describes one managed tool. Required fields are
|
|
|
91
106
|
`name`, `command`, and `install_type`; the others are optional and only
|
|
92
107
|
consulted when the relevant install method or platform applies.
|
|
93
108
|
|
|
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
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
119
|
-
| `
|
|
109
|
+
| Field | Required | Notes |
|
|
110
|
+
|:--------------------------------|:---------|:----------------------------------------------------------------------------------------------------------------|
|
|
111
|
+
| `name` | Yes | Display name for status output |
|
|
112
|
+
| `command` | Yes | Binary name (looked up in `PATH`) |
|
|
113
|
+
| `aliases` | No | Alternate names accepted by commands and resolved to the canonical tool key |
|
|
114
|
+
| `install_type` | Yes | One of `npm`, `script`, `direct_download`, `pkg` |
|
|
115
|
+
| `version_args` | No | List of arguments passed to the binary to print its version (default: `["--version"]`) |
|
|
116
|
+
| `version_url` | No | URL queried by `update-versions` to discover the latest upstream version |
|
|
117
|
+
| `version_manifest_url_template` | No | JSON manifest URL template with `{platform}`; reads its `version` field |
|
|
118
|
+
| `version_extract_pattern` | No | Regex applied to the install script to extract the version before generic heuristics |
|
|
119
|
+
| `latest_version` | Cache | Last known upstream version (filled by `update-versions`) |
|
|
120
|
+
| `latest_date` | Cache | Release date for `latest_version` |
|
|
121
|
+
| `prerequisites` | No | List of required external commands (e.g. `["npm"]`) |
|
|
122
|
+
| `min_node_version` | No | Minimum major Node.js version required |
|
|
123
|
+
| `npm_package` | npm | npm package name (e.g. `@anthropic-ai/claude-code`) |
|
|
124
|
+
| `install_url` | script | URL of the install script that will be downloaded and piped to `bash` |
|
|
125
|
+
| `install_sha256` | script | SHA-256 of the install script body — required for verified installs |
|
|
126
|
+
| `download_sha256` | Cache | SHA-256 of the downloaded tarball for direct_download tools; recorded by `update-versions`, verified on install |
|
|
127
|
+
| `install_script_path_prepend` | script | Extra directories prepended to `PATH` when the install script runs (e.g. `["~/.local/bin"]`) |
|
|
128
|
+
| `download_url_template` | direct | URL template with `{version}`, `{os}`, `{arch}` placeholders |
|
|
129
|
+
| `install_dir` | direct | Directory to extract into; supports `{version}` |
|
|
130
|
+
| `bin_dir` | direct | Directory where symlinks for `command` are created (e.g. `~/.local/bin`) |
|
|
131
|
+
| `symlinks` | direct | Map of `link_name` → relative path inside `install_dir` to symlink into `bin_dir` |
|
|
132
|
+
| `freebsd_port` | FreeBSD | FreeBSD ports/pkg name (used when running on FreeBSD) |
|
|
133
|
+
| `freebsd_pkg_repo` | FreeBSD | Optional non-default pkg repository name (passed via `pkg install -r <repo>`) |
|
|
134
|
+
| `next_steps` | No | Free-form text printed after a successful install |
|
|
135
|
+
| `docs_url` | No | Documentation URL printed after install |
|
|
136
|
+
| `self_updates` | No | Tool updates itself when run; excludes it from managed upgrade actions |
|
|
120
137
|
|
|
121
138
|
## Features
|
|
122
139
|
|
|
@@ -128,6 +145,15 @@ consulted when the relevant install method or platform applies.
|
|
|
128
145
|
- PATH configuration validation and warnings
|
|
129
146
|
- Supports Linux and macOS
|
|
130
147
|
|
|
148
|
+
## Configuration
|
|
149
|
+
|
|
150
|
+
- Tool definitions are bundled at `src/code_aide/data/tools.json`.
|
|
151
|
+
- The version cache lives at `~/.config/code-aide/versions.json` by default; set
|
|
152
|
+
`XDG_CONFIG_HOME` to relocate the `code-aide` config directory.
|
|
153
|
+
- Color output honors `NO_COLOR`, `FORCE_COLOR`, `CLICOLOR_FORCE`, `CLICOLOR=0`,
|
|
154
|
+
and `TERM=dumb`, in that priority order; color is disabled when stdout is not
|
|
155
|
+
a terminal.
|
|
156
|
+
|
|
131
157
|
## Requirements
|
|
132
158
|
|
|
133
159
|
- Python 3.11+
|
code_aide-1.18.0/TODO.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# TODO
|
|
2
|
+
|
|
3
|
+
Keep the project focused on managing AI coding CLI tools (install, upgrade,
|
|
4
|
+
remove, status, and version metadata).
|
|
5
|
+
|
|
6
|
+
All items below are deferred; none are scheduled.
|
|
7
|
+
|
|
8
|
+
| # | Item | Risk | Effort | Notes |
|
|
9
|
+
|:---|:-------------------------------|:-----|:-------|:-------------------------------------------------------|
|
|
10
|
+
| 1 | `doctor` command | Low | Med | Health checks exist but are scattered |
|
|
11
|
+
| 2 | Cross-distro package detection | Med | High | Only Gentoo supported; other Linux distros get nothing |
|
|
12
|
+
| 3 | Split large modules | Low | High | Refactoring only; no behavior change |
|
|
13
|
+
| 4 | Tests for edge cases | Med | Med | PATH oddities, more version parsing corners |
|
|
14
|
+
|
|
15
|
+
## CLI and Automation UX
|
|
16
|
+
|
|
17
|
+
- [ ] Add a focused `doctor` command for environment checks (PATH,
|
|
18
|
+
prerequisites, command health).
|
|
19
|
+
|
|
20
|
+
## Platform and Package Detection
|
|
21
|
+
|
|
22
|
+
- [ ] Broaden system package metadata detection beyond Gentoo-specific tooling
|
|
23
|
+
where practical; note that non-Gentoo system installs currently report "up to
|
|
24
|
+
date" because no available version is detectable.
|
|
25
|
+
|
|
26
|
+
## Maintainability and Tests
|
|
27
|
+
|
|
28
|
+
- [ ] Split larger modules into smaller focused files where practical
|
|
29
|
+
(`install.py`, `commands_actions.py`, `versions.py`).
|
|
30
|
+
- [ ] Add tests for more prerequisite edge cases and PATH oddities.
|
|
@@ -6,7 +6,7 @@ from typing import Any, Dict, List
|
|
|
6
6
|
|
|
7
7
|
from code_aide.constants import TOOLS
|
|
8
8
|
from code_aide.detection import detect_install_method, get_brew_package_info
|
|
9
|
-
from code_aide.install import install_tool
|
|
9
|
+
from code_aide.install import fetch_download_checksum, install_tool
|
|
10
10
|
from code_aide.install_types import (
|
|
11
11
|
InstallMethod,
|
|
12
12
|
InstallType,
|
|
@@ -16,6 +16,7 @@ from code_aide.install_types import (
|
|
|
16
16
|
from code_aide.console import error, info, success, warning
|
|
17
17
|
from code_aide.operations import (
|
|
18
18
|
UpgradeResult,
|
|
19
|
+
clean_tool_versions,
|
|
19
20
|
remove_tool,
|
|
20
21
|
upgrade_tool,
|
|
21
22
|
validate_tools,
|
|
@@ -34,6 +35,7 @@ from code_aide.versions import (
|
|
|
34
35
|
print_check_results_table,
|
|
35
36
|
)
|
|
36
37
|
from code_aide.config import (
|
|
38
|
+
ensure_versions_cache,
|
|
37
39
|
load_bundled_tools,
|
|
38
40
|
load_versions_cache,
|
|
39
41
|
merge_cached_versions,
|
|
@@ -45,6 +47,7 @@ from code_aide.config import (
|
|
|
45
47
|
def cmd_install(args: argparse.Namespace) -> None:
|
|
46
48
|
"""Handle install command."""
|
|
47
49
|
dryrun = getattr(args, "dryrun", False)
|
|
50
|
+
force = getattr(args, "force", False)
|
|
48
51
|
|
|
49
52
|
if args.tools:
|
|
50
53
|
tools_to_install = args.tools
|
|
@@ -75,7 +78,7 @@ def cmd_install(args: argparse.Namespace) -> None:
|
|
|
75
78
|
)
|
|
76
79
|
|
|
77
80
|
installed = []
|
|
78
|
-
installed_bin_dirs = []
|
|
81
|
+
installed_bin_dirs: List[str] = []
|
|
79
82
|
failed = []
|
|
80
83
|
|
|
81
84
|
for tool in tools_to_install:
|
|
@@ -85,7 +88,7 @@ def cmd_install(args: argparse.Namespace) -> None:
|
|
|
85
88
|
else:
|
|
86
89
|
info(f"=== Installing {tool} ===")
|
|
87
90
|
|
|
88
|
-
outcome = install_tool(tool, dryrun=dryrun)
|
|
91
|
+
outcome = install_tool(tool, dryrun=dryrun, force=force)
|
|
89
92
|
if outcome:
|
|
90
93
|
installed.append(tool)
|
|
91
94
|
installed_bin_dirs.extend(outcome.bin_dirs)
|
|
@@ -136,6 +139,9 @@ def cmd_upgrade(args: argparse.Namespace) -> None:
|
|
|
136
139
|
info(f"Upgrading specified tools: {', '.join(tools_to_upgrade)}")
|
|
137
140
|
else:
|
|
138
141
|
tools_to_upgrade = []
|
|
142
|
+
# Default selection is driven by latest_version, so refresh stale
|
|
143
|
+
# cache data first; named upgrades below skip this.
|
|
144
|
+
ensure_versions_cache(TOOLS)
|
|
139
145
|
for name, config in TOOLS.items():
|
|
140
146
|
assessment = ToolUpgradeEvaluator(name, config).evaluate()
|
|
141
147
|
if assessment.actionable_by_upgrade and name not in tools_to_upgrade:
|
|
@@ -198,14 +204,37 @@ def cmd_upgrade(args: argparse.Namespace) -> None:
|
|
|
198
204
|
)
|
|
199
205
|
|
|
200
206
|
|
|
207
|
+
def _confirm_remove_all(tools: List[str]) -> bool:
|
|
208
|
+
"""Prompt before removing every managed tool."""
|
|
209
|
+
print(f"This will remove {len(tools)} managed tools: {', '.join(tools)}")
|
|
210
|
+
try:
|
|
211
|
+
answer = input("Remove all of them? [y/N] ").strip().lower()
|
|
212
|
+
except (EOFError, KeyboardInterrupt):
|
|
213
|
+
print()
|
|
214
|
+
return False
|
|
215
|
+
return answer in ("y", "yes")
|
|
216
|
+
|
|
217
|
+
|
|
201
218
|
def cmd_remove(args: argparse.Namespace) -> None:
|
|
202
219
|
"""Handle remove command."""
|
|
220
|
+
dryrun = getattr(args, "dryrun", False)
|
|
221
|
+
assume_yes = getattr(args, "yes", False)
|
|
222
|
+
|
|
203
223
|
if args.tools:
|
|
204
224
|
tools_to_remove = args.tools
|
|
205
225
|
info(f"Removing specified tools: {', '.join(tools_to_remove)}")
|
|
206
226
|
else:
|
|
207
227
|
tools_to_remove = list(TOOLS.keys())
|
|
208
|
-
|
|
228
|
+
if dryrun:
|
|
229
|
+
info(
|
|
230
|
+
"[DRYRUN] Would remove all managed tools: "
|
|
231
|
+
f"{', '.join(tools_to_remove)}"
|
|
232
|
+
)
|
|
233
|
+
else:
|
|
234
|
+
info(f"No tools specified, removing all: {', '.join(tools_to_remove)}")
|
|
235
|
+
if not assume_yes and not _confirm_remove_all(tools_to_remove):
|
|
236
|
+
print("Aborted.")
|
|
237
|
+
return
|
|
209
238
|
|
|
210
239
|
tools_to_remove = resolve_tool_names(tools_to_remove, TOOLS)
|
|
211
240
|
validate_tools(tools_to_remove)
|
|
@@ -216,6 +245,14 @@ def cmd_remove(args: argparse.Namespace) -> None:
|
|
|
216
245
|
|
|
217
246
|
for tool in tools_to_remove:
|
|
218
247
|
print()
|
|
248
|
+
if dryrun:
|
|
249
|
+
info(f"=== Checking {tool} ===")
|
|
250
|
+
if is_tool_installed(tool):
|
|
251
|
+
removed.append(tool)
|
|
252
|
+
else:
|
|
253
|
+
skipped.append(tool)
|
|
254
|
+
continue
|
|
255
|
+
|
|
219
256
|
info(f"=== Removing {tool} ===")
|
|
220
257
|
|
|
221
258
|
if not is_tool_installed(tool):
|
|
@@ -229,8 +266,19 @@ def cmd_remove(args: argparse.Namespace) -> None:
|
|
|
229
266
|
|
|
230
267
|
print()
|
|
231
268
|
print("=" * 42)
|
|
232
|
-
|
|
269
|
+
if dryrun:
|
|
270
|
+
info("Removal Summary (dry run)")
|
|
271
|
+
else:
|
|
272
|
+
info("Removal Summary")
|
|
233
273
|
print("=" * 42)
|
|
274
|
+
if dryrun:
|
|
275
|
+
if removed:
|
|
276
|
+
success(f"Would remove: {', '.join(removed)}")
|
|
277
|
+
if skipped:
|
|
278
|
+
warning(f"Not installed (skipped): {', '.join(skipped)}")
|
|
279
|
+
print()
|
|
280
|
+
success("Dry run completed without removing anything!")
|
|
281
|
+
return
|
|
234
282
|
|
|
235
283
|
if removed:
|
|
236
284
|
success(f"Successfully removed: {', '.join(removed)}")
|
|
@@ -248,6 +296,56 @@ def cmd_remove(args: argparse.Namespace) -> None:
|
|
|
248
296
|
info("No tools were removed (all were not installed)")
|
|
249
297
|
|
|
250
298
|
|
|
299
|
+
def cmd_clean(args: argparse.Namespace) -> None:
|
|
300
|
+
"""Handle clean command: remove stale direct-download version dirs."""
|
|
301
|
+
dryrun = getattr(args, "dryrun", False)
|
|
302
|
+
|
|
303
|
+
if args.tools:
|
|
304
|
+
tools_to_clean = resolve_tool_names(args.tools, TOOLS)
|
|
305
|
+
else:
|
|
306
|
+
tools_to_clean = [
|
|
307
|
+
name
|
|
308
|
+
for name, config in TOOLS.items()
|
|
309
|
+
if parse_install_type(config.get("install_type"))
|
|
310
|
+
== InstallType.DIRECT_DOWNLOAD
|
|
311
|
+
]
|
|
312
|
+
if not tools_to_clean:
|
|
313
|
+
info("No direct-download tools with cleanable versions")
|
|
314
|
+
return
|
|
315
|
+
info(
|
|
316
|
+
"No tools specified, cleaning direct-download tools: "
|
|
317
|
+
f"{', '.join(tools_to_clean)}"
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
validate_tools(tools_to_clean)
|
|
321
|
+
|
|
322
|
+
cleaned: Dict[str, List[str]] = {}
|
|
323
|
+
skipped = []
|
|
324
|
+
for tool in tools_to_clean:
|
|
325
|
+
print()
|
|
326
|
+
info(f"=== {'Checking' if dryrun else 'Cleaning'} {tool} ===")
|
|
327
|
+
removed = clean_tool_versions(tool, dryrun=dryrun)
|
|
328
|
+
if removed is None:
|
|
329
|
+
skipped.append(tool)
|
|
330
|
+
elif removed:
|
|
331
|
+
cleaned[tool] = removed
|
|
332
|
+
|
|
333
|
+
print()
|
|
334
|
+
print("=" * 42)
|
|
335
|
+
info("Cleanup Summary" + (" (dry run)" if dryrun else ""))
|
|
336
|
+
print("=" * 42)
|
|
337
|
+
|
|
338
|
+
if cleaned:
|
|
339
|
+
total = sum(len(paths) for paths in cleaned.values())
|
|
340
|
+
details = ", ".join(f"{tool} ({len(paths)})" for tool, paths in cleaned.items())
|
|
341
|
+
noun = "Would remove" if dryrun else "Removed"
|
|
342
|
+
success(f"{noun} {total} stale version directories: {details}")
|
|
343
|
+
if skipped:
|
|
344
|
+
info(f"Not cleanable (no versioned install layout): {', '.join(skipped)}")
|
|
345
|
+
if not cleaned:
|
|
346
|
+
success("Nothing to clean!")
|
|
347
|
+
|
|
348
|
+
|
|
251
349
|
def cmd_update_versions(args: argparse.Namespace) -> None:
|
|
252
350
|
"""Handle update-versions command: check upstream for latest tool versions."""
|
|
253
351
|
bundled = load_bundled_tools()
|
|
@@ -326,6 +424,30 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
|
|
|
326
424
|
tool_entry["latest_version"] = normalized
|
|
327
425
|
version_info_changed = True
|
|
328
426
|
|
|
427
|
+
# Record the tarball checksum for direct-download tools so later
|
|
428
|
+
# installs can verify integrity against it.
|
|
429
|
+
if not args.dryrun:
|
|
430
|
+
for tool_name in tool_names:
|
|
431
|
+
tool_entry = config["tools"][tool_name]
|
|
432
|
+
if (
|
|
433
|
+
parse_install_type(tool_entry.get("install_type"))
|
|
434
|
+
!= InstallType.DIRECT_DOWNLOAD
|
|
435
|
+
):
|
|
436
|
+
continue
|
|
437
|
+
if "download_url_template" not in tool_entry:
|
|
438
|
+
continue
|
|
439
|
+
if not tool_entry.get("latest_version"):
|
|
440
|
+
continue
|
|
441
|
+
checksum = fetch_download_checksum(tool_entry)
|
|
442
|
+
if not checksum:
|
|
443
|
+
continue
|
|
444
|
+
if tool_entry.get("download_sha256") != checksum:
|
|
445
|
+
tool_entry["download_sha256"] = checksum
|
|
446
|
+
version_info_changed = True
|
|
447
|
+
print(f"Recorded download SHA256 for {tool_name}.")
|
|
448
|
+
else:
|
|
449
|
+
print(f"Download SHA256 for {tool_name} is unchanged.")
|
|
450
|
+
|
|
329
451
|
def _save(tools: dict) -> str:
|
|
330
452
|
"""Save versions to user cache. Returns description."""
|
|
331
453
|
save_updated_versions(tools)
|