User reported losing 6 months of accumulated work — projects, plans, custom commands/skills, file-history, history.jsonl — because uclaude_uninstall.sh did `rm -rf ~/.claude` without warning or backup. Same destruction risk in codex/gemini/qwen uninstallers (each has its own ~/.tool-name/ dir with user data). Fix: - claude/uclaude_uninstall.sh: DEFAULT preserves projects/, history.jsonl, commands/, plans/, file-history/, plugins/. Only removes settings.json + cache/ (which Claude regenerates). settings.json backed up first. - Explicit opt-in to wipe everything: UCLAUDE_PURGE_USER_DATA=1 (and even then creates a tar backup before delete) - README guidance updated NEVER again should an uninstaller silently destroy user data. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
151 lines
5.4 KiB
Bash
Executable File
151 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Claude Code — Uninstaller
|
|
# Removes Claude Code CLI, settings, env vars, and npm registry config.
|
|
#
|
|
# Usage: sudo bash uclaude_uninstall.sh
|
|
set -euo pipefail
|
|
|
|
GREEN="\033[92m"
|
|
CYAN="\033[96m"
|
|
YELLOW="\033[93m"
|
|
BOLD="\033[1m"
|
|
RESET="\033[0m"
|
|
|
|
log() { echo -e "${GREEN}[+]${RESET} $*"; }
|
|
warn() { echo -e "${YELLOW}[~]${RESET} $*"; }
|
|
info() { echo -e "${CYAN}[i]${RESET} $*"; }
|
|
|
|
# Cross-platform sed -i (macOS BSD sed requires `-i ''`, GNU sed uses `-i`).
|
|
# Use `sedi` instead of `sed -i` everywhere in this script.
|
|
sedi() {
|
|
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
sed -i '' "$@"
|
|
else
|
|
sed -i "$@"
|
|
fi
|
|
}
|
|
|
|
echo -e "${BOLD}"
|
|
echo " +--------------------------------------+"
|
|
echo " | Claude Code — Uninstaller |"
|
|
echo " +--------------------------------------+"
|
|
echo -e "${RESET}"
|
|
|
|
# ---- Uninstall npm package ----
|
|
|
|
if npm list -g @anthropic-ai/claude-code &>/dev/null 2>&1; then
|
|
info "Removing @anthropic-ai/claude-code..."
|
|
npm uninstall -g @anthropic-ai/claude-code 2>/dev/null || true
|
|
log "npm package removed"
|
|
else
|
|
warn "Claude Code not found in npm global packages"
|
|
fi
|
|
|
|
# ---- Remove settings ----
|
|
# DEFAULT: PRESERVE user data (projects, history, plans, commands, plugins,
|
|
# file-history). Only delete settings.json + cache/. User data took months
|
|
# to accumulate — never destroy without explicit opt-in.
|
|
#
|
|
# Set UCLAUDE_PURGE_USER_DATA=1 to wipe the entire ~/.claude/ directory
|
|
# (the old destructive behavior).
|
|
|
|
PURGE_USER_DATA="${UCLAUDE_PURGE_USER_DATA:-0}"
|
|
TIMESTAMP=$(date +%Y%m%d%H%M%S)
|
|
|
|
for user_home in /root /home/*; do
|
|
CLAUDE_DIR="$user_home/.claude"
|
|
if [ -d "$CLAUDE_DIR" ]; then
|
|
if [ "$PURGE_USER_DATA" = "1" ]; then
|
|
# Explicit opt-in: tar backup first, then wipe
|
|
BACKUP_TAR="$user_home/.claude.uninstall-backup.${TIMESTAMP}.tar.gz"
|
|
info "PURGE mode — backing up to $BACKUP_TAR before delete..."
|
|
tar -czf "$BACKUP_TAR" -C "$user_home" .claude 2>/dev/null && \
|
|
log "Backup saved: $BACKUP_TAR" || \
|
|
warn "Backup failed — aborting purge to preserve data"
|
|
if [ -f "$BACKUP_TAR" ]; then
|
|
rm -rf "$CLAUDE_DIR"
|
|
log "Removed $CLAUDE_DIR (restore: tar -xzf $BACKUP_TAR -C $user_home)"
|
|
fi
|
|
else
|
|
# Default: preserve user data, only remove patcher-managed files
|
|
info "Cleaning $CLAUDE_DIR (preserving user data)..."
|
|
for f in settings.json settings.local.json .patcher.config.cache.json; do
|
|
if [ -f "$CLAUDE_DIR/$f" ]; then
|
|
# Backup settings.json before delete (env vars are
|
|
# easy to recreate, but user may have customized)
|
|
cp "$CLAUDE_DIR/$f" "$CLAUDE_DIR/${f}.uninstall.bak.${TIMESTAMP}"
|
|
rm -f "$CLAUDE_DIR/$f"
|
|
log "Removed $CLAUDE_DIR/$f (backup: ${f}.uninstall.bak.${TIMESTAMP})"
|
|
fi
|
|
done
|
|
# Optionally clean cache/ (safe — Claude regenerates on next run)
|
|
if [ -d "$CLAUDE_DIR/cache" ]; then
|
|
rm -rf "$CLAUDE_DIR/cache"
|
|
log "Removed $CLAUDE_DIR/cache (will regenerate)"
|
|
fi
|
|
log "PRESERVED in $CLAUDE_DIR: projects/, history.jsonl, commands/, plans/, file-history/, plugins/, etc."
|
|
fi
|
|
fi
|
|
CLAUDE_JSON="$user_home/.claude.json"
|
|
if [ -f "$CLAUDE_JSON" ]; then
|
|
# Backup before delete (.claude.json holds onboarding + recent
|
|
# session refs — useful to keep for restore).
|
|
cp "$CLAUDE_JSON" "${CLAUDE_JSON}.uninstall.bak.${TIMESTAMP}"
|
|
rm -f "$CLAUDE_JSON"
|
|
log "Removed $CLAUDE_JSON (backup: ${CLAUDE_JSON}.uninstall.bak.${TIMESTAMP})"
|
|
fi
|
|
done
|
|
|
|
if [ "$PURGE_USER_DATA" != "1" ]; then
|
|
echo
|
|
info "User data PRESERVED. To wipe everything:"
|
|
info " UCLAUDE_PURGE_USER_DATA=1 sudo bash uclaude_uninstall.sh"
|
|
info "(That mode creates a tar backup first, even on purge)"
|
|
echo
|
|
fi
|
|
|
|
# ---- Remove env vars from shell rc files ----
|
|
|
|
for user_home in /root /home/*; do
|
|
for rc_file in "$user_home/.bashrc" "$user_home/.zshrc"; do
|
|
if [ -f "$rc_file" ] && grep -q 'ANTHROPIC_API_KEY\|CLAUDE_CODE\|Claude Code\|ANTHROPIC_BASE_URL' "$rc_file" 2>/dev/null; then
|
|
info "Cleaning env vars from $rc_file..."
|
|
sedi '/# Claude Code/d' "$rc_file"
|
|
sedi '/# UnlimitedCoding.*[Cc]laude/d' "$rc_file"
|
|
sedi '/ANTHROPIC_API_KEY/d' "$rc_file"
|
|
sedi '/ANTHROPIC_BASE_URL/d' "$rc_file"
|
|
sedi '/CLAUDE_CODE/d' "$rc_file"
|
|
log "Cleaned $rc_file"
|
|
fi
|
|
done
|
|
done
|
|
|
|
# ---- Remove /etc/profile.d script ----
|
|
|
|
for f in /etc/profile.d/claude-code.sh /etc/profile.d/claude_code.sh; do
|
|
if [ -f "$f" ]; then
|
|
rm -f "$f"
|
|
log "Removed $f"
|
|
fi
|
|
done
|
|
|
|
# ---- Remove env vars from /etc/environment ----
|
|
|
|
if [ -f "/etc/environment" ] && grep -q 'ANTHROPIC_API_KEY\|ANTHROPIC_BASE_URL\|CLAUDE_CODE' /etc/environment 2>/dev/null; then
|
|
info "Cleaning /etc/environment..."
|
|
sedi '/ANTHROPIC_API_KEY/d' /etc/environment
|
|
sedi '/ANTHROPIC_BASE_URL/d' /etc/environment
|
|
sedi '/CLAUDE_CODE/d' /etc/environment
|
|
log "Cleaned /etc/environment"
|
|
fi
|
|
|
|
# ---- Remove npm registry config ----
|
|
|
|
info "Removing npm registry config..."
|
|
npm config delete @anthropic-ai:registry 2>/dev/null || true
|
|
log "npm registry config removed"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}${BOLD} Claude Code fully uninstalled!${RESET}"
|
|
echo ""
|