Files
unlimitedcoding/codex/ucodex_uninstall.sh
delta-cloud-208e dd11b9784d fix(uninstall): MANDATORY tar backup in ALL modes (safe/settings-only/full)
Per user demand after data loss incident: never trust mode flags alone.
Previously only `full` mode created tar.gz backup. Now `safe` and
`settings-only` also create full tar.gz of ~/.claude (resp .codex,
.gemini, .qwen) BEFORE any mutation. If backup fails, refuse to
proceed for that user — skip to next.

Restore is always one command:
  tar -xzf ~/.<tool>.uninstall-backup.<TS>.tar.gz -C ~

Applies to all 4 scripts: uclaude, ucodex, ugemini, uqwen.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-26 07:17:34 +00:00

214 lines
6.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Codex CLI — Uninstaller
# Removes Codex CLI binary, config, env vars.
#
# Usage: sudo bash ucodex_uninstall.sh
set -euo pipefail
# ---- Interactive mode select (post user-data-loss incident) ----
# Modes:
# safe (default) — remove binary + settings, KEEP user data
# settings-only — clear settings only, keep binary + user data
# full — wipe everything (with tar backup first)
MODE="${UCODEX_MODE:-}"
ASSUME_YES="${UCLAUDE_YES:-0}"
TIMESTAMP=$(date +%Y%m%d%H%M%S)
inventory_user_dirs_codex() {
for user_home in /root /home/*; do
local d="$user_home/.codex"
[ -d "$d" ] || continue
local size_kb
size_kb=$(du -sk "$d" 2>/dev/null | awk '{print $1}')
echo " $d ($((size_kb / 1024)) MB)"
done
}
if [ -z "$MODE" ] && [ "$ASSUME_YES" != "1" ]; then
echo
echo "What to uninstall Codex CLI?"
echo " 1) safe — remove binary + settings, KEEP user data (recommended)"
echo " 2) settings-only — only clear settings, keep binary + user data"
echo " 3) full — wipe everything (tar backup created first)"
echo " 4) cancel"
echo
echo "Your data right now:"
inventory_user_dirs_codex
echo
while true; do
read -r -p "Choose [1/2/3/4] (default 1=safe): " choice
case "${choice:-1}" in
1|safe) MODE="safe"; break ;;
2|settings-only) MODE="settings-only"; break ;;
3|full)
echo "WARNING: full mode DESTROYS all Codex CLI user data."
read -r -p "Type 'WIPE' to confirm: " confirm
[ "$confirm" = "WIPE" ] && MODE="full" && break
echo "Confirmation failed, pick again." ;;
4|cancel|q|exit) echo "Cancelled."; exit 0 ;;
*) echo "Invalid — pick 1/2/3/4." ;;
esac
done
elif [ -z "$MODE" ]; then
MODE="safe"
fi
echo "Mode: $MODE"
OS="$(uname -s)"
IS_MACOS=false
[ "$OS" = "Darwin" ] && IS_MACOS=true
# Cross-platform sed -i
sedi() {
if $IS_MACOS; then
sed -i '' "$@"
else
sed -i "$@"
fi
}
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} $*"; }
echo -e "${BOLD}"
echo " +--------------------------------------+"
echo " | Codex CLI — Uninstaller |"
echo " +--------------------------------------+"
echo -e "${RESET}"
# ---- Remove binary ----
CODEX_PATH=$(command -v codex 2>/dev/null || echo "")
if [ -n "$CODEX_PATH" ]; then
info "Removing wrapper: $CODEX_PATH"
rm -f "$CODEX_PATH"
log "Wrapper removed"
else
warn "Codex wrapper not found in PATH"
fi
# Also remove the hidden binary
if [ -f "/usr/local/bin/.codex-bin" ]; then
info "Removing binary: /usr/local/bin/.codex-bin"
rm -f "/usr/local/bin/.codex-bin"
log "Binary removed"
fi
# ---- Determine user home directories ----
if $IS_MACOS; then
_home_dirs=(/Users/*)
else
_home_dirs=(/root /home/*)
fi
# ---- Remove config ----
for user_home in "${_home_dirs[@]}"; do
CODEX_DIR="$user_home/.codex"
if [ -d "$CODEX_DIR" ]; then
# ALWAYS create full tar backup BEFORE any destructive op, in EVERY mode.
# Per user demand after data loss incident: never trust mode flags alone.
FULL_BAK="$user_home/.codex.uninstall-backup.$TIMESTAMP.tar.gz"
echo " Creating safety backup: $FULL_BAK ..."
if ! tar -czf "$FULL_BAK" -C "$user_home" .codex 2>/dev/null; then
echo " ERROR: backup FAILED for $CODEX_DIR — REFUSING to proceed (data preserved)"
continue
fi
echo " Safety backup: $FULL_BAK ($(du -h "$FULL_BAK" 2>/dev/null | awk '{print $1}'))"
echo " Restore anytime: tar -xzf $FULL_BAK -C $user_home"
# PRESERVE user data by default. See uclaude_uninstall.sh history.
case "${MODE:-safe}" in
safe)
# Remove only managed config files, keep everything else
for f in settings.json config.toml config.yaml; do
if [ -f "$user_home/.codex/$f" ]; then
cp -p "$user_home/.codex/$f" "$user_home/.codex/$f.uninstall.bak.$TIMESTAMP"
rm -f "$user_home/.codex/$f"
echo " Removed $user_home/.codex/$f (backup: $f.uninstall.bak.$TIMESTAMP)"
fi
done
echo " PRESERVED user data in $user_home/.codex"
;;
settings-only)
for f in settings.json config.toml config.yaml; do
if [ -f "$user_home/.codex/$f" ]; then
cp -p "$user_home/.codex/$f" "$user_home/.codex/$f.uninstall.bak.$TIMESTAMP"
rm -f "$user_home/.codex/$f"
fi
done
;;
full)
rm -rf "$user_home/.codex"
echo " Removed $user_home/.codex (full wipe)"
;;
esac
fi
done
# ---- Remove env vars from shell rc files ----
for user_home in "${_home_dirs[@]}"; do
for rc_file in "$user_home/.bashrc" "$user_home/.zshrc"; do
if [ -f "$rc_file" ] && grep -q 'OPENAI_API_KEY\|OPENAI_BASE_URL\|Codex' "$rc_file" 2>/dev/null; then
info "Cleaning env vars from $rc_file..."
sedi '/# Codex/d' "$rc_file"
sedi '/# UnlimitedCoding.*[Cc]odex/d' "$rc_file"
sedi '/OPENAI_API_KEY/d' "$rc_file"
sedi '/OPENAI_BASE_URL/d' "$rc_file"
log "Cleaned $rc_file"
fi
done
done
# ---- Remove env vars from /etc/environment ----
if [ -f "/etc/environment" ] && grep -q 'OPENAI_API_KEY\|OPENAI_BASE_URL' /etc/environment 2>/dev/null; then
info "Cleaning /etc/environment..."
sedi '/OPENAI_API_KEY/d' /etc/environment
sedi '/OPENAI_BASE_URL/d' /etc/environment
log "Cleaned /etc/environment"
fi
# ---- Remove env file and profile.d scripts ----
for envf in "/etc/profile.d/codex-cli.sh" "/etc/profile.d/codex-env.sh" "/etc/codex-env.sh"; do
if [ -f "$envf" ]; then
rm -f "$envf"
log "Removed $envf"
fi
done
# ---- macOS: unset launchctl env vars ----
if $IS_MACOS; then
launchctl unsetenv OPENAI_API_KEY 2>/dev/null || true
launchctl unsetenv OPENAI_BASE_URL 2>/dev/null || true
log "Unset launchctl env vars"
fi
# ---- Clean codex-env.sh source lines from rc files ----
for user_home in "${_home_dirs[@]}"; do
for rc_file in "$user_home/.bashrc" "$user_home/.zshrc"; do
if [ -f "$rc_file" ] && grep -q 'codex-env\.sh' "$rc_file" 2>/dev/null; then
sedi '/codex-env\.sh/d' "$rc_file"
log "Cleaned codex-env source from $rc_file"
fi
done
done
echo ""
echo -e "${GREEN}${BOLD} Codex CLI fully uninstalled!${RESET}"
echo ""