#!/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 ""