code-aide 1.5.0__tar.gz → 1.7.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.5.0 → code_aide-1.7.0}/AGENTS.md +10 -5
- {code_aide-1.5.0 → code_aide-1.7.0}/PKG-INFO +18 -28
- {code_aide-1.5.0 → code_aide-1.7.0}/README.md +17 -27
- {code_aide-1.5.0 → code_aide-1.7.0}/TODO.md +19 -18
- code_aide-1.7.0/specs/auto-migrate-deprecated-installs.md +128 -0
- code_aide-1.7.0/specs/remove-bundled-version-baseline.md +77 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/__init__.py +1 -1
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/commands_actions.py +7 -7
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/commands_tools.py +14 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/config.py +4 -30
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/data/tools.json +8 -24
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/detection.py +60 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/entry.py +0 -6
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/install.py +12 -2
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/operations.py +41 -2
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_commands_actions.py +0 -61
- code_aide-1.7.0/tests/test_commands_tools.py +163 -0
- code_aide-1.7.0/tests/test_detection.py +286 -0
- code_aide-1.7.0/tests/test_operations.py +309 -0
- code_aide-1.5.0/tests/test_commands_tools.py +0 -78
- code_aide-1.5.0/tests/test_detection.py +0 -116
- code_aide-1.5.0/tests/test_operations.py +0 -159
- {code_aide-1.5.0 → code_aide-1.7.0}/.github/workflows/ci.yml +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/.github/workflows/publish.yml +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/.gitignore +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/.gitlab-ci.yml +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/.pre-commit-config.yaml +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/CLAUDE.md +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/LICENSE +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/pyproject.toml +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/specs/claude-native-installer-migration.md +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/specs/missing-coding-llm-cli-tools.md +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/specs/pre-commit-uv-setup.md +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/__main__.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/console.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/constants.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/prereqs.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/status.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/src/code_aide/versions.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_config.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_console.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_constants.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_install.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_status.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/tests/test_versions.py +0 -0
- {code_aide-1.5.0 → code_aide-1.7.0}/uv.lock +0 -0
|
@@ -3,15 +3,20 @@
|
|
|
3
3
|
## Key Design Decisions
|
|
4
4
|
|
|
5
5
|
- No external dependencies - stdlib only
|
|
6
|
-
-
|
|
6
|
+
- Two-layer version data: bundled definitions (with SHA256 checksums),
|
|
7
7
|
user's local cache (~/.config/code-aide/versions.json)
|
|
8
8
|
- All tests should pass before committing
|
|
9
|
-
- pre-commit runs black and ruff on commit; run `
|
|
10
|
-
|
|
11
|
-
- When changing pyproject.toml dependencies, run `uv lock` and commit
|
|
9
|
+
- pre-commit runs black and ruff on commit; run `black` to format and then
|
|
10
|
+
`pre-commit run --all-files` to check before committing
|
|
11
|
+
- When changing pyproject.toml dependencies, run `uv lock` and commit
|
|
12
|
+
uv.lock
|
|
12
13
|
- Write useful commit messages: start subjects with past-tense action verbs
|
|
13
14
|
(`Added`, `Changed`, `Fixed`, `Removed`), keep them user-facing, and keep
|
|
14
15
|
commits focused.
|
|
15
16
|
- Python 3.11+ compatible
|
|
16
17
|
- Keep files under 300 lines where practical
|
|
17
|
-
- Run `format-markdown` on markdown files before commits (if it is
|
|
18
|
+
- Run `format-markdown` on markdown files before commits (if it is
|
|
19
|
+
available)
|
|
20
|
+
- When pushing tags, always push them explicitly with `git push <remote>
|
|
21
|
+
<tag>` rather than relying on `--follow-tags`, which silently skips tags
|
|
22
|
+
when the branch commits are already on the remote
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-aide
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: Manage AI coding CLI tools (Claude, 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
|
|
@@ -74,9 +74,6 @@ code-aide update-versions -n
|
|
|
74
74
|
|
|
75
75
|
# Update version cache
|
|
76
76
|
code-aide update-versions -y
|
|
77
|
-
|
|
78
|
-
# Update bundled version baseline (developer use, before releases)
|
|
79
|
-
code-aide update-versions -b -y
|
|
80
77
|
```
|
|
81
78
|
|
|
82
79
|
## Supported Tools
|
|
@@ -94,22 +91,18 @@ code-aide update-versions -b -y
|
|
|
94
91
|
|
|
95
92
|
## How Version Data Works
|
|
96
93
|
|
|
97
|
-
code-aide uses a
|
|
98
|
-
|
|
99
|
-
1. **Tool definitions** (bundled with the package): Install methods, URLs,
|
|
100
|
-
npm packages, version args. Updated by releasing new versions of
|
|
101
|
-
code-aide.
|
|
94
|
+
code-aide uses a two-layer version data model:
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
1. **Bundled tool definitions** (in `data/tools.json`): Install methods,
|
|
97
|
+
URLs, npm packages, version args, and SHA256 checksums. Updated by
|
|
98
|
+
releasing new versions of code-aide.
|
|
106
99
|
|
|
107
|
-
|
|
108
|
-
Written by `code-aide update-versions`.
|
|
109
|
-
|
|
100
|
+
2. **User's local version cache** (`~/.config/code-aide/versions.json`):
|
|
101
|
+
Written by `code-aide update-versions`. Provides latest versions, dates,
|
|
102
|
+
and updated SHA256 checksums.
|
|
110
103
|
|
|
111
|
-
Run `code-aide update-versions` to get
|
|
112
|
-
for a new code-aide release.
|
|
104
|
+
Run `code-aide update-versions` to get the latest version data without
|
|
105
|
+
waiting for a new code-aide release.
|
|
113
106
|
|
|
114
107
|
## Features
|
|
115
108
|
|
|
@@ -147,29 +140,26 @@ uv run pytest tests/test_install.py::TestDetectOsArch -v
|
|
|
147
140
|
|
|
148
141
|
`publish.yml` publishes to PyPI when a Git tag matching `v*` is pushed.
|
|
149
142
|
|
|
150
|
-
1. Update the
|
|
151
|
-
- `code-aide update-versions -b -y`
|
|
152
|
-
- `git add src/code_aide/data/tools.json`
|
|
153
|
-
- `git commit -m "Updated bundled version data"`
|
|
154
|
-
2. Update the version string in `src/code_aide/__init__.py` (`__version__`).
|
|
143
|
+
1. Update the version string in `src/code_aide/__init__.py` (`__version__`).
|
|
155
144
|
`pyproject.toml` reads it automatically via Hatchling.
|
|
156
|
-
|
|
145
|
+
2. Run checks:
|
|
157
146
|
- `uv run pytest tests/ -v`
|
|
158
147
|
- `uv build`
|
|
159
|
-
|
|
148
|
+
3. Commit the release version bump:
|
|
160
149
|
- `git add src/code_aide/__init__.py`
|
|
161
150
|
- `git commit -m "Bumped version to X.Y.Z"`
|
|
162
|
-
|
|
151
|
+
4. Write useful commit messages before tagging:
|
|
163
152
|
- Start subject lines with an action verb in past tense (`Added`,
|
|
164
153
|
`Changed`, `Fixed`, `Removed`).
|
|
165
154
|
- Keep subjects user-facing so auto-generated release notes are
|
|
166
155
|
meaningful.
|
|
167
156
|
- Group related changes into focused commits instead of one broad commit.
|
|
168
157
|
- Example: `Fixed timeout handling in status command`
|
|
169
|
-
|
|
158
|
+
5. Tag and push:
|
|
170
159
|
- `git tag vX.Y.Z`
|
|
171
|
-
- `git push origin main
|
|
172
|
-
|
|
160
|
+
- `git push origin main`
|
|
161
|
+
- `git push origin vX.Y.Z`
|
|
162
|
+
6. Confirm GitHub Actions:
|
|
173
163
|
- CI should pass.
|
|
174
164
|
- Publish workflow should upload to PyPI and create GitHub Release notes.
|
|
175
165
|
- Release notes should include generated notes plus a commit summary from
|
|
@@ -48,9 +48,6 @@ code-aide update-versions -n
|
|
|
48
48
|
|
|
49
49
|
# Update version cache
|
|
50
50
|
code-aide update-versions -y
|
|
51
|
-
|
|
52
|
-
# Update bundled version baseline (developer use, before releases)
|
|
53
|
-
code-aide update-versions -b -y
|
|
54
51
|
```
|
|
55
52
|
|
|
56
53
|
## Supported Tools
|
|
@@ -68,22 +65,18 @@ code-aide update-versions -b -y
|
|
|
68
65
|
|
|
69
66
|
## How Version Data Works
|
|
70
67
|
|
|
71
|
-
code-aide uses a
|
|
72
|
-
|
|
73
|
-
1. **Tool definitions** (bundled with the package): Install methods, URLs,
|
|
74
|
-
npm packages, version args. Updated by releasing new versions of
|
|
75
|
-
code-aide.
|
|
68
|
+
code-aide uses a two-layer version data model:
|
|
76
69
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
70
|
+
1. **Bundled tool definitions** (in `data/tools.json`): Install methods,
|
|
71
|
+
URLs, npm packages, version args, and SHA256 checksums. Updated by
|
|
72
|
+
releasing new versions of code-aide.
|
|
80
73
|
|
|
81
|
-
|
|
82
|
-
Written by `code-aide update-versions`.
|
|
83
|
-
|
|
74
|
+
2. **User's local version cache** (`~/.config/code-aide/versions.json`):
|
|
75
|
+
Written by `code-aide update-versions`. Provides latest versions, dates,
|
|
76
|
+
and updated SHA256 checksums.
|
|
84
77
|
|
|
85
|
-
Run `code-aide update-versions` to get
|
|
86
|
-
for a new code-aide release.
|
|
78
|
+
Run `code-aide update-versions` to get the latest version data without
|
|
79
|
+
waiting for a new code-aide release.
|
|
87
80
|
|
|
88
81
|
## Features
|
|
89
82
|
|
|
@@ -121,29 +114,26 @@ uv run pytest tests/test_install.py::TestDetectOsArch -v
|
|
|
121
114
|
|
|
122
115
|
`publish.yml` publishes to PyPI when a Git tag matching `v*` is pushed.
|
|
123
116
|
|
|
124
|
-
1. Update the
|
|
125
|
-
- `code-aide update-versions -b -y`
|
|
126
|
-
- `git add src/code_aide/data/tools.json`
|
|
127
|
-
- `git commit -m "Updated bundled version data"`
|
|
128
|
-
2. Update the version string in `src/code_aide/__init__.py` (`__version__`).
|
|
117
|
+
1. Update the version string in `src/code_aide/__init__.py` (`__version__`).
|
|
129
118
|
`pyproject.toml` reads it automatically via Hatchling.
|
|
130
|
-
|
|
119
|
+
2. Run checks:
|
|
131
120
|
- `uv run pytest tests/ -v`
|
|
132
121
|
- `uv build`
|
|
133
|
-
|
|
122
|
+
3. Commit the release version bump:
|
|
134
123
|
- `git add src/code_aide/__init__.py`
|
|
135
124
|
- `git commit -m "Bumped version to X.Y.Z"`
|
|
136
|
-
|
|
125
|
+
4. Write useful commit messages before tagging:
|
|
137
126
|
- Start subject lines with an action verb in past tense (`Added`,
|
|
138
127
|
`Changed`, `Fixed`, `Removed`).
|
|
139
128
|
- Keep subjects user-facing so auto-generated release notes are
|
|
140
129
|
meaningful.
|
|
141
130
|
- Group related changes into focused commits instead of one broad commit.
|
|
142
131
|
- Example: `Fixed timeout handling in status command`
|
|
143
|
-
|
|
132
|
+
5. Tag and push:
|
|
144
133
|
- `git tag vX.Y.Z`
|
|
145
|
-
- `git push origin main
|
|
146
|
-
|
|
134
|
+
- `git push origin main`
|
|
135
|
+
- `git push origin vX.Y.Z`
|
|
136
|
+
6. Confirm GitHub Actions:
|
|
147
137
|
- CI should pass.
|
|
148
138
|
- Publish workflow should upload to PyPI and create GitHub Release notes.
|
|
149
139
|
- Release notes should include generated notes plus a commit summary from
|
|
@@ -7,8 +7,8 @@ remove, status, and version metadata).
|
|
|
7
7
|
|
|
8
8
|
- [x] Standardize `--dryrun` flag: `update-versions` uses `--dry-run` but
|
|
9
9
|
`install` uses `--dryrun`. Change `update-versions` to `--dryrun`.
|
|
10
|
-
- [x] Add missing `success()` message for direct-download installs in
|
|
11
|
-
mode (`install.py`, `install_tool()`).
|
|
10
|
+
- [x] Add missing `success()` message for direct-download installs in
|
|
11
|
+
non-dryrun mode (`install.py`, `install_tool()`).
|
|
12
12
|
- [x] Replace PID-based temp directory naming with `tempfile.mkdtemp()` in
|
|
13
13
|
`install.py` `install_direct_download()`.
|
|
14
14
|
- [x] Guard `package.split("/", 1)` in `detection.py`
|
|
@@ -18,21 +18,21 @@ remove, status, and version metadata).
|
|
|
18
18
|
|
|
19
19
|
- [ ] Handle missing `node` cleanly during prerequisite checks
|
|
20
20
|
(`FileNotFoundError` path in Node version probing).
|
|
21
|
-
- [ ] Read tool version output from both stdout and stderr so status does
|
|
22
|
-
miss installed versions.
|
|
21
|
+
- [ ] Read tool version output from both stdout and stderr so status does
|
|
22
|
+
not miss installed versions.
|
|
23
23
|
- [ ] Make version cache writes atomic (write temp file + rename) to avoid
|
|
24
|
-
partial/corrupted `versions.json`.
|
|
25
|
-
- [ ] Warn when `versions.json` cache contains invalid JSON instead of
|
|
26
|
-
returning empty data.
|
|
24
|
+
partial/corrupted `versions.json`.
|
|
25
|
+
- [ ] Warn when `versions.json` cache contains invalid JSON instead of
|
|
26
|
+
silently returning empty data.
|
|
27
27
|
- [ ] Use `os.pathsep` instead of hardcoded `":"` in `prereqs.py`
|
|
28
28
|
`check_path_directories()`.
|
|
29
29
|
|
|
30
30
|
## Security and Integrity
|
|
31
31
|
|
|
32
|
-
- [ ] Add integrity verification for direct-download tarballs (not only
|
|
33
|
-
script SHA256).
|
|
34
|
-
- [ ] Extend tool metadata to support tarball checksum/signature fields
|
|
35
|
-
applicable.
|
|
32
|
+
- [ ] Add integrity verification for direct-download tarballs (not only
|
|
33
|
+
install script SHA256).
|
|
34
|
+
- [ ] Extend tool metadata to support tarball checksum/signature fields
|
|
35
|
+
where applicable.
|
|
36
36
|
|
|
37
37
|
## CLI and Automation UX
|
|
38
38
|
|
|
@@ -40,21 +40,23 @@ remove, status, and version metadata).
|
|
|
40
40
|
- [ ] Add a focused `doctor` command for environment checks (PATH,
|
|
41
41
|
prerequisites, command health).
|
|
42
42
|
- [ ] Consider `install --force` for reinstall/repair flows.
|
|
43
|
-
- [ ] Add cleanup support for stale direct-download versions no longer in
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
- [ ] Add cleanup support for stale direct-download versions no longer in
|
|
44
|
+
use.
|
|
45
|
+
- [ ] Expand `upgrade` help text to mention the default "only out-of-date
|
|
46
|
+
tools" behavior.
|
|
46
47
|
|
|
47
48
|
## Documentation
|
|
48
49
|
|
|
49
|
-
- [ ] Document that running `code-aide` with no subcommand defaults to
|
|
50
|
+
- [ ] Document that running `code-aide` with no subcommand defaults to
|
|
51
|
+
`status`.
|
|
50
52
|
- [ ] Add `install --dryrun` to the README usage examples.
|
|
51
53
|
- [ ] Document environment variables and config file paths
|
|
52
54
|
(`~/.config/code-aide/versions.json`).
|
|
53
55
|
|
|
54
56
|
## Platform and Package Detection
|
|
55
57
|
|
|
56
|
-
- [ ] Broaden system package metadata detection beyond Gentoo-specific
|
|
57
|
-
where practical.
|
|
58
|
+
- [ ] Broaden system package metadata detection beyond Gentoo-specific
|
|
59
|
+
tooling where practical.
|
|
58
60
|
|
|
59
61
|
## Maintainability and Tests
|
|
60
62
|
|
|
@@ -65,6 +67,5 @@ remove, status, and version metadata).
|
|
|
65
67
|
- `cmd_remove()` (completely untested)
|
|
66
68
|
- `fetch_url()` (completely untested)
|
|
67
69
|
- `check_prerequisites()` / `install_nodejs_npm()` (completely untested)
|
|
68
|
-
- `save_bundled_versions()` (untested)
|
|
69
70
|
- `get_system_package_info()` (completely untested)
|
|
70
71
|
- [ ] Add tests for prerequisite edge cases and cache write behavior.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Auto-migrate deprecated install methods
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
Claude Code switched from npm to a native installer. Users who installed
|
|
6
|
+
Claude via npm are stuck: `code-aide upgrade` runs `npm install -g @latest`
|
|
7
|
+
(the detected method) instead of the native script installer (the configured
|
|
8
|
+
method). `code-aide install` exits early because the command already exists.
|
|
9
|
+
There is no migration path. code-aide should detect this and fix it
|
|
10
|
+
automatically.
|
|
11
|
+
|
|
12
|
+
This is a general pattern -- any tool could change install methods in the
|
|
13
|
+
future. The solution should not be Claude-specific.
|
|
14
|
+
|
|
15
|
+
## Approach
|
|
16
|
+
|
|
17
|
+
A detected install method is "deprecated" when:
|
|
18
|
+
|
|
19
|
+
- Detected method is `npm` or `brew_npm` AND config `install_type` is
|
|
20
|
+
`script` or `direct_download`
|
|
21
|
+
|
|
22
|
+
Methods that are never considered deprecated (user-managed choices):
|
|
23
|
+
|
|
24
|
+
- `brew_formula`, `brew_cask` -- user explicitly chose Homebrew
|
|
25
|
+
- `system` -- managed by system package manager
|
|
26
|
+
|
|
27
|
+
Migration flow: remove old (npm), install new (configured method), with
|
|
28
|
+
clear messaging. If the new install fails after removal, provide recovery
|
|
29
|
+
instructions.
|
|
30
|
+
|
|
31
|
+
## Changes
|
|
32
|
+
|
|
33
|
+
### 1. `src/code_aide/data/tools.json` -- add deprecated_npm_package
|
|
34
|
+
|
|
35
|
+
Add a `deprecated_npm_package` field to Claude's entry:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
"claude": {
|
|
39
|
+
"name": "Claude CLI (Claude Code)",
|
|
40
|
+
"install_type": "script",
|
|
41
|
+
"deprecated_npm_package": "@anthropic-ai/claude-code",
|
|
42
|
+
...
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This records the old npm package name explicitly so the migration removal
|
|
47
|
+
step does not rely solely on extracting the package name from the binary
|
|
48
|
+
path.
|
|
49
|
+
|
|
50
|
+
### 2. `src/code_aide/detection.py` -- add deprecation detection
|
|
51
|
+
|
|
52
|
+
Add two functions:
|
|
53
|
+
|
|
54
|
+
- `is_deprecated_install(tool_name)` -- returns True when the detected
|
|
55
|
+
install method is `npm` or `brew_npm` but the configured `install_type` is
|
|
56
|
+
something else (script, direct_download). Also returns True when
|
|
57
|
+
`deprecated_npm_package` is set and the detected method is npm. Brew
|
|
58
|
+
formula/cask and system installs are never deprecated (user-managed).
|
|
59
|
+
- `format_migration_warning(tool_name)` -- returns a human-readable warning
|
|
60
|
+
string, or None if not deprecated. Uses existing `format_install_method()`
|
|
61
|
+
for labels.
|
|
62
|
+
|
|
63
|
+
### 3. `src/code_aide/operations.py` -- auto-migrate in upgrade
|
|
64
|
+
|
|
65
|
+
Add `_migrate_install_method()` private function that:
|
|
66
|
+
|
|
67
|
+
1. Warns about the deprecated method
|
|
68
|
+
2. Calls `remove_tool()` to remove the old npm install
|
|
69
|
+
3. Calls `install_tool()` to install via the configured method
|
|
70
|
+
4. If install fails after remove, prints recovery instructions (`code-aide
|
|
71
|
+
install <tool>` and manual curl command for script types)
|
|
72
|
+
|
|
73
|
+
Modify `upgrade_tool()`: after `detect_install_method()`, check
|
|
74
|
+
`is_deprecated_install()`. If True, call `_migrate_install_method()` instead
|
|
75
|
+
of the normal upgrade branch.
|
|
76
|
+
|
|
77
|
+
Modify `remove_tool()` npm branch: fall back to
|
|
78
|
+
`tool_config.get("deprecated_npm_package")` when looking up the npm package
|
|
79
|
+
name. Current code: `npm_package = detail or
|
|
80
|
+
tool_config.get("npm_package")`. Change to also check
|
|
81
|
+
`deprecated_npm_package`.
|
|
82
|
+
|
|
83
|
+
New imports needed: `is_deprecated_install`, `format_install_method` from
|
|
84
|
+
detection, `install_tool` from install.
|
|
85
|
+
|
|
86
|
+
Note: after `remove_tool()` succeeds, `command_exists()` returns False so
|
|
87
|
+
`install_tool()` proceeds normally with the configured `install_type`.
|
|
88
|
+
|
|
89
|
+
### 4. `src/code_aide/commands_actions.py` -- include deprecated in auto-upgrade
|
|
90
|
+
|
|
91
|
+
Modify `cmd_upgrade()` no-args path: after building the version-outdated
|
|
92
|
+
list, also add any installed tools with deprecated install methods. Without
|
|
93
|
+
this, a tool whose version is current but install method is deprecated would
|
|
94
|
+
be silently skipped by `code-aide upgrade`.
|
|
95
|
+
|
|
96
|
+
New import: `is_deprecated_install` from detection.
|
|
97
|
+
|
|
98
|
+
### 5. `src/code_aide/commands_tools.py` -- show warnings in status/list
|
|
99
|
+
|
|
100
|
+
In both `cmd_list()` and `cmd_status()`, after displaying "Installed via:",
|
|
101
|
+
call `format_migration_warning()` and display the warning if present.
|
|
102
|
+
|
|
103
|
+
At the end of `cmd_status()`, add a summary line counting tools that need
|
|
104
|
+
migration.
|
|
105
|
+
|
|
106
|
+
New imports: `format_migration_warning`, `is_deprecated_install` from
|
|
107
|
+
detection.
|
|
108
|
+
|
|
109
|
+
### 6. Tests
|
|
110
|
+
|
|
111
|
+
- `tests/test_detection.py`: Tests for `is_deprecated_install()` covering
|
|
112
|
+
npm to script (deprecated), npm to npm (not deprecated), brew_formula
|
|
113
|
+
(never deprecated), system (never deprecated), not installed, unknown
|
|
114
|
+
tool, npm to direct_download. Tests for `format_migration_warning()`.
|
|
115
|
+
- `tests/test_operations.py`: Tests for migration in `upgrade_tool()`:
|
|
116
|
+
triggers migration, normal upgrade when not deprecated, migration fails on
|
|
117
|
+
remove, migration fails on install with recovery message.
|
|
118
|
+
- `tests/test_commands_tools.py`: Test that status/list show migration
|
|
119
|
+
warnings for deprecated installs.
|
|
120
|
+
|
|
121
|
+
## Verification
|
|
122
|
+
|
|
123
|
+
1. `pre-commit run --all-files` -- formatting passes
|
|
124
|
+
2. `uv run pytest tests/ -v` -- all tests pass
|
|
125
|
+
3. `uv run python -m code_aide status` -- shows migration warning for
|
|
126
|
+
npm-installed Claude (if applicable)
|
|
127
|
+
4. `uv run python -m code_aide upgrade claude` -- performs migration (remove
|
|
128
|
+
npm, install via script)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Remove bundled version baseline
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
code-aide has a three-layer version data model where `latest_version` and
|
|
6
|
+
`latest_date` are bundled in `tools.json` as a baseline. These go stale
|
|
7
|
+
between releases and require a manual release step (`update-versions -b
|
|
8
|
+
-y`). The `install_sha256` field protects against tampered install scripts
|
|
9
|
+
and must remain bundled.
|
|
10
|
+
|
|
11
|
+
## Approach
|
|
12
|
+
|
|
13
|
+
Remove `latest_version` and `latest_date` from bundled data and the
|
|
14
|
+
`-b`/`--bundled` flag from `update-versions`, simplifying to two layers:
|
|
15
|
+
bundled definitions (with SHA256) + user cache (with versions). The
|
|
16
|
+
`install_direct_download()` function needs an on-demand fetch when
|
|
17
|
+
`latest_version` is missing (fresh install with no cache).
|
|
18
|
+
|
|
19
|
+
## Changes
|
|
20
|
+
|
|
21
|
+
### 1. `src/code_aide/data/tools.json` -- remove version fields
|
|
22
|
+
|
|
23
|
+
Remove `latest_version` and `latest_date` from all 8 tool entries. Keep
|
|
24
|
+
`install_sha256`.
|
|
25
|
+
|
|
26
|
+
### 2. `src/code_aide/config.py` -- remove bundled save function
|
|
27
|
+
|
|
28
|
+
- Remove `save_bundled_versions()` function.
|
|
29
|
+
- Update `load_tools_config()` docstring to describe two-layer model.
|
|
30
|
+
- `DYNAMIC_FIELDS` stays the same (user cache still stores all three).
|
|
31
|
+
|
|
32
|
+
### 3. `src/code_aide/entry.py` -- remove --bundled flag
|
|
33
|
+
|
|
34
|
+
Remove `-b`/`--bundled` argument from the update-versions subparser.
|
|
35
|
+
|
|
36
|
+
### 4. `src/code_aide/commands_actions.py` -- simplify update-versions
|
|
37
|
+
|
|
38
|
+
- Remove `save_bundled_versions` from imports.
|
|
39
|
+
- Remove `if not args.bundled:` guard around `merge_cached_versions` --
|
|
40
|
+
always merge.
|
|
41
|
+
- Remove bundled branch in `_save()` -- always save to user cache.
|
|
42
|
+
- Remove `args.bundled` reference.
|
|
43
|
+
|
|
44
|
+
### 5. `src/code_aide/install.py` -- handle missing latest_version
|
|
45
|
+
|
|
46
|
+
In `install_direct_download()`, `tool_config["latest_version"]` will
|
|
47
|
+
KeyError on fresh installs with no cache. Add on-demand fetch: if
|
|
48
|
+
`latest_version` is missing, call `check_script_tool()` to get it before
|
|
49
|
+
proceeding with the download.
|
|
50
|
+
|
|
51
|
+
### 6. `README.md` -- update documentation
|
|
52
|
+
|
|
53
|
+
- Rewrite "How Version Data Works" to describe two-layer model.
|
|
54
|
+
- Remove release step 1 (`update-versions -b -y` step).
|
|
55
|
+
- Remove usage example for `update-versions -b -y`.
|
|
56
|
+
|
|
57
|
+
### 7. `AGENTS.md` -- update layer description
|
|
58
|
+
|
|
59
|
+
Change "Three-layer version data" to "Two-layer version data" and update
|
|
60
|
+
description.
|
|
61
|
+
|
|
62
|
+
### 8. Tests
|
|
63
|
+
|
|
64
|
+
- `tests/test_commands_actions.py`: Remove
|
|
65
|
+
`test_bundled_flag_skips_cache_and_saves_to_bundled`. Update remaining
|
|
66
|
+
tests that set `"bundled": False` in args.
|
|
67
|
+
|
|
68
|
+
## Verification
|
|
69
|
+
|
|
70
|
+
1. `pre-commit run --all-files` -- formatting passes
|
|
71
|
+
2. `uv run pytest tests/ -v` -- all tests pass
|
|
72
|
+
3. `uv run python -m code_aide status` -- shows versions from cache, or
|
|
73
|
+
plain version without comparison if no cache
|
|
74
|
+
4. `uv run python -m code_aide update-versions -n` -- fetches latest
|
|
75
|
+
versions
|
|
76
|
+
5. `uv run python -m code_aide update-versions -y` -- saves to user cache
|
|
77
|
+
6. `uv run python -m code_aide update-versions -b` -- errors (flag removed)
|
|
@@ -5,6 +5,7 @@ import sys
|
|
|
5
5
|
from typing import Any, Dict, List
|
|
6
6
|
|
|
7
7
|
from code_aide.constants import TOOLS
|
|
8
|
+
from code_aide.detection import is_deprecated_install
|
|
8
9
|
from code_aide.install import install_tool
|
|
9
10
|
from code_aide.console import error, info, success, warning
|
|
10
11
|
from code_aide.operations import remove_tool, upgrade_tool, validate_tools
|
|
@@ -26,7 +27,6 @@ from code_aide.config import (
|
|
|
26
27
|
load_bundled_tools,
|
|
27
28
|
load_versions_cache,
|
|
28
29
|
merge_cached_versions,
|
|
29
|
-
save_bundled_versions,
|
|
30
30
|
save_updated_versions,
|
|
31
31
|
)
|
|
32
32
|
|
|
@@ -124,6 +124,10 @@ def cmd_upgrade(args: argparse.Namespace) -> None:
|
|
|
124
124
|
for name, config in TOOLS.items():
|
|
125
125
|
if not is_tool_installed(name):
|
|
126
126
|
continue
|
|
127
|
+
if is_deprecated_install(name):
|
|
128
|
+
if name not in tools_to_upgrade:
|
|
129
|
+
tools_to_upgrade.append(name)
|
|
130
|
+
continue
|
|
127
131
|
latest = config.get("latest_version")
|
|
128
132
|
if not latest:
|
|
129
133
|
continue
|
|
@@ -234,8 +238,7 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
|
|
|
234
238
|
"""Handle update-versions command: check upstream for latest tool versions."""
|
|
235
239
|
bundled = load_bundled_tools()
|
|
236
240
|
tools = bundled.get("tools", {})
|
|
237
|
-
|
|
238
|
-
merge_cached_versions(tools, load_versions_cache())
|
|
241
|
+
merge_cached_versions(tools, load_versions_cache())
|
|
239
242
|
|
|
240
243
|
config: Dict[str, Any] = {"tools": tools}
|
|
241
244
|
|
|
@@ -293,10 +296,7 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
|
|
|
293
296
|
version_info_changed = True
|
|
294
297
|
|
|
295
298
|
def _save(tools: dict) -> str:
|
|
296
|
-
"""Save versions to
|
|
297
|
-
if args.bundled:
|
|
298
|
-
path = save_bundled_versions(tools)
|
|
299
|
-
return path
|
|
299
|
+
"""Save versions to user cache. Returns description."""
|
|
300
300
|
save_updated_versions(tools)
|
|
301
301
|
return "~/.config/code-aide/versions.json"
|
|
302
302
|
|
|
@@ -8,6 +8,7 @@ from typing import List
|
|
|
8
8
|
from code_aide.constants import Colors, PACKAGE_MANAGERS, TOOLS
|
|
9
9
|
from code_aide.detection import (
|
|
10
10
|
format_install_method,
|
|
11
|
+
format_migration_warning,
|
|
11
12
|
get_system_package_info,
|
|
12
13
|
detect_install_method,
|
|
13
14
|
)
|
|
@@ -48,6 +49,9 @@ def cmd_list(args: argparse.Namespace) -> None:
|
|
|
48
49
|
" Installed via: "
|
|
49
50
|
f"{format_install_method(install_info['method'], install_info['detail'])}"
|
|
50
51
|
)
|
|
52
|
+
migration_msg = format_migration_warning(tool_name)
|
|
53
|
+
if migration_msg:
|
|
54
|
+
warning(f" {migration_msg}")
|
|
51
55
|
|
|
52
56
|
if tool_config.get("min_node_version"):
|
|
53
57
|
print(f" Requires: Node.js v{tool_config['min_node_version']}+")
|
|
@@ -99,6 +103,7 @@ def cmd_status(args: argparse.Namespace) -> None:
|
|
|
99
103
|
print()
|
|
100
104
|
|
|
101
105
|
outdated_count = 0
|
|
106
|
+
migration_count = 0
|
|
102
107
|
config_outdated: List[str] = []
|
|
103
108
|
|
|
104
109
|
for tool_name, tool_config in TOOLS.items():
|
|
@@ -156,6 +161,10 @@ def cmd_status(args: argparse.Namespace) -> None:
|
|
|
156
161
|
" Installed via: "
|
|
157
162
|
f"{format_install_method(install_info['method'], install_info['detail'])}"
|
|
158
163
|
)
|
|
164
|
+
migration_msg = format_migration_warning(tool_name)
|
|
165
|
+
if migration_msg:
|
|
166
|
+
warning(f" {migration_msg}")
|
|
167
|
+
migration_count += 1
|
|
159
168
|
|
|
160
169
|
if status["user"]:
|
|
161
170
|
print(f" User: {status['user']}")
|
|
@@ -181,3 +190,8 @@ def cmd_status(args: argparse.Namespace) -> None:
|
|
|
181
190
|
f"{Colors.YELLOW}{outdated_count} tool(s) can be upgraded with "
|
|
182
191
|
f"'code-aide upgrade'.{Colors.NC}"
|
|
183
192
|
)
|
|
193
|
+
if migration_count > 0:
|
|
194
|
+
print(
|
|
195
|
+
f"{Colors.YELLOW}{migration_count} tool(s) need migration to a "
|
|
196
|
+
f"new install method. Run 'code-aide upgrade' to migrate.{Colors.NC}"
|
|
197
|
+
)
|
|
@@ -76,10 +76,10 @@ def merge_cached_versions(tools: dict, cache: dict) -> None:
|
|
|
76
76
|
def load_tools_config() -> dict:
|
|
77
77
|
"""Load tool config: bundled definitions merged with cached versions.
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
when present.
|
|
79
|
+
Two-layer model: the bundled tools.json provides tool definitions and
|
|
80
|
+
install_sha256 checksums. The user's version cache (from
|
|
81
|
+
update-versions) provides latest_version, latest_date, and updated
|
|
82
|
+
install_sha256 values when present.
|
|
83
83
|
"""
|
|
84
84
|
bundled = load_bundled_tools()
|
|
85
85
|
cache = load_versions_cache()
|
|
@@ -103,29 +103,3 @@ def save_updated_versions(tools: dict) -> None:
|
|
|
103
103
|
if entry:
|
|
104
104
|
cache_data["tools"][tool_key] = entry
|
|
105
105
|
save_versions_cache(cache_data)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def save_bundled_versions(tools: dict) -> str:
|
|
109
|
-
"""Update dynamic fields in the bundled data/tools.json.
|
|
110
|
-
|
|
111
|
-
Loads the existing bundled file to preserve static fields, then
|
|
112
|
-
overwrites only the dynamic version fields from the provided tools
|
|
113
|
-
dict. Returns the file path written.
|
|
114
|
-
"""
|
|
115
|
-
ref = importlib.resources.files("code_aide").joinpath("data/tools.json")
|
|
116
|
-
path = str(ref)
|
|
117
|
-
|
|
118
|
-
with open(path, encoding="utf-8") as f:
|
|
119
|
-
bundled = json.load(f)
|
|
120
|
-
|
|
121
|
-
for tool_key, tool_data in tools.items():
|
|
122
|
-
if tool_key in bundled.get("tools", {}):
|
|
123
|
-
for field in DYNAMIC_FIELDS:
|
|
124
|
-
if field in tool_data:
|
|
125
|
-
bundled["tools"][tool_key][field] = tool_data[field]
|
|
126
|
-
|
|
127
|
-
with open(path, "w", encoding="utf-8") as f:
|
|
128
|
-
json.dump(bundled, f, indent=2)
|
|
129
|
-
f.write("\n")
|
|
130
|
-
|
|
131
|
-
return path
|