Skip to content

Commit 5c9af2a

Browse files
committed
fix(claude): prevent repeated npm migration and improve cleanup
- Check for existing native binary before triggering migration - Extract cleanup_npm_versions() for reusable cleanup without reinstall - Remove nvm bin symlinks unconditionally (not just when node_modules exists) - Fully suppress pnpm uninstall errors (redirect both stdout and stderr) - Clean up stale nvm versions after direct binary install - Warn if another claude installation shadows the native binary - Warn if ~/.local/bin is not in PATH Fixes issue where migration ran repeatedly because: 1. Detection found nvm version first (PATH order) 2. npm uninstall left bin symlinks (conditional check failed) 3. pnpm error showed despite || true (stderr not redirected)
1 parent 6b74632 commit 5c9af2a

1 file changed

Lines changed: 68 additions & 18 deletions

File tree

scripts/install_claude.sh

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -153,45 +153,76 @@ install_direct() {
153153
chmod +x ~/.local/bin/claude
154154

155155
# Verify it works
156-
if ~/.local/bin/claude --version >/dev/null 2>&1; then
157-
echo "[claude] Installed to ~/.local/bin/claude" >&2
158-
echo "[claude] Make sure ~/.local/bin is in your PATH" >&2
159-
return 0
160-
else
156+
if ! ~/.local/bin/claude --version >/dev/null 2>&1; then
161157
echo "[claude] Binary verification failed" >&2
162158
rm -f ~/.local/bin/claude
163159
return 1
164160
fi
161+
162+
echo "[claude] Installed to ~/.local/bin/claude" >&2
163+
164+
# Check if PATH has ~/.local/bin
165+
case ":$PATH:" in
166+
*":$HOME/.local/bin:"*) ;;
167+
*)
168+
echo "[claude] Warning: ~/.local/bin is not in your PATH" >&2
169+
echo "[claude] Add to your shell config: export PATH=\"\$HOME/.local/bin:\$PATH\"" >&2
170+
;;
171+
esac
172+
173+
# Clean up any stale nvm versions that might shadow this installation
174+
cleanup_npm_versions 2>/dev/null || true
175+
176+
# Verify we're now finding the native version
177+
hash -r 2>/dev/null || true
178+
local found_path
179+
found_path=$(command -v claude 2>/dev/null || true)
180+
if [ "$found_path" != "$HOME/.local/bin/claude" ]; then
181+
echo "[claude] Warning: Another claude installation at $found_path may shadow this one" >&2
182+
echo "[claude] Ensure ~/.local/bin comes first in PATH" >&2
183+
fi
184+
185+
return 0
165186
}
166187

167188
# Compare versions (returns 0 if v1 < v2)
168189
version_lt() {
169190
[ "$(printf '%s\n%s' "$1" "$2" | sort -V | head -1)" = "$1" ] && [ "$1" != "$2" ]
170191
}
171192

172-
# Migrate from npm to native installer
173-
migrate_npm_to_native() {
174-
echo "[claude] Migrating from npm to native installer..." >&2
175-
echo "[claude] Removing npm packages..." >&2
193+
# Clean up npm/nvm versions without reinstalling
194+
# Used when native binary exists but stale npm versions remain
195+
cleanup_npm_versions() {
196+
# Remove from current npm (silent)
197+
npm uninstall -g @anthropic-ai/claude-code >/dev/null 2>&1 || true
176198

177-
# Remove from current npm
178-
npm uninstall -g @anthropic-ai/claude-code 2>/dev/null || true
179-
180-
# Remove from ALL nvm Node versions (they accumulate)
199+
# Remove from ALL nvm Node versions
181200
if [ -d "$HOME/.nvm/versions/node" ]; then
182201
for node_dir in "$HOME/.nvm/versions/node"/*/; do
202+
[ -d "$node_dir" ] || continue
203+
# Always remove bin symlink if it exists (don't check node_modules)
204+
if [ -L "$node_dir/bin/claude" ] || [ -f "$node_dir/bin/claude" ]; then
205+
rm -f "$node_dir/bin/claude" 2>/dev/null || true
206+
fi
207+
# Remove node_modules if present
183208
if [ -d "$node_dir/lib/node_modules/@anthropic-ai" ]; then
184-
echo "[claude] Removing from ${node_dir}..." >&2
185-
rm -rf "$node_dir/lib/node_modules/@anthropic-ai"
186-
rm -f "$node_dir/bin/claude"
209+
rm -rf "$node_dir/lib/node_modules/@anthropic-ai" 2>/dev/null || true
187210
fi
188211
done
189212
fi
190213

191-
# Remove pnpm version if present
214+
# Remove pnpm version if present (fully silent)
192215
if command -v pnpm >/dev/null 2>&1; then
193-
pnpm uninstall -g @anthropic-ai/claude-code 2>/dev/null || true
216+
pnpm uninstall -g @anthropic-ai/claude-code >/dev/null 2>&1 || true
194217
fi
218+
}
219+
220+
# Migrate from npm to native installer
221+
migrate_npm_to_native() {
222+
echo "[claude] Migrating from npm to native installer..." >&2
223+
echo "[claude] Removing npm packages..." >&2
224+
225+
cleanup_npm_versions
195226

196227
hash -r 2>/dev/null || true
197228
echo "[claude] Installing native version..." >&2
@@ -212,6 +243,25 @@ upgrade_claude() {
212243
local real_path
213244
real_path=$(readlink -f "$claude_bin" 2>/dev/null || echo "$claude_bin")
214245

246+
# Check if native binary already exists (even if not first in PATH)
247+
# This prevents unnecessary migration if native install succeeded previously
248+
if [ -x "$HOME/.local/bin/claude" ]; then
249+
local native_ver
250+
native_ver=$("$HOME/.local/bin/claude" --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)
251+
if [ -n "$native_ver" ]; then
252+
echo "[claude] Native installation exists at ~/.local/bin/claude (v${native_ver})" >&2
253+
# Only clean up stale nvm versions, don't reinstall
254+
if echo "$real_path" | grep -qE 'node_modules|\.nvm/'; then
255+
echo "[claude] Cleaning up stale npm installation..." >&2
256+
cleanup_npm_versions
257+
hash -r 2>/dev/null || true
258+
fi
259+
echo "[claude] Upgrading native installation..." >&2
260+
install_native
261+
return $?
262+
fi
263+
fi
264+
215265
# Detect installation method and upgrade accordingly
216266
# Check for npm install: node_modules in resolved path OR .nvm path (nvm-managed npm)
217267
if echo "$real_path" | grep -qE 'node_modules|\.nvm/'; then

0 commit comments

Comments
 (0)