Skip to content

Commit 38babaf

Browse files
committed
fix(claude): use native installer and robust version detection
- Switch from npm_global to dedicated_script install method - Add version_command that reads package.json for npm installs (avoids Node.js v25+ crash with SlowBuffer API removal) - Create install_claude.sh with install method priority: 1. Native installer (curl -fsSL https://claude.ai/install.sh) 2. Homebrew cask (brew install --cask claude-code) 3. npm fallback (with Node.js version check) - Add github_repo for upstream version tracking - Document all installation methods in notes Fixes version detection showing Node.js version (25.2.1) instead of Claude Code version when claude --version crashes.
1 parent d41f1c4 commit 38babaf

2 files changed

Lines changed: 183 additions & 4 deletions

File tree

catalog/claude.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
{
22
"name": "claude",
33
"category": "ai",
4-
"install_method": "npm_global",
4+
"install_method": "dedicated_script",
55
"description": "Anthropic's Claude Code CLI - AI-powered development assistant",
6-
"homepage": "https://www.npmjs.com/package/@anthropic-ai/claude-code",
6+
"homepage": "https://claude.ai/download",
7+
"github_repo": "anthropics/claude-code",
78
"binary_name": "claude",
8-
"package_name": "@anthropic-ai/claude-code",
9+
"script": "install_claude.sh",
10+
"version_command": "claude_bin=$(command -v claude 2>/dev/null); if [ -n \"$claude_bin\" ]; then real_path=$(readlink -f \"$claude_bin\" 2>/dev/null || echo \"$claude_bin\"); if echo \"$real_path\" | grep -q 'node_modules'; then pkg_dir=$(dirname \"$real_path\"); [ -f \"$pkg_dir/package.json\" ] && grep '\"version\"' \"$pkg_dir/package.json\" | head -1 | sed 's/.*\"version\": *\"\\([0-9][0-9.]*\\)\".*/\\1/' && exit 0; fi; timeout 2 \"$claude_bin\" --version 2>/dev/null | grep -oE '[0-9]+\\.[0-9]+\\.[0-9]+' | head -1; fi",
911
"guide": {
1012
"display_name": "Claude Code",
1113
"install_action": "upgrade",
1214
"order": 400
1315
},
14-
"auto_update": true
16+
"auto_update": true,
17+
"notes": "Native install recommended: curl -fsSL https://claude.ai/install.sh | bash. Also available via: brew install --cask claude-code (macOS). Legacy npm install requires Node.js 18-24 (v25+ incompatible)."
1518
}

scripts/install_claude.sh

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#!/usr/bin/env bash
2+
# Dedicated installer for Claude Code CLI
3+
# Uses official native installer (recommended) with fallbacks
4+
set -euo pipefail
5+
6+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
ACTION="${1:-install}"
8+
9+
# Get current version
10+
get_current_version() {
11+
local claude_bin
12+
claude_bin=$(command -v claude 2>/dev/null || true)
13+
14+
if [ -z "$claude_bin" ]; then
15+
echo ""
16+
return
17+
fi
18+
19+
local real_path
20+
real_path=$(readlink -f "$claude_bin" 2>/dev/null || echo "$claude_bin")
21+
22+
# If npm install, get version from package.json (avoids Node.js version issues)
23+
if echo "$real_path" | grep -q 'node_modules'; then
24+
local pkg_dir
25+
pkg_dir=$(dirname "$real_path")
26+
if [ -f "$pkg_dir/package.json" ]; then
27+
grep '"version"' "$pkg_dir/package.json" | head -1 | sed 's/.*"version": *"\([0-9][0-9.]*\)".*/\1/' && return
28+
fi
29+
fi
30+
31+
# For native installs, try --version
32+
timeout 2 "$claude_bin" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true
33+
}
34+
35+
# Install via native installer (recommended)
36+
install_native() {
37+
echo "[claude] Installing via native installer (recommended)..." >&2
38+
39+
if [ "$(uname)" = "Darwin" ] || [ "$(uname)" = "Linux" ]; then
40+
# macOS / Linux / WSL
41+
if command -v curl >/dev/null 2>&1; then
42+
curl -fsSL https://claude.ai/install.sh | bash
43+
return $?
44+
elif command -v wget >/dev/null 2>&1; then
45+
wget -qO- https://claude.ai/install.sh | bash
46+
return $?
47+
fi
48+
fi
49+
50+
return 1
51+
}
52+
53+
# Install via Homebrew (macOS alternative)
54+
install_homebrew() {
55+
if command -v brew >/dev/null 2>&1; then
56+
echo "[claude] Installing via Homebrew cask..." >&2
57+
brew install --cask claude-code
58+
return $?
59+
fi
60+
return 1
61+
}
62+
63+
# Install via npm (legacy fallback)
64+
install_npm() {
65+
if command -v npm >/dev/null 2>&1; then
66+
# Check Node.js version - npm install doesn't work with v25+
67+
local node_version
68+
node_version=$(node --version 2>/dev/null | sed 's/v//' | cut -d. -f1)
69+
70+
if [ -n "$node_version" ] && [ "$node_version" -ge 25 ]; then
71+
echo "[claude] Warning: npm install not supported on Node.js v25+ (SlowBuffer API removed)" >&2
72+
echo "[claude] Please use native installer: curl -fsSL https://claude.ai/install.sh | bash" >&2
73+
return 1
74+
fi
75+
76+
echo "[claude] Installing via npm (legacy)..." >&2
77+
npm install -g @anthropic-ai/claude-code
78+
return $?
79+
fi
80+
return 1
81+
}
82+
83+
# Upgrade existing installation
84+
upgrade_claude() {
85+
local claude_bin
86+
claude_bin=$(command -v claude 2>/dev/null || true)
87+
88+
if [ -z "$claude_bin" ]; then
89+
echo "[claude] Not installed, running install..." >&2
90+
install_claude
91+
return $?
92+
fi
93+
94+
local real_path
95+
real_path=$(readlink -f "$claude_bin" 2>/dev/null || echo "$claude_bin")
96+
97+
# Detect installation method and upgrade accordingly
98+
if echo "$real_path" | grep -q 'node_modules'; then
99+
echo "[claude] Detected npm installation, upgrading via npm..." >&2
100+
npm update -g @anthropic-ai/claude-code || install_native
101+
elif echo "$real_path" | grep -q 'Cellar\|homebrew'; then
102+
echo "[claude] Detected Homebrew installation, upgrading via brew..." >&2
103+
brew upgrade --cask claude-code || brew reinstall --cask claude-code
104+
else
105+
echo "[claude] Detected native installation, re-running installer..." >&2
106+
install_native
107+
fi
108+
}
109+
110+
# Main install function
111+
install_claude() {
112+
local before after path
113+
before="$(get_current_version)"
114+
115+
# Try installation methods in order of preference
116+
if ! install_native; then
117+
echo "[claude] Native installer failed, trying alternatives..." >&2
118+
if ! install_homebrew; then
119+
if ! install_npm; then
120+
echo "[claude] Error: All installation methods failed" >&2
121+
echo "[claude] Please install manually from: https://claude.ai/download" >&2
122+
return 1
123+
fi
124+
fi
125+
fi
126+
127+
# Refresh PATH
128+
hash -r 2>/dev/null || true
129+
130+
after="$(get_current_version)"
131+
path="$(command -v claude 2>/dev/null || true)"
132+
133+
printf "[%s] before: %s\n" "claude" "${before:-<none>}"
134+
printf "[%s] after: %s\n" "claude" "${after:-<none>}"
135+
if [ -n "$path" ]; then printf "[%s] path: %s\n" "claude" "$path"; fi
136+
137+
# Refresh snapshot if available
138+
if [ -f "$DIR/lib/install_strategy.sh" ]; then
139+
. "$DIR/lib/install_strategy.sh"
140+
refresh_snapshot "claude" 2>/dev/null || true
141+
fi
142+
}
143+
144+
# Uninstall
145+
uninstall_claude() {
146+
local claude_bin
147+
claude_bin=$(command -v claude 2>/dev/null || true)
148+
149+
if [ -z "$claude_bin" ]; then
150+
echo "[claude] Not installed" >&2
151+
return 0
152+
fi
153+
154+
local real_path
155+
real_path=$(readlink -f "$claude_bin" 2>/dev/null || echo "$claude_bin")
156+
157+
if echo "$real_path" | grep -q 'node_modules'; then
158+
echo "[claude] Uninstalling npm package..." >&2
159+
npm uninstall -g @anthropic-ai/claude-code
160+
elif echo "$real_path" | grep -q 'Cellar\|homebrew'; then
161+
echo "[claude] Uninstalling Homebrew cask..." >&2
162+
brew uninstall --cask claude-code
163+
else
164+
echo "[claude] Native installation detected" >&2
165+
echo "[claude] To uninstall, remove: $claude_bin" >&2
166+
echo "[claude] And optionally: rm -rf ~/.claude" >&2
167+
fi
168+
}
169+
170+
case "$ACTION" in
171+
install) install_claude ;;
172+
update|upgrade) upgrade_claude ;;
173+
uninstall) uninstall_claude ;;
174+
reconcile) install_claude ;;
175+
*) echo "Usage: $0 {install|update|upgrade|uninstall|reconcile}" ; exit 2 ;;
176+
esac

0 commit comments

Comments
 (0)