1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 11:31:46 +00:00

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
This commit is contained in:
Tw93
2025-09-23 14:32:12 +08:00
commit 6402ac3f4a
6 changed files with 1112 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

30
Formula/clean-mac.rb Normal file
View File

@@ -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

21
LICENSE Normal file
View File

@@ -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.

141
README.md Normal file
View File

@@ -0,0 +1,141 @@
<div align="center">
<img src="https://gw.alipayobjects.com/zos/k/gj/clean.svg" alt="Clean Mac" width="120" height="120"/>
# 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)
</div>
---
## 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 |
<table>
<tr>
<td width="50%">
**🌐 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
</td>
<td width="50%">
**📱 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
</td>
</tr>
</table>
## 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 <a href="https://miaoyan.app/cats.html?name=CleanMac" target="_blank">feed them canned food 🥩🍤</a>
## License
MIT License © [tw93](https://github.com/tw93) - Feel free to enjoy and contribute to open source

729
clean.sh Executable file
View File

@@ -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 "==================================================================="

191
install.sh Executable file
View File

@@ -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