Skip to content

Instantly share code, notes, and snippets.

@zaherg
Created May 19, 2026 07:06
Show Gist options
  • Select an option

  • Save zaherg/d4acfc3879718be3add15cbd5be20311 to your computer and use it in GitHub Desktop.

Select an option

Save zaherg/d4acfc3879718be3add15cbd5be20311 to your computer and use it in GitHub Desktop.
uninstall claude
#!/usr/bin/env bash
set -euo pipefail
RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; BOLD='\033[1m'; NC='\033[0m'
info() { echo -e "${GREEN}[+]${NC} $*"; }
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
die() { echo -e "${RED}[✗]${NC} $*" >&2; exit 1; }
success() { echo -e "${GREEN}[✓]${NC} $*"; }
header() { echo -e "\n${BOLD}$*${NC}"; }
usage() {
echo ""
echo -e "${BOLD} Claude Code Uninstaller — macOS${NC}"
echo ""
echo " Usage: $0 [OPTIONS]"
echo ""
echo " Options:"
echo " --purge Also remove config, settings, and session history"
echo " (~/.claude, ~/.claude.json, caches, preferences)"
echo " --help Show this help message"
echo ""
echo " Detects and removes:"
echo " • Native install (~/.local/bin/claude + ~/.local/share/claude)"
echo " • Homebrew cask (claude-code or claude-code@latest)"
echo " • npm global (@anthropic-ai/claude-code)"
echo " • Desktop app (/Applications/Claude.app)"
echo " • IDE extensions (VS Code, JetBrains)"
echo " • Stale binaries (/usr/local/bin/claude, etc.)"
echo ""
echo " Examples:"
echo " bash $0 # remove CLI only, keep config"
echo " bash $0 --purge # remove everything"
echo ""
}
REMOVE_CONFIG=false
case "${1:-}" in
--help|-h) usage; exit 0 ;;
--purge) REMOVE_CONFIG=true ;;
"") ;;
*) echo -e "${RED}Unknown option: $1${NC}" >&2; usage; exit 1 ;;
esac
echo ""
echo -e "${BOLD} Claude Code Uninstaller — macOS${NC}"
echo ""
# ── Detect all installation types ─────────────────────────────────────────────
FOUND_ANY=false
FOUND_NATIVE=false
FOUND_BREW=false
FOUND_NPM=false
FOUND_DESKTOP=false
# 1. Native install (curl | bash) — official recommended method
# Binary: ~/.local/bin/claude Data: ~/.local/share/claude
if [[ -f "$HOME/.local/bin/claude" ]]; then
FOUND_NATIVE=true
FOUND_ANY=true
info "Native install detected: $HOME/.local/bin/claude"
fi
# 2. Homebrew cask (stable or latest)
BREW_CASK=""
if command -v brew &>/dev/null; then
if brew list --cask 2>/dev/null | grep -q "^claude-code$"; then
BREW_CASK="claude-code"
FOUND_BREW=true
FOUND_ANY=true
info "Homebrew cask detected: claude-code"
elif brew list --cask 2>/dev/null | grep -q "^claude-code@latest$"; then
BREW_CASK="claude-code@latest"
FOUND_BREW=true
FOUND_ANY=true
info "Homebrew cask detected: claude-code@latest"
fi
fi
# 3. npm global
if command -v npm &>/dev/null && npm list -g --depth=0 2>/dev/null | grep -q "@anthropic-ai/claude-code"; then
FOUND_NPM=true
FOUND_ANY=true
info "npm global install detected"
fi
# 4. Desktop app
for app in "/Applications/Claude.app" "$HOME/Applications/Claude.app"; do
if [[ -d "$app" ]]; then
FOUND_DESKTOP=true
FOUND_ANY=true
info "Desktop app detected: $app"
break
fi
done
# 5. Stale binary in other locations (leftover from old installers)
STALE_BINARIES=()
for loc in "/usr/local/bin/claude" "/opt/homebrew/bin/claude" "$HOME/bin/claude"; do
if [[ -f "$loc" ]]; then
STALE_BINARIES+=("$loc")
FOUND_ANY=true
info "Stale binary detected: $loc"
fi
done
if ! $FOUND_ANY; then
warn "No Claude Code installation detected."
warn "Checked: native (~/.local/bin/claude), Homebrew casks, npm global, Desktop app."
exit 1
fi
# ── Confirm ───────────────────────────────────────────────────────────────────
echo ""
read -r -p "Proceed with uninstall? [y/N] " confirm
[[ "$confirm" =~ ^[Yy]$ ]] || { warn "Aborted."; exit 0; }
# ── Remove CLI installations ──────────────────────────────────────────────────
header "Removing CLI..."
if $FOUND_NATIVE; then
info "Removing native install..."
rm -f "$HOME/.local/bin/claude"
rm -rf "$HOME/.local/share/claude"
success "Native install removed."
fi
if $FOUND_BREW; then
info "Removing Homebrew cask: $BREW_CASK"
brew uninstall --cask "$BREW_CASK"
success "Homebrew cask removed."
fi
if $FOUND_NPM; then
info "Removing npm global package..."
npm uninstall -g @anthropic-ai/claude-code
# Clean any stale symlink
for stale in "/usr/local/bin/claude" "/opt/homebrew/bin/claude"; do
if [[ -L "$stale" ]] && [[ ! -e "$stale" ]]; then
rm -f "$stale"
info "Removed stale symlink: $stale"
fi
done
success "npm package removed."
fi
if ((${#STALE_BINARIES[@]} > 0)); then
for stale in "${STALE_BINARIES[@]}"; do
info "Removing stale binary: $stale"
rm -f "$stale"
done
success "Stale binaries removed."
fi
# ── Desktop app ───────────────────────────────────────────────────────────────
if $FOUND_DESKTOP; then
header "Desktop app..."
for app in "/Applications/Claude.app" "$HOME/Applications/Claude.app"; do
if [[ -d "$app" ]]; then
warn "Desktop app found at: $app"
read -r -p " Remove it now? [y/N] " rm_app
if [[ "$rm_app" =~ ^[Yy]$ ]]; then
# Kill if running
osascript -e 'quit app "Claude"' 2>/dev/null || true
sleep 1
rm -rf "$app"
success "Desktop app removed."
else
warn "Skipped. Remove manually via Finder > Applications > Claude."
fi
fi
done
fi
# ── IDE extensions ────────────────────────────────────────────────────────────
header "Checking IDE extensions..."
FOUND_EXT=false
for dir in \
"$HOME/.vscode/extensions" \
"$HOME/.vscode-insiders/extensions" \
"$HOME/Library/Application Support/Code/extensions" \
"$HOME/Library/Application Support/Code - Insiders/extensions"; do
if [[ -d "$dir" ]]; then
while IFS= read -r -d '' ext; do
rm -rf "$ext"
info "Removed VS Code extension: $(basename "$ext")"
FOUND_EXT=true
done < <(find "$dir" -maxdepth 1 \( -name "anthropic*" -o -name "claude-code*" \) -print0 2>/dev/null)
fi
done
for base in "$HOME/Library/Application Support/JetBrains"; do
if [[ -d "$base" ]]; then
while IFS= read -r -d '' ext; do
rm -rf "$ext"
info "Removed JetBrains plugin: $(basename "$ext")"
FOUND_EXT=true
done < <(find "$base" -maxdepth 4 \( -name "claude-code*" -o -name "ClaudeCode*" \) -print0 2>/dev/null)
fi
done
$FOUND_EXT || info "No IDE extensions found."
# ── Config & data ─────────────────────────────────────────────────────────────
header "Configuration..."
CONFIG_TARGETS=(
"$HOME/.claude"
"$HOME/.claude.json"
"$HOME/.config/claude"
"$HOME/Library/Application Support/claude-code"
"$HOME/Library/Application Support/Claude-3p"
"$HOME/Library/Caches/claude-code"
"$HOME/Library/Caches/claude-cli-nodejs"
"$HOME/Library/Caches/com.anthropic.claude"
"$HOME/Library/Logs/claude-code"
"$HOME/Library/Preferences/com.anthropic.claude-code.plist"
"$HOME/Library/Saved Application State/com.anthropic.claude-code.savedState"
"/Library/Application Support/claude-code"
"/Library/Application Support/Claude"
)
if $REMOVE_CONFIG; then
# Backup config dirs before purge
BACKUP_DIRS=()
[[ -d "$HOME/.claude" ]] && BACKUP_DIRS+=(-C "$HOME" .claude)
[[ -d "$HOME/.local/share/claude" ]] && BACKUP_DIRS+=(-C "$HOME" ".local/share/claude")
if ((${#BACKUP_DIRS[@]} > 0)); then
BACKUP="$HOME/claude-config-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
info "Backing up config / data to $BACKUP ..."
tar -czf "$BACKUP" "${BACKUP_DIRS[@]}"
success "Backup saved: $BACKUP"
fi
warn "Purging config and data..."
for path in "${CONFIG_TARGETS[@]}"; do
if [[ -e "$path" ]]; then
if rm -rf "$path" 2>/dev/null; then
info "Removed: $path"
else
warn "Permission denied: $path — try: sudo rm -rf \"$path\""
fi
fi
done
success "Config purged."
else
warn "Config kept. Re-run with --purge to also remove:"
for path in "${CONFIG_TARGETS[@]}"; do
[[ -e "$path" ]] && echo " $path"
done
fi
# ── Verify ────────────────────────────────────────────────────────────────────
header "Verification..."
if command -v claude &>/dev/null; then
warn "claude still found in PATH: $(command -v claude)"
warn "Possible shell alias, function, or PATH entry. Check with: type claude"
else
success "claude not found in PATH. Uninstall complete."
fi
echo ""
warn "You may also want to check your shell config files for leftover PATH entries:"
for rc in ~/.zshrc ~/.bashrc ~/.bash_profile ~/.zprofile; do
[[ -f "$rc" ]] || continue
if grep -nEq '\bclaude\b' "$rc" 2>/dev/null; then
echo " $rc -- references found"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment