code-aide 1.4.2__tar.gz → 1.5.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.
Files changed (42) hide show
  1. {code_aide-1.4.2 → code_aide-1.5.0}/PKG-INFO +17 -16
  2. {code_aide-1.4.2 → code_aide-1.5.0}/README.md +16 -15
  3. code_aide-1.5.0/specs/claude-native-installer-migration.md +112 -0
  4. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/__init__.py +1 -1
  5. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/commands_actions.py +1 -1
  6. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/data/tools.json +5 -10
  7. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/detection.py +3 -2
  8. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/install.py +0 -14
  9. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/operations.py +6 -37
  10. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/versions.py +0 -2
  11. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_config.py +1 -1
  12. code_aide-1.5.0/tests/test_constants.py +21 -0
  13. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_detection.py +16 -18
  14. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_operations.py +10 -9
  15. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_versions.py +0 -10
  16. code_aide-1.4.2/tests/test_constants.py +0 -13
  17. {code_aide-1.4.2 → code_aide-1.5.0}/.github/workflows/ci.yml +0 -0
  18. {code_aide-1.4.2 → code_aide-1.5.0}/.github/workflows/publish.yml +0 -0
  19. {code_aide-1.4.2 → code_aide-1.5.0}/.gitignore +0 -0
  20. {code_aide-1.4.2 → code_aide-1.5.0}/.gitlab-ci.yml +0 -0
  21. {code_aide-1.4.2 → code_aide-1.5.0}/.pre-commit-config.yaml +0 -0
  22. {code_aide-1.4.2 → code_aide-1.5.0}/AGENTS.md +0 -0
  23. {code_aide-1.4.2 → code_aide-1.5.0}/CLAUDE.md +0 -0
  24. {code_aide-1.4.2 → code_aide-1.5.0}/LICENSE +0 -0
  25. {code_aide-1.4.2 → code_aide-1.5.0}/TODO.md +0 -0
  26. {code_aide-1.4.2 → code_aide-1.5.0}/pyproject.toml +0 -0
  27. {code_aide-1.4.2 → code_aide-1.5.0}/specs/missing-coding-llm-cli-tools.md +0 -0
  28. {code_aide-1.4.2 → code_aide-1.5.0}/specs/pre-commit-uv-setup.md +0 -0
  29. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/__main__.py +0 -0
  30. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/commands_tools.py +0 -0
  31. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/config.py +0 -0
  32. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/console.py +0 -0
  33. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/constants.py +0 -0
  34. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/entry.py +0 -0
  35. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/prereqs.py +0 -0
  36. {code_aide-1.4.2 → code_aide-1.5.0}/src/code_aide/status.py +0 -0
  37. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_commands_actions.py +0 -0
  38. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_commands_tools.py +0 -0
  39. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_console.py +0 -0
  40. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_install.py +0 -0
  41. {code_aide-1.4.2 → code_aide-1.5.0}/tests/test_status.py +0 -0
  42. {code_aide-1.4.2 → code_aide-1.5.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-aide
3
- Version: 1.4.2
3
+ Version: 1.5.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
@@ -84,7 +84,7 @@ code-aide update-versions -b -y
84
84
  | Tool | Command | Install Type | Default |
85
85
  |--------------------------|-----------|--------------------|---------|
86
86
  | Cursor CLI | `agent` | Direct download | Yes |
87
- | Claude CLI (Claude Code) | `claude` | Self-managed (npm) | Yes |
87
+ | Claude CLI (Claude Code) | `claude` | Script | Yes |
88
88
  | Gemini CLI | `gemini` | npm | Yes |
89
89
  | OpenCode | `opencode`| npm | No |
90
90
  | Kilo CLI | `kilo` | npm | No |
@@ -96,20 +96,20 @@ code-aide update-versions -b -y
96
96
 
97
97
  code-aide uses a three-layer version data model:
98
98
 
99
- 1. **Tool definitions** (bundled with the package): Install methods,
100
- URLs, npm packages, version args. Updated by releasing new versions
101
- of code-aide.
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.
102
102
 
103
- 2. **Bundled version baseline** (in `data/tools.json`): Latest
104
- versions and SHA256 hashes as known at release time. Acts as a
105
- fallback for fresh installs.
103
+ 2. **Bundled version baseline** (in `data/tools.json`): Latest versions and
104
+ SHA256 hashes as known at release time. Acts as a fallback for fresh
105
+ installs.
106
106
 
107
- 3. **User's local version cache**
108
- (`~/.config/code-aide/versions.json`): Written by `code-aide
109
- update-versions`. Takes precedence over bundled data when present.
107
+ 3. **User's local version cache** (`~/.config/code-aide/versions.json`):
108
+ Written by `code-aide update-versions`. Takes precedence over bundled
109
+ data when present.
110
110
 
111
- Run `code-aide update-versions` to get fresher version data without
112
- waiting for a new code-aide release.
111
+ Run `code-aide update-versions` to get fresher version data without waiting
112
+ for a new code-aide release.
113
113
 
114
114
  ## Features
115
115
 
@@ -130,7 +130,8 @@ waiting for a new code-aide release.
130
130
 
131
131
  1. Install uv: `curl -LsSf https://astral.sh/uv/install.sh | sh`
132
132
  2. Install dependencies: `uv sync`
133
- 3. Install pre-commit hooks: `uv tool install pre-commit && pre-commit install`
133
+ 3. Install pre-commit hooks: `uv tool install pre-commit && pre-commit
134
+ install`
134
135
  4. Run tests: `uv run pytest tests/ -v`
135
136
 
136
137
  ```bash
@@ -159,8 +160,8 @@ uv run pytest tests/test_install.py::TestDetectOsArch -v
159
160
  - `git add src/code_aide/__init__.py`
160
161
  - `git commit -m "Bumped version to X.Y.Z"`
161
162
  5. Write useful commit messages before tagging:
162
- - Start subject lines with an action verb in past tense (`Added`, `Changed`,
163
- `Fixed`, `Removed`).
163
+ - Start subject lines with an action verb in past tense (`Added`,
164
+ `Changed`, `Fixed`, `Removed`).
164
165
  - Keep subjects user-facing so auto-generated release notes are
165
166
  meaningful.
166
167
  - Group related changes into focused commits instead of one broad commit.
@@ -58,7 +58,7 @@ code-aide update-versions -b -y
58
58
  | Tool | Command | Install Type | Default |
59
59
  |--------------------------|-----------|--------------------|---------|
60
60
  | Cursor CLI | `agent` | Direct download | Yes |
61
- | Claude CLI (Claude Code) | `claude` | Self-managed (npm) | Yes |
61
+ | Claude CLI (Claude Code) | `claude` | Script | Yes |
62
62
  | Gemini CLI | `gemini` | npm | Yes |
63
63
  | OpenCode | `opencode`| npm | No |
64
64
  | Kilo CLI | `kilo` | npm | No |
@@ -70,20 +70,20 @@ code-aide update-versions -b -y
70
70
 
71
71
  code-aide uses a three-layer version data model:
72
72
 
73
- 1. **Tool definitions** (bundled with the package): Install methods,
74
- URLs, npm packages, version args. Updated by releasing new versions
75
- of code-aide.
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.
76
76
 
77
- 2. **Bundled version baseline** (in `data/tools.json`): Latest
78
- versions and SHA256 hashes as known at release time. Acts as a
79
- fallback for fresh installs.
77
+ 2. **Bundled version baseline** (in `data/tools.json`): Latest versions and
78
+ SHA256 hashes as known at release time. Acts as a fallback for fresh
79
+ installs.
80
80
 
81
- 3. **User's local version cache**
82
- (`~/.config/code-aide/versions.json`): Written by `code-aide
83
- update-versions`. Takes precedence over bundled data when present.
81
+ 3. **User's local version cache** (`~/.config/code-aide/versions.json`):
82
+ Written by `code-aide update-versions`. Takes precedence over bundled
83
+ data when present.
84
84
 
85
- Run `code-aide update-versions` to get fresher version data without
86
- waiting for a new code-aide release.
85
+ Run `code-aide update-versions` to get fresher version data without waiting
86
+ for a new code-aide release.
87
87
 
88
88
  ## Features
89
89
 
@@ -104,7 +104,8 @@ waiting for a new code-aide release.
104
104
 
105
105
  1. Install uv: `curl -LsSf https://astral.sh/uv/install.sh | sh`
106
106
  2. Install dependencies: `uv sync`
107
- 3. Install pre-commit hooks: `uv tool install pre-commit && pre-commit install`
107
+ 3. Install pre-commit hooks: `uv tool install pre-commit && pre-commit
108
+ install`
108
109
  4. Run tests: `uv run pytest tests/ -v`
109
110
 
110
111
  ```bash
@@ -133,8 +134,8 @@ uv run pytest tests/test_install.py::TestDetectOsArch -v
133
134
  - `git add src/code_aide/__init__.py`
134
135
  - `git commit -m "Bumped version to X.Y.Z"`
135
136
  5. Write useful commit messages before tagging:
136
- - Start subject lines with an action verb in past tense (`Added`, `Changed`,
137
- `Fixed`, `Removed`).
137
+ - Start subject lines with an action verb in past tense (`Added`,
138
+ `Changed`, `Fixed`, `Removed`).
138
139
  - Keep subjects user-facing so auto-generated release notes are
139
140
  meaningful.
140
141
  - Group related changes into focused commits instead of one broad commit.
@@ -0,0 +1,112 @@
1
+ # Migrate Claude Code from npm to native installer in code-aide
2
+
3
+ ## Context
4
+
5
+ Anthropic has deprecated npm installation of Claude Code in favor of a
6
+ native installer (`curl -fsSL https://claude.ai/install.sh | bash`). The
7
+ native binary lives at `~/.local/bin/claude` (symlink to
8
+ `~/.local/share/claude/versions/<version>`), auto-updates, and has no
9
+ Node.js dependency. code-aide currently treats Claude as `self_managed`
10
+ install type backed by npm, which is now outdated.
11
+
12
+ ## Approach
13
+
14
+ Change Claude's install type from `self_managed` (npm-backed) to `script`
15
+ (install-script-backed). This reuses the existing `script` install type
16
+ already used by Amp, which downloads and verifies a shell script by SHA256
17
+ before executing it. Claude Code was the only tool using `self_managed`, so
18
+ that type becomes dead code and can be removed.
19
+
20
+ ## Changes
21
+
22
+ ### 1. `src/code_aide/data/tools.json` -- update claude config
23
+
24
+ - Change `install_type` from `self_managed` to `script`
25
+ - Add `install_url`: `https://claude.ai/install.sh`
26
+ - Add `install_sha256`:
27
+ `431889ac7d056f636aaf5b71524666d04c89c45560f80329940846479d484778`
28
+ - Remove `npm_package` field
29
+ - Remove `upgrade_command` field (native binary auto-updates; `script`
30
+ upgrade re-runs the install script which is idempotent)
31
+ - Change `prerequisites` from `["npm"]` to `[]`
32
+ - Update `docs_url` to `https://code.claude.com/docs/en/setup`
33
+
34
+ ### 2. `src/code_aide/detection.py` -- detect native installer
35
+
36
+ Add a new detection case before the `node_modules` check:
37
+
38
+ ```python
39
+ if "/.local/share/claude/versions/" in real_path:
40
+ return {"method": "script", "detail": "native installer"}
41
+ ```
42
+
43
+ This detects the native binary's real path pattern.
44
+
45
+ ### 3. `src/code_aide/detection.py` -- format label
46
+
47
+ No change needed -- the existing `format_install_method("script")` returns
48
+ `"script"` which is accurate.
49
+
50
+ ### 4. `src/code_aide/install.py` -- remove `self_managed` branch
51
+
52
+ Remove the `elif install_type == "self_managed"` block (lines 289-301). The
53
+ `script` handler (lines 261-275) will now handle Claude's installation.
54
+
55
+ ### 5. `src/code_aide/operations.py` -- remove `self_managed` branches
56
+
57
+ - **upgrade_tool**: Remove `elif method == "self_managed"` block (lines
58
+ 65-71). The `script` branch (lines 53-59) handles re-running the install
59
+ script, which for Claude is idempotent and installs the latest version.
60
+ - **remove_tool**: Remove `elif method == "self_managed"` block (lines
61
+ 203-230). The `script` branch (lines 133-158) removes the binary at its
62
+ `which` path. For full cleanup, add removal of `~/.local/share/claude`
63
+ directory in the script removal path when the tool is `claude`.
64
+
65
+ ### 6. `src/code_aide/versions.py` -- remove `self_managed` branch
66
+
67
+ - `format_check_backend`: Remove the `self_managed` -> `npm-registry`
68
+ mapping (line 276-277). Claude will now use `script-url` backend (SHA256
69
+ check of install script + version extraction).
70
+ - `check_npm_tool` is no longer called for Claude; `check_script_tool`
71
+ handles it instead via the `script` type path.
72
+
73
+ ### 7. `src/code_aide/commands_actions.py` -- remove `self_managed` from update check
74
+
75
+ - Line 259: Change `if install_type in ("npm", "self_managed")` to `if
76
+ install_type == "npm"`.
77
+
78
+ ### 8. Tests -- update all `self_managed` references
79
+
80
+ - **`tests/test_constants.py`**: Change assertion from `self_managed` to
81
+ `script`; remove npm prerequisite assertion
82
+ - **`tests/test_config.py`**: Change assertion from `self_managed` to
83
+ `script`
84
+ - **`tests/test_detection.py`**:
85
+ - Update `test_detects_brew_npm_wrapper` -- this test was for npm Claude
86
+ installs; replace with test for native installer detection (realpath
87
+ containing `/.local/share/claude/versions/`)
88
+ - Update `test_detects_plain_npm_global` -- same, replace with a variant
89
+ - Remove `TestFormatInstallMethodSelfManaged` class
90
+ - Update `test_brew_npm_label` test -- change to use a different tool's
91
+ npm package (or remove if no tools use brew_npm)
92
+ - **`tests/test_operations.py`**: Change `TestRemoveToolSelfManaged` to test
93
+ script-based removal instead
94
+ - **`tests/test_versions.py`**: Remove `TestFormatCheckBackendSelfManaged`;
95
+ optionally add a test that `script` maps to `script-url`
96
+
97
+ ### 9. `README.md` -- update table
98
+
99
+ Change Claude's install type from `Self-managed (npm)` to `Script`.
100
+
101
+ ## Verification
102
+
103
+ 1. `uv run pytest tests/ -v` -- all tests pass
104
+ 2. `uv run python -m code_aide status` -- Claude shows as installed, method
105
+ shows `script`
106
+ 3. `uv run python -m code_aide list` -- Claude listed with script install
107
+ type
108
+ 4. `uv run python -m code_aide update-versions -n` -- Claude checked via
109
+ script-url backend, SHA256 verified
110
+ 5. Manually verify detection: `claude` resolves to `~/.local/bin/claude`
111
+ with realpath `~/.local/share/claude/versions/...`, detected as `script`
112
+ method
@@ -1,3 +1,3 @@
1
1
  """code-aide - Manage AI coding CLI tools."""
2
2
 
3
- __version__ = "1.4.2"
3
+ __version__ = "1.5.0"
@@ -256,7 +256,7 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
256
256
  tool_config = tools[name]
257
257
  install_type = tool_config["install_type"]
258
258
 
259
- if install_type in ("npm", "self_managed"):
259
+ if install_type == "npm":
260
260
  results.append(check_npm_tool(name, tool_config, args.verbose))
261
261
  elif install_type in ("script", "direct_download"):
262
262
  results.append(check_script_tool(name, tool_config, args.verbose))
@@ -28,21 +28,16 @@
28
28
  "claude": {
29
29
  "name": "Claude CLI (Claude Code)",
30
30
  "command": "claude",
31
- "install_type": "self_managed",
32
- "npm_package": "@anthropic-ai/claude-code",
33
- "upgrade_command": [
34
- "claude",
35
- "upgrade"
36
- ],
37
- "prerequisites": [
38
- "npm"
39
- ],
31
+ "install_type": "script",
32
+ "install_url": "https://claude.ai/install.sh",
33
+ "install_sha256": "431889ac7d056f636aaf5b71524666d04c89c45560f80329940846479d484778",
34
+ "prerequisites": [],
40
35
  "min_node_version": null,
41
36
  "next_steps": "Run 'claude' and then use '/login' to authenticate",
42
37
  "version_args": [
43
38
  "--version"
44
39
  ],
45
- "docs_url": "https://docs.anthropic.com/en/docs/build-with-claude/claude-code",
40
+ "docs_url": "https://code.claude.com/docs/en/setup",
46
41
  "default_install": true,
47
42
  "latest_version": "2.1.63",
48
43
  "latest_date": "2026-02-28"
@@ -32,6 +32,9 @@ def detect_install_method(tool_name: str) -> Dict[str, Optional[str]]:
32
32
  if caskroom_match:
33
33
  return {"method": "brew_cask", "detail": caskroom_match.group(1)}
34
34
 
35
+ if "/.local/share/claude/versions/" in real_path:
36
+ return {"method": "script", "detail": "native installer"}
37
+
35
38
  if "/node_modules/" in real_path:
36
39
  npm_package = tool_config.get("npm_package")
37
40
  if not npm_package:
@@ -180,8 +183,6 @@ def format_install_method(method: Optional[str], detail: Optional[str]) -> str:
180
183
  return "script"
181
184
  if method == "direct_download":
182
185
  return "direct download"
183
- if method == "self_managed":
184
- return "self-managed"
185
186
  if method:
186
187
  return method
187
188
  return "unknown"
@@ -286,20 +286,6 @@ def install_tool(tool_name: str, dryrun: bool = False) -> bool:
286
286
  else:
287
287
  return False
288
288
 
289
- elif install_type == "self_managed":
290
- npm_package = tool_config.get("npm_package")
291
- if not npm_package:
292
- error(f"No npm package configured for {tool_config['name']}")
293
- return False
294
- if dryrun:
295
- info(f"[DRYRUN] Would install npm package: {npm_package}")
296
- else:
297
- run_command(["npm", "install", "-g", npm_package], check=True)
298
- success(f"{tool_config['name']} installed successfully")
299
- info(tool_config["next_steps"])
300
- if "docs_url" in tool_config:
301
- info(f"Documentation: {tool_config['docs_url']}")
302
-
303
289
  return True
304
290
 
305
291
  except subprocess.CalledProcessError as exc:
@@ -62,14 +62,6 @@ def upgrade_tool(tool_name: str) -> bool:
62
62
  if not install_direct_download(tool_name, tool_config):
63
63
  return False
64
64
 
65
- elif method == "self_managed":
66
- upgrade_cmd = tool_config.get("upgrade_command")
67
- if not upgrade_cmd:
68
- error(f"No upgrade_command configured for {tool_config['name']}")
69
- return False
70
- run_command(upgrade_cmd, check=True, capture=False)
71
- success(f"{tool_config['name']} upgraded successfully")
72
-
73
65
  elif method == "system":
74
66
  error(
75
67
  f"{tool_config['name']} is managed by the system package manager. "
@@ -157,6 +149,12 @@ def remove_tool(tool_name: str) -> bool:
157
149
  warning(f"Could not find {command} binary to remove")
158
150
  return True
159
151
 
152
+ if tool_name == "claude":
153
+ claude_data = os.path.expanduser("~/.local/share/claude")
154
+ if os.path.isdir(claude_data):
155
+ shutil.rmtree(claude_data)
156
+ info(f"Removed data directory: {claude_data}")
157
+
160
158
  elif method == "direct_download":
161
159
  bin_dir = os.path.expanduser(tool_config.get("bin_dir", "~/.local/bin"))
162
160
  removed_links = set()
@@ -200,35 +198,6 @@ def remove_tool(tool_name: str) -> bool:
200
198
 
201
199
  success(f"{tool_config['name']} removed successfully")
202
200
 
203
- elif method == "self_managed":
204
- command = tool_config["command"]
205
- command_path = shutil.which(command)
206
- removed_any = False
207
- if command_path:
208
- real_path = os.path.realpath(command_path)
209
- remove_paths = [command_path]
210
- if real_path != command_path:
211
- remove_paths.append(real_path)
212
-
213
- for path in remove_paths:
214
- if not os.path.lexists(path):
215
- continue
216
- is_link = os.path.islink(path)
217
- if os.path.isdir(path) and not is_link:
218
- shutil.rmtree(path)
219
- else:
220
- os.remove(path)
221
- if is_link:
222
- info(f"Removed symlink: {path}")
223
- else:
224
- info(f"Removed: {path}")
225
- removed_any = True
226
-
227
- if removed_any:
228
- success(f"{tool_config['name']} removed successfully")
229
- else:
230
- warning(f"Could not find {command} binary to remove")
231
-
232
201
  elif method == "system":
233
202
  error(
234
203
  f"{tool_config['name']} is managed by the system package manager. "
@@ -273,8 +273,6 @@ def format_check_backend(check_type: str) -> str:
273
273
  return "npm-registry"
274
274
  if check_type in ("script", "direct_download"):
275
275
  return "script-url"
276
- if check_type == "self_managed":
277
- return "npm-registry"
278
276
  return check_type
279
277
 
280
278
 
@@ -102,7 +102,7 @@ class TestMergeCachedOverBundled(unittest.TestCase):
102
102
  tools = code_aide_config.load_tools_config()
103
103
  self.assertEqual(tools["claude"]["latest_version"], "99.0.0")
104
104
  self.assertEqual(tools["claude"]["latest_date"], "2099-01-01")
105
- self.assertEqual(tools["claude"]["install_type"], "self_managed")
105
+ self.assertEqual(tools["claude"]["install_type"], "script")
106
106
 
107
107
 
108
108
  if __name__ == "__main__":
@@ -0,0 +1,21 @@
1
+ """Unit tests for shared CLI constants."""
2
+
3
+ import unittest
4
+
5
+ from code_aide import constants as cli_constants
6
+
7
+
8
+ class TestClaudeScriptConfig(unittest.TestCase):
9
+ """Tests for claude tool config expectations."""
10
+
11
+ def test_claude_install_type_is_script(self):
12
+ self.assertEqual(cli_constants.TOOLS["claude"]["install_type"], "script")
13
+
14
+ def test_claude_has_no_prerequisites(self):
15
+ self.assertEqual(cli_constants.TOOLS["claude"].get("prerequisites", []), [])
16
+
17
+ def test_claude_has_install_url(self):
18
+ self.assertIn("install_url", cli_constants.TOOLS["claude"])
19
+
20
+ def test_claude_has_install_sha256(self):
21
+ self.assertIn("install_sha256", cli_constants.TOOLS["claude"])
@@ -11,10 +11,8 @@ class TestFormatInstallMethod(unittest.TestCase):
11
11
 
12
12
  def test_brew_npm_label(self):
13
13
  self.assertEqual(
14
- cli_detection.format_install_method(
15
- "brew_npm", "@anthropic-ai/claude-code"
16
- ),
17
- "Homebrew prefix npm-global (@anthropic-ai/claude-code)",
14
+ cli_detection.format_install_method("brew_npm", "@google/gemini-cli"),
15
+ "Homebrew prefix npm-global (@google/gemini-cli)",
18
16
  )
19
17
 
20
18
  def test_brew_formula_label(self):
@@ -35,28 +33,28 @@ class TestDetectInstallMethod(unittest.TestCase):
35
33
 
36
34
  @mock.patch.object(cli_detection.os.path, "realpath")
37
35
  @mock.patch.object(cli_detection.shutil, "which")
38
- def test_detects_brew_npm_wrapper(self, mock_which, mock_realpath):
39
- mock_which.return_value = "/opt/homebrew/bin/claude"
36
+ def test_detects_native_installer(self, mock_which, mock_realpath):
37
+ mock_which.return_value = "/Users/test/.local/bin/claude"
40
38
  mock_realpath.return_value = (
41
- "/opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/cli.js"
39
+ "/Users/test/.local/share/claude/versions/2.1.63/claude"
42
40
  )
43
41
 
44
42
  self.assertEqual(
45
43
  cli_detection.detect_install_method("claude"),
46
- {"method": "brew_npm", "detail": "@anthropic-ai/claude-code"},
44
+ {"method": "script", "detail": "native installer"},
47
45
  )
48
46
 
49
47
  @mock.patch.object(cli_detection.os.path, "realpath")
50
48
  @mock.patch.object(cli_detection.shutil, "which")
51
- def test_detects_plain_npm_global(self, mock_which, mock_realpath):
52
- mock_which.return_value = "/Users/test/.local/bin/claude"
49
+ def test_detects_npm_global_gemini(self, mock_which, mock_realpath):
50
+ mock_which.return_value = "/Users/test/.local/bin/gemini"
53
51
  mock_realpath.return_value = (
54
- "/Users/test/.local/lib/node_modules/" "@anthropic-ai/claude-code/cli.js"
52
+ "/Users/test/.local/lib/node_modules/@google/gemini-cli/cli.js"
55
53
  )
56
54
 
57
55
  self.assertEqual(
58
- cli_detection.detect_install_method("claude"),
59
- {"method": "npm", "detail": "@anthropic-ai/claude-code"},
56
+ cli_detection.detect_install_method("gemini"),
57
+ {"method": "npm", "detail": "@google/gemini-cli"},
60
58
  )
61
59
 
62
60
  @mock.patch.object(cli_detection.os.path, "realpath")
@@ -108,11 +106,11 @@ class TestFormatInstallMethodDirectDownload(unittest.TestCase):
108
106
  )
109
107
 
110
108
 
111
- class TestFormatInstallMethodSelfManaged(unittest.TestCase):
112
- """Tests for format_install_method with self_managed method."""
109
+ class TestFormatInstallMethodScript(unittest.TestCase):
110
+ """Tests for format_install_method with script method."""
113
111
 
114
- def test_self_managed_label(self):
112
+ def test_script_label(self):
115
113
  self.assertEqual(
116
- cli_detection.format_install_method("self_managed", None),
117
- "self-managed",
114
+ cli_detection.format_install_method("script", None),
115
+ "script",
118
116
  )
@@ -70,21 +70,22 @@ class TestRemoveToolDirectDownload(unittest.TestCase):
70
70
  self.assertFalse(os.path.exists(os.path.join(versions_dir, "2.0.0")))
71
71
 
72
72
 
73
- class TestRemoveToolSelfManaged(unittest.TestCase):
74
- """Tests for remove_tool with self_managed install method."""
73
+ class TestRemoveToolScript(unittest.TestCase):
74
+ """Tests for remove_tool with script install method."""
75
75
 
76
- def test_removes_non_symlink_binary(self):
76
+ def test_removes_binary(self):
77
77
  with tempfile.TemporaryDirectory() as td:
78
- binary_path = os.path.join(td, "claude")
78
+ binary_path = os.path.join(td, "amp")
79
79
  with open(binary_path, "w", encoding="utf-8") as f:
80
80
  f.write("#!/bin/sh\n")
81
81
  os.chmod(binary_path, 0o755)
82
82
 
83
- tool_name = "self-managed-test"
83
+ tool_name = "script-test"
84
84
  tool_config = {
85
- "name": "Self Managed Test",
86
- "command": "claude",
87
- "install_type": "self_managed",
85
+ "name": "Script Test",
86
+ "command": "amp",
87
+ "install_type": "script",
88
+ "install_url": "https://example.com/install.sh",
88
89
  }
89
90
 
90
91
  with (
@@ -96,7 +97,7 @@ class TestRemoveToolSelfManaged(unittest.TestCase):
96
97
  cli_operations,
97
98
  "detect_install_method",
98
99
  return_value={
99
- "method": "self_managed",
100
+ "method": "script",
100
101
  "detail": None,
101
102
  },
102
103
  ),
@@ -238,16 +238,6 @@ class TestFormatCheckBackend(unittest.TestCase):
238
238
  self.assertEqual(cli_versions.format_check_backend("custom"), "custom")
239
239
 
240
240
 
241
- class TestFormatCheckBackendSelfManaged(unittest.TestCase):
242
- """Tests for format_check_backend with self_managed type."""
243
-
244
- def test_self_managed_uses_npm_registry(self):
245
- self.assertEqual(
246
- cli_versions.format_check_backend("self_managed"),
247
- "npm-registry",
248
- )
249
-
250
-
251
241
  class TestExtractScriptDate(unittest.TestCase):
252
242
  """Tests for extract_script_date."""
253
243
 
@@ -1,13 +0,0 @@
1
- """Unit tests for shared CLI constants."""
2
-
3
- import unittest
4
-
5
- from code_aide import constants as cli_constants
6
-
7
-
8
- class TestSelfManagedConfig(unittest.TestCase):
9
- """Tests for self-managed tool config expectations."""
10
-
11
- def test_claude_install_still_requires_npm(self):
12
- self.assertEqual(cli_constants.TOOLS["claude"]["install_type"], "self_managed")
13
- self.assertIn("npm", cli_constants.TOOLS["claude"].get("prerequisites", []))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes