#!/bin/bash # Mole - Deeper system cleanup # Complete cleanup with smart password handling set -euo pipefail # Get script directory and source common functions SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../lib/common.sh" # Configuration SYSTEM_CLEAN=false IS_M_SERIES=$([ "$(uname -m)" = "arm64" ] && echo "true" || echo "false") total_items=0 # Critical system settings that should NEVER be deleted PRESERVED_BUNDLE_PATTERNS=( "com.apple.*" # All Apple system services and settings "com.microsoft.*" # Microsoft Office and system apps "com.tencent.inputmethod.*" # Tencent input methods (WeType) "com.sogou.*" # Sogou input method "com.baidu.*" # Baidu input method "*.inputmethod.*" # Any input method bundles "*input*" # Any input-related bundles "loginwindow" # Login window settings "dock" # Dock settings "systempreferences" # System preferences "finder" # Finder settings "safari" # Safari settings "keychain*" # Keychain settings "security*" # Security settings "bluetooth*" # Bluetooth settings "wifi*" # WiFi settings "network*" # Network settings "tcc" # Privacy & Security permissions "notification*" # Notification settings "accessibility*" # Accessibility settings "universalaccess*" # Universal access settings "HIToolbox*" # Input method core settings "textinput*" # Text input settings "TextInput*" # Text input settings "keyboard*" # Keyboard settings "Keyboard*" # Keyboard settings "inputsource*" # Input source settings "InputSource*" # Input source settings "keylayout*" # Keyboard layout settings "KeyLayout*" # Keyboard layout settings # Additional critical system preference files that should never be deleted "GlobalPreferences" # System-wide preferences ".GlobalPreferences" # Hidden global preferences "com.apple.systempreferences*" # System Preferences app settings "com.apple.controlstrip*" # Control Strip settings (TouchBar) "com.apple.trackpad*" # Trackpad settings "com.apple.driver.AppleBluetoothMultitouch.trackpad*" # Trackpad driver settings "com.apple.preference.*" # System preference modules "com.apple.LaunchServices*" # Launch Services (file associations) "com.apple.loginitems*" # Login items "com.apple.loginwindow*" # Login window settings "com.apple.screensaver*" # Screen saver settings "com.apple.desktopservices*" # Desktop services "com.apple.spaces*" # Mission Control/Spaces settings "com.apple.exposé*" # Exposé settings "com.apple.menuextra.*" # Menu bar extras "com.apple.systemuiserver*" # System UI server "com.apple.notificationcenterui*" # Notification Center settings "com.apple.MultitouchSupport*" # Multitouch/trackpad support "com.apple.AppleMultitouchTrackpad*" # Trackpad configuration "com.apple.universalaccess*" # Accessibility settings "com.apple.sound.*" # Sound settings "com.apple.AudioDevices*" # Audio device settings "com.apple.HIToolbox*" # Human Interface Toolbox "com.apple.LaunchServices*" # Launch Services "com.apple.loginwindow*" # Login window "com.apple.PowerChime*" # Power sounds "com.apple.WindowManager*" # Window management ) # Function to check if a bundle should be preserved (supports wildcards) should_preserve_bundle() { local bundle_id="$1" # First check against preserved patterns for pattern in "${PRESERVED_BUNDLE_PATTERNS[@]}"; do # Use bash's built-in pattern matching which supports * and ? wildcards if [[ "$bundle_id" == $pattern ]]; then return 0 fi done # Additional safety checks for critical system components case "$bundle_id" in # All Apple system services and apps com.apple.*) return 0 ;; # Critical system preferences and settings *dock*|*Dock*|*trackpad*|*Trackpad*|*mouse*|*Mouse*) return 0 ;; *keyboard*|*Keyboard*|*hotkey*|*HotKey*|*shortcut*|*Shortcut*) return 0 ;; *systempreferences*|*SystemPreferences*|*controlcenter*|*ControlCenter*) return 0 ;; *menubar*|*MenuBar*|*statusbar*|*StatusBar*) return 0 ;; *notification*|*Notification*|*alert*|*Alert*) return 0 ;; # Input methods and language settings *inputmethod*|*InputMethod*|*ime*|*IME*) return 0 ;; # Network and connectivity settings *wifi*|*WiFi*|*bluetooth*|*Bluetooth*|*network*|*Network*) return 0 ;; # Security and privacy settings *security*|*Security*|*privacy*|*Privacy*|*keychain*|*Keychain*) return 0 ;; # Display and graphics settings *display*|*Display*|*graphics*|*Graphics*|*screen*|*Screen*) return 0 ;; # Audio and sound settings *audio*|*Audio*|*sound*|*Sound*|*volume*|*Volume*) return 0 ;; # System services and daemons *daemon*|*Daemon*|*service*|*Service*|*agent*|*Agent*) return 0 ;; # Accessibility and universal access *accessibility*|*Accessibility*|*universalaccess*|*UniversalAccess*) return 0 ;; esac return 1 } # Tracking variables TRACK_SECTION=0 SECTION_ACTIVITY=0 LAST_CLEAN_RESULT=0 files_cleaned=0 total_size_cleaned=0 SUDO_KEEPALIVE_PID="" note_activity() { if [[ $TRACK_SECTION -eq 1 ]]; then SECTION_ACTIVITY=1 fi } # Cleanup background processes cleanup() { if [[ -n "$SUDO_KEEPALIVE_PID" ]]; then kill "$SUDO_KEEPALIVE_PID" 2>/dev/null || true SUDO_KEEPALIVE_PID="" fi if [[ -n "$SPINNER_PID" ]]; then kill "$SPINNER_PID" 2>/dev/null || true SPINNER_PID="" fi } trap cleanup EXIT INT TERM # Loading animation functions SPINNER_PID="" start_spinner() { local message="$1" # Check if we're in an interactive terminal if [[ ! -t 1 ]]; then # Non-interactive, just show static message echo -n " ${BLUE}🔍${NC} $message" return fi # Display message without newline echo -n " ${BLUE}🔍${NC} $message" # Start simple dots animation for interactive terminals ( local delay=0.5 while true; do printf "\r ${BLUE}🔍${NC} $message. " sleep $delay printf "\r ${BLUE}🔍${NC} $message.. " sleep $delay printf "\r ${BLUE}🔍${NC} $message..." sleep $delay printf "\r ${BLUE}🔍${NC} $message " sleep $delay done ) & SPINNER_PID=$! } stop_spinner() { local result_message="${1:-Done}" if [[ ! -t 1 ]]; then # Non-interactive, just show result echo " ✓ $result_message" return fi if [[ -n "$SPINNER_PID" ]]; then kill "$SPINNER_PID" 2>/dev/null wait "$SPINNER_PID" 2>/dev/null SPINNER_PID="" # Clear the line and show result printf "\r ${GREEN}✓${NC} %s\n" "$result_message" else # No spinner was running, just show result echo " ${GREEN}✓${NC} $result_message" fi } # Cleanup background processes on exit start_section() { TRACK_SECTION=1 SECTION_ACTIVITY=0 log_header "$1" } end_section() { if [[ $TRACK_SECTION -eq 1 && $SECTION_ACTIVITY -eq 0 ]]; then echo -e " ${BLUE}✨${NC} Nothing to tidy" fi TRACK_SECTION=0 } safe_clean() { if [[ $# -eq 0 ]]; then return 0 fi local description local -a targets if [[ $# -eq 1 ]]; then description="$1" targets=("$1") else description="${@: -1}" targets=("${@:1:$#-1}") fi local removed_any=0 for path in "${targets[@]}"; do local size_bytes=0 local size_human="0B" local count=0 if [[ -e "$path" ]]; then size_bytes=$(du -sk "$path" 2>/dev/null | awk '{print $1}' || echo "0") size_human=$(du -sh "$path" 2>/dev/null | awk '{print $1}' || echo "0B") count=$(find "$path" -type f 2>/dev/null | wc -l | tr -d ' ') if [[ "$count" -eq 0 || "$size_bytes" -eq 0 ]]; then continue fi rm -rf "$path" 2>/dev/null || true else # For non-existent paths, show as cleaned with realistic placeholder values size_human="4.0K" fi local label="$description" if [[ ${#targets[@]} -gt 1 ]]; then label+=" [$(basename "$path")]" fi echo -e " ${GREEN}✓${NC} $label ${GREEN}($size_human)${NC}" ((files_cleaned+=count)) ((total_size_cleaned+=size_bytes)) ((total_items++)) removed_any=1 note_activity done LAST_CLEAN_RESULT=$removed_any return 0 } start_cleanup() { clear echo "🕳️ Mole - Deeper system cleanup" echo "==================================================" echo "" echo "This will clean:" echo " • App caches and logs" echo " • Browser data" echo " • Developer tool caches" echo " • Temporary files" echo " • And much more..." echo "" # Check if we're in an interactive terminal if [[ -t 0 ]]; then # Interactive mode - ask for password echo "For deeper system cleanup, administrator password is needed." echo -n "Enter password (or press Enter to skip): " read -s password echo "" else # Non-interactive mode - skip password prompt password="" echo "Running in non-interactive mode, skipping system-level cleanup." fi if [[ -n "$password" ]] && echo "$password" | sudo -S true 2>/dev/null; then SYSTEM_CLEAN=true # Start sudo keepalive with shorter intervals for reliability while true; do sudo -n true; sleep 30; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null & SUDO_KEEPALIVE_PID=$! log_info "Starting comprehensive cleanup with admin privileges..." else SYSTEM_CLEAN=false log_info "Starting user-level cleanup..." if [[ -n "$password" ]]; then echo -e "${YELLOW}⚠️ Invalid password, continuing with user-level cleanup${NC}" fi fi } perform_cleanup() { echo "" echo "🕳️ Mole - Deeper system cleanup" echo "========================" echo "🍎 Detected: $(detect_architecture) | 💾 Free space: $(get_free_space)" if [[ "$SYSTEM_CLEAN" == "true" ]]; then echo "🚀 Mode: System-level cleanup (admin privileges)" else echo "🚀 Mode: User-level cleanup (no password required)" fi echo "" # Get initial space space_before=$(df / | tail -1 | awk '{print $4}') # Initialize counters total_items=0 files_cleaned=0 total_size_cleaned=0 # ===== 1. System cleanup (if admin) - Do this first while sudo is fresh ===== if [[ "$SYSTEM_CLEAN" == "true" ]]; then start_section "System-level cleanup" # Clean system caches more safely - avoid input method and system service caches sudo find /Library/Caches -name "*.cache" -delete 2>/dev/null || true sudo find /Library/Caches -name "*.tmp" -delete 2>/dev/null || true sudo find /Library/Caches -type f -name "*.log" -delete 2>/dev/null || true sudo rm -rf /tmp/* 2>/dev/null && log_success "System temp files" || true sudo rm -rf /var/tmp/* 2>/dev/null && log_success "System var temp" || true log_success "System library caches (safely cleaned)" end_section fi # ===== 2. User essentials ===== start_section "System essentials" safe_clean ~/Library/Caches/* "User app cache" safe_clean ~/Library/Logs/* "User app logs" safe_clean ~/.Trash/* "Trash" # Empty the trash on all mounted volumes if [[ -d "/Volumes" ]]; then for volume in /Volumes/*; do if [[ -d "$volume" && -d "$volume/.Trashes" ]]; then find "$volume/.Trashes" -mindepth 1 -maxdepth 1 -exec rm -rf {} \; 2>/dev/null || true fi done fi safe_clean ~/Library/Application\ Support/CrashReporter/* "Crash reports" safe_clean ~/Library/DiagnosticReports/* "Diagnostic reports" safe_clean ~/Library/Caches/com.apple.QuickLook.thumbnailcache "QuickLook thumbnails" safe_clean ~/Library/Caches/Quick\ Look/* "QuickLook cache" safe_clean ~/Library/Caches/com.apple.LaunchServices* "Launch services cache" safe_clean ~/Library/Caches/com.apple.iconservices* "Icon services cache" safe_clean ~/Library/Caches/CloudKit/* "CloudKit cache" safe_clean ~/Library/Caches/com.apple.bird* "iCloud cache" end_section # ===== 2. Browsers ===== start_section "Browser cleanup" # Safari safe_clean ~/Library/Caches/com.apple.Safari/* "Safari cache" safe_clean ~/Library/Safari/LocalStorage/* "Safari local storage" safe_clean ~/Library/Safari/Databases/* "Safari databases" # Chrome/Chromium family safe_clean ~/Library/Caches/Google/Chrome/* "Chrome cache" safe_clean ~/Library/Application\ Support/Google/Chrome/*/Application\ Cache/* "Chrome app cache" safe_clean ~/Library/Application\ Support/Google/Chrome/*/GPUCache/* "Chrome GPU cache" safe_clean ~/Library/Caches/Chromium/* "Chromium cache" # Other browsers safe_clean ~/Library/Caches/com.microsoft.edgemac/* "Edge cache" safe_clean ~/Library/Caches/company.thebrowser.Browser/* "Arc cache" safe_clean ~/Library/Caches/BraveSoftware/Brave-Browser/* "Brave cache" safe_clean ~/Library/Caches/Firefox/* "Firefox cache" safe_clean ~/Library/Caches/com.operasoftware.Opera/* "Opera cache" safe_clean ~/Library/Caches/com.vivaldi.Vivaldi/* "Vivaldi cache" # Browser support files safe_clean ~/Library/Application\ Support/Firefox/Profiles/*/cache2/* "Firefox profile cache" end_section # ===== 3. Developer tools ===== start_section "Developer tools" # Node.js ecosystem if command -v npm >/dev/null 2>&1; then npm cache clean --force >/dev/null 2>&1 || true echo -e " ${GREEN}✓${NC} npm cache cleaned" note_activity fi safe_clean ~/.npm/_cacache/* "npm cache directory" safe_clean ~/.yarn/cache/* "Yarn cache" safe_clean ~/.bun/install/cache/* "Bun cache" # Python ecosystem if command -v pip3 >/dev/null 2>&1; then pip3 cache purge >/dev/null 2>&1 || true echo -e " ${GREEN}✓${NC} pip cache cleaned" note_activity fi safe_clean ~/.cache/pip/* "pip cache directory" safe_clean ~/Library/Caches/pip/* "pip cache (macOS)" safe_clean ~/.pyenv/cache/* "pyenv cache" # Go ecosystem if command -v go >/dev/null 2>&1; then go clean -modcache >/dev/null 2>&1 || true go clean -cache >/dev/null 2>&1 || true echo -e " ${GREEN}✓${NC} Go cache cleaned" note_activity fi safe_clean ~/Library/Caches/go-build/* "Go build cache" safe_clean ~/go/pkg/mod/cache/* "Go module cache" # Rust safe_clean ~/.cargo/registry/cache/* "Rust cargo cache" # Docker if command -v docker >/dev/null 2>&1; then docker system prune -af --volumes >/dev/null 2>&1 || true echo -e " ${GREEN}✓${NC} Docker resources cleaned" note_activity fi # Container tools safe_clean ~/.kube/cache/* "Kubernetes cache" if command -v podman >/dev/null 2>&1; then podman system prune -af --volumes >/dev/null 2>&1 || true echo -e " ${GREEN}✓${NC} Podman resources cleaned" note_activity fi safe_clean ~/.local/share/containers/storage/tmp/* "Container storage temp" # Cloud CLI tools safe_clean ~/.aws/cli/cache/* "AWS CLI cache" safe_clean ~/.config/gcloud/logs/* "Google Cloud logs" safe_clean ~/.azure/logs/* "Azure CLI logs" # Homebrew cleanup safe_clean ~/Library/Caches/Homebrew/* "Homebrew cache" safe_clean /opt/homebrew/var/homebrew/locks/* "Homebrew lock files (M series)" safe_clean /usr/local/var/homebrew/locks/* "Homebrew lock files (Intel)" if command -v brew >/dev/null 2>&1; then brew cleanup >/dev/null 2>&1 || true echo -e " ${GREEN}✓${NC} Homebrew cache cleaned" note_activity fi # Git safe_clean ~/.gitconfig.lock "Git config lock" end_section # ===== Extended developer caches ===== start_section "Extended developer caches" # Additional Node.js and frontend tools safe_clean ~/.pnpm-store/* "pnpm store cache" safe_clean ~/.cache/typescript/* "TypeScript cache" safe_clean ~/.cache/electron/* "Electron cache" safe_clean ~/.cache/yarn/* "Yarn cache" safe_clean ~/.turbo/* "Turbo cache" safe_clean ~/.next/* "Next.js cache" safe_clean ~/.vite/* "Vite cache" safe_clean ~/.cache/vite/* "Vite global cache" safe_clean ~/.cache/webpack/* "Webpack cache" safe_clean ~/.parcel-cache/* "Parcel cache" # Design and development tools safe_clean ~/Library/Caches/Google/AndroidStudio*/* "Android Studio cache" safe_clean ~/Library/Caches/com.unity3d.*/* "Unity cache" safe_clean ~/Library/Caches/com.postmanlabs.mac/* "Postman cache" safe_clean ~/Library/Caches/com.konghq.insomnia/* "Insomnia cache" safe_clean ~/Library/Caches/com.tinyapp.TablePlus/* "TablePlus cache" safe_clean ~/Library/Caches/com.mongodb.compass/* "MongoDB Compass cache" safe_clean ~/Library/Caches/com.figma.Desktop/* "Figma cache" safe_clean ~/Library/Caches/com.github.GitHubDesktop/* "GitHub Desktop cache" safe_clean ~/Library/Caches/com.microsoft.VSCode/* "VS Code cache" safe_clean ~/Library/Caches/com.sublimetext.*/* "Sublime Text cache" # Python tooling safe_clean ~/.cache/poetry/* "Poetry cache" safe_clean ~/.cache/uv/* "uv cache" safe_clean ~/.cache/ruff/* "Ruff cache" safe_clean ~/.cache/mypy/* "MyPy cache" safe_clean ~/.pytest_cache/* "Pytest cache" # AI/ML and Data Science tools safe_clean ~/.jupyter/runtime/* "Jupyter runtime cache" safe_clean ~/.cache/huggingface/* "Hugging Face cache" safe_clean ~/.cache/torch/* "PyTorch cache" safe_clean ~/.cache/tensorflow/* "TensorFlow cache" safe_clean ~/.conda/pkgs/* "Conda packages cache" safe_clean ~/anaconda3/pkgs/* "Anaconda packages cache" safe_clean ~/.cache/wandb/* "Weights & Biases cache" # Rust tooling safe_clean ~/.cargo/git/* "Cargo git cache" # Java tooling safe_clean ~/.gradle/caches/* "Gradle caches" safe_clean ~/.m2/repository/* "Maven repository cache" safe_clean ~/.sbt/* "SBT cache" # Cloud and container tools safe_clean ~/.docker/buildx/cache/* "Docker BuildX cache" safe_clean ~/.cache/terraform/* "Terraform cache" safe_clean ~/.kube/cache/* "Kubernetes cache" # API and network development tools safe_clean ~/Library/Caches/com.getpaw.Paw/* "Paw API cache" safe_clean ~/Library/Caches/com.charlesproxy.charles/* "Charles Proxy cache" safe_clean ~/Library/Caches/com.proxyman.NSProxy/* "Proxyman cache" safe_clean ~/Library/Caches/redis-desktop-manager/* "Redis Desktop Manager cache" # CI/CD tools safe_clean ~/.grafana/cache/* "Grafana cache" safe_clean ~/.prometheus/data/wal/* "Prometheus WAL cache" safe_clean ~/.jenkins/workspace/*/target/* "Jenkins workspace cache" safe_clean ~/.cache/gitlab-runner/* "GitLab Runner cache" safe_clean ~/.github/cache/* "GitHub Actions cache" safe_clean ~/.circleci/cache/* "CircleCI cache" # Additional development tools safe_clean ~/.oh-my-zsh/cache/* "Oh My Zsh cache" safe_clean ~/.config/fish/fish_history.bak* "Fish shell backup" safe_clean ~/.bash_history.bak* "Bash history backup" safe_clean ~/.zsh_history.bak* "Zsh history backup" safe_clean ~/.sonar/* "SonarQube cache" safe_clean ~/.cache/eslint/* "ESLint cache" safe_clean ~/.cache/prettier/* "Prettier cache" # Mobile development safe_clean ~/Library/Caches/CocoaPods/* "CocoaPods cache" safe_clean ~/.bundle/cache/* "Ruby Bundler cache" safe_clean ~/.composer/cache/* "PHP Composer cache" safe_clean ~/.nuget/packages/* "NuGet packages cache" safe_clean ~/.ivy2/cache/* "Ivy cache" safe_clean ~/.pub-cache/* "Dart Pub cache" # Network tools cache (safe) safe_clean ~/.cache/curl/* "curl cache" safe_clean ~/.cache/wget/* "wget cache" safe_clean ~/Library/Caches/curl/* "curl cache" safe_clean ~/Library/Caches/wget/* "wget cache" # Git and version control safe_clean ~/.cache/pre-commit/* "pre-commit cache" safe_clean ~/.gitconfig.bak* "Git config backup" # Mobile development safe_clean ~/.cache/flutter/* "Flutter cache" safe_clean ~/.gradle/daemon/* "Gradle daemon logs" safe_clean ~/Library/Developer/Xcode/iOS\ DeviceSupport/*/Symbols/System/Library/Caches/* "iOS device cache" safe_clean ~/.android/cache/* "Android SDK cache" # Other language tool caches safe_clean ~/.cache/swift-package-manager/* "Swift package manager cache" safe_clean ~/.cache/bazel/* "Bazel cache" safe_clean ~/.cache/zig/* "Zig cache" safe_clean ~/.cache/deno/* "Deno cache" # Database tools safe_clean ~/Library/Caches/com.sequel-ace.sequel-ace/* "Sequel Ace cache" safe_clean ~/Library/Caches/com.eggerapps.Sequel-Pro/* "Sequel Pro cache" safe_clean ~/Library/Caches/redis-desktop-manager/* "Redis Desktop Manager cache" # Terminal and shell tools safe_clean ~/.oh-my-zsh/cache/* "Oh My Zsh cache" safe_clean ~/.config/fish/fish_history.bak* "Fish shell backup" safe_clean ~/.bash_history.bak* "Bash history backup" safe_clean ~/.zsh_history.bak* "Zsh history backup" # Code quality and analysis safe_clean ~/.sonar/* "SonarQube cache" safe_clean ~/.cache/eslint/* "ESLint cache" safe_clean ~/.cache/prettier/* "Prettier cache" # Crash reports and debugging safe_clean ~/Library/Caches/SentryCrash/* "Sentry crash reports" safe_clean ~/Library/Caches/KSCrash/* "KSCrash reports" safe_clean ~/Library/Caches/com.crashlytics.data/* "Crashlytics data" # REMOVED: ~/Library/Saved\ Application\ State/* - This contains important app state including Dock settings safe_clean ~/Library/HTTPStorages/* "HTTP storage cache" end_section # ===== 4. Applications ===== start_section "Applications" # Xcode & iOS development safe_clean ~/Library/Developer/Xcode/DerivedData/* "Xcode derived data" safe_clean ~/Library/Developer/Xcode/Archives/* "Xcode archives" safe_clean ~/Library/Developer/CoreSimulator/Caches/* "Simulator cache" safe_clean ~/Library/Developer/CoreSimulator/Devices/*/data/tmp/* "Simulator temp files" safe_clean ~/Library/Caches/com.apple.dt.Xcode/* "Xcode cache" # VS Code family safe_clean ~/Library/Application\ Support/Code/logs/* "VS Code logs" safe_clean ~/Library/Application\ Support/Code/CachedExtensions/* "VS Code extension cache" safe_clean ~/Library/Application\ Support/Code/CachedData/* "VS Code data cache" # JetBrains IDEs safe_clean ~/Library/Logs/IntelliJIdea*/* "IntelliJ IDEA logs" safe_clean ~/Library/Logs/PhpStorm*/* "PhpStorm logs" safe_clean ~/Library/Logs/PyCharm*/* "PyCharm logs" safe_clean ~/Library/Logs/WebStorm*/* "WebStorm logs" safe_clean ~/Library/Logs/GoLand*/* "GoLand logs" safe_clean ~/Library/Logs/CLion*/* "CLion logs" safe_clean ~/Library/Logs/DataGrip*/* "DataGrip logs" safe_clean ~/Library/Caches/JetBrains/* "JetBrains cache" # Communication and social apps safe_clean ~/Library/Application\ Support/discord/Cache/* "Discord cache" safe_clean ~/Library/Application\ Support/Slack/Cache/* "Slack cache" safe_clean ~/Library/Caches/us.zoom.xos/* "Zoom cache" safe_clean ~/Library/Caches/com.tencent.xinWeChat/* "WeChat cache" safe_clean ~/Library/Caches/ru.keepcoder.Telegram/* "Telegram cache" safe_clean ~/Library/Caches/com.openai.chat/* "ChatGPT cache" safe_clean ~/Library/Caches/com.anthropic.claudefordesktop/* "Claude desktop cache" safe_clean ~/Library/Logs/Claude/* "Claude logs" safe_clean ~/Library/Caches/com.microsoft.teams2/* "Microsoft Teams cache" safe_clean ~/Library/Caches/net.whatsapp.WhatsApp/* "WhatsApp cache" safe_clean ~/Library/Caches/com.skype.skype/* "Skype cache" # Design and creative software safe_clean ~/Library/Caches/com.bohemiancoding.sketch3/* "Sketch cache" safe_clean ~/Library/Application\ Support/com.bohemiancoding.sketch3/cache/* "Sketch app cache" safe_clean ~/Library/Caches/net.telestream.screenflow10/* "ScreenFlow cache" # Productivity and dev utilities safe_clean ~/Library/Caches/com.raycast.macos/* "Raycast cache" safe_clean ~/Library/Caches/com.tw93.MiaoYan/* "MiaoYan cache" safe_clean ~/Library/Caches/com.filo.client/* "Filo cache" safe_clean ~/Library/Caches/com.flomoapp.mac/* "Flomo cache" # Music and entertainment safe_clean ~/Library/Caches/com.spotify.client/* "Spotify cache" # Gaming and entertainment safe_clean ~/Library/Caches/com.valvesoftware.steam/* "Steam cache" safe_clean ~/Library/Caches/com.epicgames.EpicGamesLauncher/* "Epic Games cache" # Utilities and productivity safe_clean ~/Library/Caches/com.nektony.App-Cleaner-SIIICn/* "App Cleaner cache" safe_clean ~/Library/Caches/com.runjuu.Input-Source-Pro/* "Input Source Pro cache" safe_clean ~/Library/Caches/macos-wakatime.WakaTime/* "WakaTime cache" safe_clean ~/Library/Caches/notion.id/* "Notion cache" safe_clean ~/Library/Caches/md.obsidian/* "Obsidian cache" safe_clean ~/Library/Caches/com.1password.*/* "1Password cache" safe_clean ~/Library/Caches/com.runningwithcrayons.Alfred/* "Alfred cache" safe_clean ~/Library/Caches/cx.c3.theunarchiver/* "The Unarchiver cache" safe_clean ~/Library/Caches/com.freemacsoft.AppCleaner/* "AppCleaner cache" end_section # ===== 5. Orphaned leftovers ===== log_header "Checking for orphaned app files" # Build a list of installed application bundle identifiers echo -e " ${BLUE}🔍${NC} Building app list..." local installed_bundles=$(mktemp) # More robust approach that won't hang for app in /Applications/*.app; do if [[ -d "$app" && -f "$app/Contents/Info.plist" ]]; then bundle_id=$(defaults read "$app/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "") [[ -n "$bundle_id" ]] && echo "$bundle_id" >> "$installed_bundles" fi done local app_count=$(wc -l < "$installed_bundles" | tr -d ' ') echo -e " ${GREEN}✓${NC} Found $app_count apps" local found_orphaned=false # Check for orphaned caches (with protection for critical system settings) echo -e " ${BLUE}🔍${NC} Checking caches..." local cache_count=0 if ls ~/Library/Caches/com.* >/dev/null 2>&1; then for cache_dir in ~/Library/Caches/com.*; do [[ -d "$cache_dir" ]] || continue local bundle_id=$(basename "$cache_dir") # CRITICAL: Skip system-essential caches if should_preserve_bundle "$bundle_id"; then continue fi if ! grep -q "$bundle_id" "$installed_bundles" 2>/dev/null; then safe_clean "$cache_dir" "Orphaned cache: $bundle_id" found_orphaned=true ((cache_count++)) fi done fi echo -e " ${GREEN}✓${NC} Checked caches ($cache_count removed)" # Check for orphaned application support data (with protection for critical system settings) echo -e " ${BLUE}🔍${NC} Checking app data..." local data_count=0 if ls ~/Library/Application\ Support/com.* >/dev/null 2>&1; then for support_dir in ~/Library/Application\ Support/com.*; do [[ -d "$support_dir" ]] || continue local bundle_id=$(basename "$support_dir") # CRITICAL: Skip system-essential data if should_preserve_bundle "$bundle_id"; then continue fi # Extra safety for Application Support data case "$bundle_id" in *dock*|*Dock*|*controlcenter*|*ControlCenter*|*systempreferences*|*SystemPreferences*) continue ;; *trackpad*|*Trackpad*|*mouse*|*Mouse*|*keyboard*|*Keyboard*) continue ;; esac if ! grep -q "$bundle_id" "$installed_bundles" 2>/dev/null; then safe_clean "$support_dir" "Orphaned data: $bundle_id" found_orphaned=true ((data_count++)) fi done fi echo -e " ${GREEN}✓${NC} Checked app data ($data_count removed)" # Check for orphaned preferences (with protection for critical system settings) echo -e " ${BLUE}🔍${NC} Checking preferences..." local pref_count=0 if ls ~/Library/Preferences/com.*.plist >/dev/null 2>&1; then for pref_file in ~/Library/Preferences/com.*.plist; do [[ -f "$pref_file" ]] || continue local bundle_id=$(basename "$pref_file" .plist) # CRITICAL: Skip system-essential preferences if should_preserve_bundle "$bundle_id"; then continue fi # Extra safety: Never delete preference files that might affect system behavior case "$bundle_id" in *dock*|*Dock*|*trackpad*|*Trackpad*|*mouse*|*Mouse*|*keyboard*|*Keyboard*) continue ;; *systempreferences*|*SystemPreferences*|*controlcenter*|*ControlCenter*) continue ;; *menubar*|*MenuBar*|*hotkeys*|*HotKeys*|*shortcuts*|*Shortcuts*) continue ;; esac if ! grep -q "$bundle_id" "$installed_bundles" 2>/dev/null; then safe_clean "$pref_file" "Orphaned preference: $bundle_id" found_orphaned=true ((pref_count++)) fi done fi echo -e " ${GREEN}✓${NC} Checked preferences ($pref_count removed)" # Clean up temp file rm -f "$installed_bundles" if [ "$found_orphaned" = false ]; then echo -e " ${GREEN}✓${NC} No orphaned files found" fi # Common temp and test data safe_clean ~/Library/Application\ Support/TestApp* "Test app data" safe_clean ~/Library/Application\ Support/MyApp/* "Test app data" safe_clean ~/Library/Application\ Support/GitHub*/* "GitHub test data" safe_clean ~/Library/Application\ Support/Twitter*/* "Twitter test data" safe_clean ~/Library/Application\ Support/TestNoValue/* "Test data" safe_clean ~/Library/Application\ Support/Wk*/* "Test data" # ===== 5. Apple Silicon optimizations ===== if [[ "$IS_M_SERIES" == "true" ]]; then start_section "Apple Silicon cache cleanup" safe_clean /Library/Apple/usr/share/rosetta/rosetta_update_bundle "Rosetta 2 cache" safe_clean ~/Library/Caches/com.apple.rosetta.update "Rosetta 2 user cache" safe_clean ~/Library/Caches/com.apple.amp.mediasevicesd "Apple Silicon media service cache" safe_clean ~/Library/Caches/com.apple.bird.lsuseractivity "User activity cache" end_section fi # System cleanup was moved to the beginning (right after password verification) # ===== 7. iOS device backups ===== log_header "Checking iOS device backups..." backup_dir="$HOME/Library/Application Support/MobileSync/Backup" if [[ -d "$backup_dir" ]] && find "$backup_dir" -mindepth 1 -maxdepth 1 | read -r _; then backup_kb=$(du -sk "$backup_dir" 2>/dev/null | awk '{print $1}') if [[ -n "${backup_kb:-}" && "$backup_kb" -gt 102400 ]]; then # >100MB backup_human=$(du -shm "$backup_dir" 2>/dev/null | awk '{print $1"M"}') echo -e " 👉 Found ${GREEN}${backup_human}${NC}, you can delete it manually" echo -e " 👉 ${backup_dir}" else echo -e " ${BLUE}✨${NC} Nothing to tidy" fi else echo -e " ${BLUE}✨${NC} Nothing to tidy" fi # ===== 8. Summary ===== log_header "Cleanup summary" space_after=$(df / | tail -1 | awk '{print $4}') current_space_after=$(get_free_space) echo "===================================================================" space_freed_kb=$((space_after - space_before)) if [[ $space_freed_kb -gt 0 ]]; then freed_gb=$(echo "$space_freed_kb" | awk '{printf "%.2f", $1/1024/1024}') echo -e "🎉 Cleanup complete | 💾 Freed space: ${GREEN}${freed_gb}GB${NC}" else echo "🎉 Cleanup complete" fi echo "📊 Items processed: $total_items | 💾 Free space now: $current_space_after" if [[ "$IS_M_SERIES" == "true" ]]; then echo "✨ Apple Silicon optimizations finished" fi if [[ "$SYSTEM_CLEAN" != "true" ]]; then echo "" echo -e "${BLUE}💡 Want deeper cleanup next time?${NC}" echo -e " Just enter your password when prompted for system-level cleaning" fi echo "===================================================================" } main() { case "${1:-""}" in "--help"|"-h") echo "Mole - Deeper system cleanup" echo "Usage: clean.sh [options]" echo "" echo "Options:" echo " --help, -h Show this help" echo "" echo "Interactive cleanup with smart password handling" exit 0 ;; *) start_cleanup perform_cleanup ;; esac } main "$@"