@@ -10,6 +10,7 @@ set -euo pipefail
# MOLE_MAIL_AGE_DAYS: Minimum age in days for Mail attachments to be cleaned (default: 30)
readonly MOLE_TM_THIN_TIMEOUT = 180
readonly MOLE_TM_THIN_VALUE = 9999999999
readonly MOLE_SQLITE_MAX_SIZE = 104857600 # 100MB
# Helper function to get appropriate icon and color for dry-run mode
opt_msg( ) {
@@ -36,6 +37,60 @@ run_launchctl_unload() {
fi
}
needs_permissions_repair( ) {
local owner
owner = $( stat -f %Su " $HOME " 2> /dev/null || echo "" )
if [ [ -n " $owner " && " $owner " != " $USER " ] ] ; then
return 0
fi
local -a paths = (
" $HOME "
" $HOME /Library "
" $HOME /Library/Preferences "
)
local path
for path in " ${ paths [@] } " ; do
if [ [ -e " $path " && ! -w " $path " ] ] ; then
return 0
fi
done
return 1
}
has_bluetooth_hid_connected( ) {
local bt_report
bt_report = $( system_profiler SPBluetoothDataType 2> /dev/null || echo "" )
if ! echo " $bt_report " | grep -q "Connected: Yes" ; then
return 1
fi
if echo " $bt_report " | grep -Eiq "Keyboard|Trackpad|Mouse|HID" ; then
return 0
fi
return 1
}
is_ac_power( ) {
pmset -g batt 2> /dev/null | grep -q "AC Power"
}
is_memory_pressure_high( ) {
if ! command -v memory_pressure > /dev/null 2>& 1; then
return 1
fi
local mp_output
mp_output = $( memory_pressure -Q 2> /dev/null || echo "" )
if echo " $mp_output " | grep -Eiq "warning|critical" ; then
return 0
fi
return 1
}
flush_dns_cache( ) {
# Skip actual flush in dry-run mode
if [ [ " ${ MOLE_DRY_RUN :- 0 } " = = "1" ] ] ; then
@@ -148,7 +203,7 @@ opt_network_optimization() {
# Compresses and optimizes SQLite databases for Mail, Messages, Safari
opt_sqlite_vacuum( ) {
if ! command -v sqlite3 > /dev/null 2>& 1; then
echo -e " ${ GRAY } - ${ NC } sqlite3 not available, skipping database optimization "
echo -e " ${ GRAY } - ${ NC } Database optimization already optimal (sqlite3 unavailable) "
return 0
fi
@@ -166,6 +221,13 @@ opt_sqlite_vacuum() {
return 0
fi
local spinner_started = "false"
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" && -t 1 ] ] ; then
MOLE_SPINNER_PREFIX = " " start_inline_spinner "Optimizing databases..."
spinner_started = "true"
trap '[[ "${spinner_started:-false}" == "true" ]] && stop_inline_spinner' RETURN
fi
local -a db_paths = (
" $HOME /Library/Mail/V*/MailData/Envelope Index* "
" $HOME /Library/Messages/chat.db "
@@ -176,6 +238,7 @@ opt_sqlite_vacuum() {
local vacuumed = 0
local timed_out = 0
local failed = 0
local skipped = 0
for pattern in " ${ db_paths [@] } " ; do
while IFS = read -r db_file; do
@@ -190,6 +253,43 @@ opt_sqlite_vacuum() {
continue
fi
# Safety check 1: Skip large databases (>100MB) to avoid timeouts
local file_size
file_size = $( get_file_size " $db_file " )
if [ [ " $file_size " -gt " $MOLE_SQLITE_MAX_SIZE " ] ] ; then
( ( skipped++) )
continue
fi
# Safety check 2: Skip if freelist is tiny (already compact)
local page_info = ""
page_info = $( run_with_timeout 5 sqlite3 " $db_file " "PRAGMA page_count; PRAGMA freelist_count;" 2> /dev/null || echo "" )
local page_count = ""
local freelist_count = ""
page_count = $( echo " $page_info " | awk 'NR==1 {print $1}' 2> /dev/null || echo "" )
freelist_count = $( echo " $page_info " | awk 'NR==2 {print $1}' 2> /dev/null || echo "" )
if [ [ " $page_count " = ~ ^[ 0-9] +$ && " $freelist_count " = ~ ^[ 0-9] +$ && " $page_count " -gt 0 ] ] ; then
if ( ( freelist_count * 100 < page_count * 5 ) ) ; then
( ( skipped++) )
continue
fi
fi
# Safety check 3: Verify database integrity before VACUUM
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
local integrity_check = ""
set +e
integrity_check = $( run_with_timeout 10 sqlite3 " $db_file " "PRAGMA integrity_check;" 2> /dev/null)
local integrity_status = $?
set -e
# Skip if integrity check failed or database is corrupted
if [ [ $integrity_status -ne 0 ] ] || ! echo " $integrity_check " | grep -q "ok" ; then
( ( skipped++) )
continue
fi
fi
# Try to vacuum (skip in dry-run mode)
local exit_code = 0
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
@@ -220,6 +320,10 @@ opt_sqlite_vacuum() {
echo -e " ${ YELLOW } ! ${ NC } Database optimization incomplete "
fi
if [ [ $skipped -gt 0 ] ] ; then
echo -e " ${ GRAY } Already optimal for $skipped databases (size or integrity limits) ${ NC } "
fi
if [ [ $timed_out -gt 0 ] ] ; then
echo -e " ${ YELLOW } ! ${ NC } Timed out on $timed_out databases "
fi
@@ -295,322 +399,209 @@ opt_font_cache_rebuild() {
fi
}
# Startup items cleanup
# Removes broken LaunchAgents and analyzes startup performance impact
opt_startup_items_cleanup( ) {
# Check whitelist (respects 'Login item s c heck' setting)
if command -v is_whitelisted > /dev/null && is_whitelisted "check_login_items" ; then
return 0
fi
# Removed high-risk optimizations:
# - opt_startup_items_cleanup: Risk of deleting legitimate app helpers
# - opt_dyld_cache_update: Low benefit, time-consuming, auto-managed by macOS
# - opt_system_services_refresh: Risk of data los s w hen killing system services
local -a scan_dirs = (
" $HOME /Library/LaunchAgents "
" $HOME /Library/LaunchDaemons "
"/Library/LaunchAgents"
"/Library/LaunchDaemons"
)
local broken_count = 0
local total_count = 0
local processed_files = 0
for dir in " ${ scan_dirs [@] } " ; do
[ [ ! -d " $dir " ] ] && continue
# Check if we need sudo for this directory
local need_sudo = false
if [ [ " $dir " = = "/Library" * ] ] ; then
need_sudo = true
fi
# Process plists
local find_cmd = ( find)
if [ [ " $need_sudo " = = "true" ] ] ; then
find_cmd = ( sudo find)
fi
while IFS = read -r plist_file; do
# Verify file exists (unless in test mode)
if [ [ -z " ${ MO_TEST_MODE :- } " && ! -f " $plist_file " ] ] ; then
continue
fi
( ( total_count++) )
# Skip system items (com.apple.*)
local filename = $( basename " $plist_file " )
[ [ " $filename " = = com.apple.* ] ] && continue
# Check if plist is valid (use sudo for system dirs)
local lint_output = ""
local lint_status = 0
local errexit_was_set = 0
[ [ $- = = *e* ] ] && errexit_was_set = 1
set +e
if [ [ " $need_sudo " = = "true" ] ] ; then
lint_output = $( sudo plutil -lint " $plist_file " 2>& 1)
lint_status = $?
else
lint_output = $( plutil -lint " $plist_file " 2>& 1)
lint_status = $?
fi
if [ [ $errexit_was_set -eq 1 ] ] ; then
set -e
fi
if [ [ $lint_status -ne 0 ] ] ; then
# Skip if lint failed due to permissions or transient read errors
if echo " $lint_output " | grep -qi "permission\\|operation not permitted\\|not permitted" ; then
continue
fi
# Invalid plist - remove it
if command -v should_protect_path > /dev/null && should_protect_path " $plist_file " ; then
continue
fi
if [ [ " $need_sudo " = = "true" ] ] ; then
run_launchctl_unload " $plist_file " " $need_sudo "
if safe_sudo_remove " $plist_file " ; then
( ( broken_count++) )
else
echo -e " ${ YELLOW } ! ${ NC } Failed to remove (sudo) $plist_file "
fi
else
run_launchctl_unload " $plist_file " " $need_sudo "
if safe_remove " $plist_file " true; then
( ( broken_count++) )
else
echo -e " ${ YELLOW } ! ${ NC } Failed to remove $plist_file "
fi
fi
continue
fi
# Extract program path
local program = ""
program = $( plutil -extract Program raw " $plist_file " 2> /dev/null || echo "" )
if [ [ -z " $program " ] ] ; then
program = $( plutil -extract ProgramArguments.0 raw " $plist_file " 2> /dev/null || echo "" )
fi
program = " ${ program /# \~ / $HOME } "
# Skip paths with variables or non-absolute program definitions
if [ [ " $program " = = *'$' * || " $program " != /* ] ] ; then
continue
fi
# Check for orphaned privileged helpers (app uninstalled but helper remains)
local associated_bundle = ""
associated_bundle = $( plutil -extract AssociatedBundleIdentifiers.0 raw " $plist_file " 2> /dev/null || echo "" )
if [ [ -n " $associated_bundle " ] ] ; then
# Check if the associated app exists
local app_path = ""
# First check standard locations
if [ [ -d " /Applications/ $associated_bundle .app " ] ] ; then
app_path = " /Applications/ $associated_bundle .app "
elif [ [ -d " $HOME /Applications/ $associated_bundle .app " ] ] ; then
app_path = " $HOME /Applications/ $associated_bundle .app "
else
# Try extracting app name from bundle ID (e.g., com.dropbox.Dropbox -> Dropbox)
local app_name = " ${ associated_bundle ##*. } "
if [ [ -n " $app_name " && -d " /Applications/ $app_name .app " ] ] ; then
app_path = " /Applications/ $app_name .app "
elif [ [ -n " $app_name " && -d " $HOME /Applications/ $app_name .app " ] ] ; then
app_path = " $HOME /Applications/ $app_name .app "
else
# Fallback to mdfind (slower but comprehensive, with 10s timeout)
app_path = $( run_with_timeout 10 mdfind " kMDItemCFBundleIdentifier == ' $associated_bundle ' " 2> /dev/null | head -1 || echo "" )
fi
fi
# CRITICAL FIX: Only consider it orphaned if BOTH conditions are true:
# 1. Associated app is not found
# 2. The program/executable itself also doesn't exist
if [ [ -z " $app_path " ] ] ; then
if command -v should_protect_path > /dev/null && should_protect_path " $plist_file " ; then
continue
fi
# CRITICAL: Check if the program itself exists (reuse already extracted program path)
# If the executable exists, this is NOT an orphan - it's a valid helper
# whose app we just can't find (maybe mdfind indexing issue, non-standard location, etc.)
if [ [ -n " $program " && -e " $program " ] ] ; then
debug_log " Keeping LaunchAgent (program exists): $plist_file -> $program "
continue
fi
# Double check we are not deleting system files
if [ [ " $program " = = /System/* ||
" $program " = = /usr/lib/* ||
" $program " = = /usr/bin/* ||
" $program " = = /usr/sbin/* ||
" $program " = = /Library/Apple/* ] ] ; then
continue
fi
# Only delete if BOTH app and program are missing
debug_log " Removing orphaned helper (app not found, program missing): $plist_file "
if [ [ " $need_sudo " = = "true" ] ] ; then
run_launchctl_unload " $plist_file " " $need_sudo "
# remove the plist
safe_sudo_remove " $plist_file "
# The program doesn't exist (verified above), so no need to remove it
( ( broken_count++) )
opt_msg " Removed orphaned helper: $( basename " $plist_file " .plist) "
else
run_launchctl_unload " $plist_file " " $need_sudo "
safe_remove " $plist_file " true
( ( broken_count++) )
opt_msg " Removed orphaned helper: $( basename " $plist_file " .plist) "
fi
continue
fi
fi
# If program doesn't exist, remove the launch agent/daemon
if [ [ -n " $program " && ! -e " $program " ] ] ; then
if command -v should_protect_path > /dev/null && should_protect_path " $plist_file " ; then
continue
fi
if [ [ " $need_sudo " = = "true" ] ] ; then
run_launchctl_unload " $plist_file " " $need_sudo "
if safe_sudo_remove " $plist_file " ; then
( ( broken_count++) )
else
echo -e " ${ YELLOW } ! ${ NC } Failed to remove (sudo) $plist_file "
fi
else
run_launchctl_unload " $plist_file " " $need_sudo "
if safe_remove " $plist_file " true; then
( ( broken_count++) )
else
echo -e " ${ YELLOW } ! ${ NC } Failed to remove $plist_file "
fi
fi
fi
done < <( " ${ find_cmd [@] } " " $dir " -maxdepth 1 -name "*.plist" -type f 2> /dev/null || true )
done
if [ [ $broken_count -gt 0 ] ] ; then
opt_msg " Removed $broken_count broken startup items "
fi
if [ [ $total_count -gt 0 ] ] ; then
opt_msg " Verified $total_count startup items "
else
opt_msg "No startup items found"
fi
}
# dyld shared cache update
# Rebuilds dynamic linker shared cache to improve app launch speed
# Only beneficial after new app installations or system updates
opt_dyld_cache_update( ) {
# Check if command exists
if ! command -v update_dyld_shared_cache > /dev/null 2>& 1; then
echo -e " ${ GRAY } - ${ NC } dyld cache (automatically managed by macOS) "
return 0
fi
# Skip if dyld cache was already rebuilt recently (within 24 hours)
local dyld_cache_path = " /var/db/dyld/dyld_shared_cache_ $( uname -m) "
if [ [ -e " $dyld_cache_path " ] ] ; then
local cache_mtime
cache_mtime = $( stat -f "%m" " $dyld_cache_path " 2> /dev/null || echo "0" )
local current_time
current_time = $( date +%s)
local time_diff = $(( current_time - cache_mtime))
local one_day_seconds = $(( 24 * 3600 ))
if [ [ $time_diff -lt $one_day_seconds ] ] ; then
opt_msg "dyld shared cache already up-to-date"
# Memory pressure relief
# Clears inactive memory and disk cache to improve system responsiveness
opt_memory_pressure_relief( ) {
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
if ! is_memory_pressure_high; then
opt_msg "Memory pressure already optimal"
return 0
fi
fi
if [ [ -t 1 ] ] ; then
start_inline_spinner "Rebuilding dyld cache... "
fi
local success = false
local exit_code = 0
# Skip actual rebuild in dry-run mode
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
# This can take 1-2 minutes on some systems (180 second timeout)
set +e
run_with_timeout 180 sudo update_dyld_shared_cache -force > /dev/null 2>& 1
exit_code = $?
set -e
if [ [ $exit_code -eq 0 ] ] ; then
success = true
if sudo purge > /dev/null 2>& 1 ; then
opt_msg "Inactive memory released "
opt_msg "System responsiveness improved"
else
echo -e " ${ YELLOW } ! ${ NC } Failed to release memory pressure "
fi
else
success = true # Assume success in dry-run mode
exit_code = 0
fi
if [ [ -t 1 ] ] ; then
stop_inline_spinner
fi
if [ [ " $success " = = "true" ] ] ; then
opt_msg "dyld shared cache rebuilt"
opt_msg "App launch speed improved"
elif [ [ $exit_code -eq 124 ] ] ; then
echo -e " ${ YELLOW } ! ${ NC } dyld cache update timed out "
else
echo -e " ${ GRAY } - ${ NC } dyld cache update skipped (automatically managed) "
opt_msg "Inactive memory released"
opt_msg "System responsiveness improved"
fi
}
# System services refresh
# Restarts system services to apply cache and configuration chang es
opt_system_services_refresh ( ) {
local -a servi ces = (
"cfprefsd:Preferences"
"lsd:LaunchServices"
"iconservicesagent:Icon Services"
"fontd:Font Server"
)
local -a restarted_services = ( )
# Network stack optimization
# Flushes routing table and ARP cache to resolve network issu es
opt_network_stack_optimize ( ) {
local suc cess = 0
# Skip actual service restarts in dry-run mode
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
for service_entry in " ${ services [@] } " ; do
IFS = ':' read -r process_name display_name <<< " $service_entry "
local route_ok = true
local dns_ok = true
# Special handling for cfprefsd (use -HUP instead of normal kill)
if [ [ " $process_name " = = "cfprefsd" ] ] ; then
if killall -HUP " $process_name " 2> /dev/null; then
restarted_services += ( " $display_name " )
fi
else
if killall " $process_name " 2> /dev/null; then
restarted_services += ( " $display_name " )
fi
fi
done
if ! route -n get default > /dev/null 2>& 1; then
route_ok = false
f i
if ! dscacheutil -q host -a name "example.com" > /dev/null 2>& 1; then
dns_ok = false
fi
if [ [ " $route_ok " = = "true" && " $dns_ok " = = "true" ] ] ; then
opt_msg "Network stack already optimal"
return 0
fi
# Flush routing table
if sudo route -n flush > /dev/null 2>& 1; then
( ( success++) )
fi
# Clear ARP cache
if sudo arp -a -d > /dev/null 2>& 1; then
( ( success++) )
fi
else
# In dry-run mode, show all services that would be restarted
for service_entry in " ${ services [@] } " ; do
IFS = ':' read -r _ display_name <<< " $service_entry "
restarted_services += ( " $display_name " )
done
success = 2
fi
if [ [ ${# restarted_services [@] } -gt 0 ] ] ; then
opt_msg "Refreshed ${# restarted_services [@] } system services "
for service in " ${ restarted_services [@] } " ; do
echo -e " • $service "
done
if [ [ $success -gt 0 ] ] ; then
opt_msg "Network routing table refreshed "
opt_msg "ARP cache cleared"
else
opt_msg "System services already optimal "
echo -e " ${ YELLOW } ! ${ NC } Failed to optimize network stack "
fi
}
# Disk permissions repair
# Fixes user home directory permission issues
opt_disk_permissions_repair( ) {
local user_id
user_id = $( id -u)
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
if ! needs_permissions_repair; then
opt_msg "User directory permissions already optimal"
return 0
fi
if [ [ -t 1 ] ] ; then
start_inline_spinner "Repairing disk permissions..."
fi
local success = false
if sudo diskutil resetUserPermissions / " $user_id " > /dev/null 2>& 1; then
success = true
fi
if [ [ -t 1 ] ] ; then
stop_inline_spinner
fi
if [ [ " $success " = = "true" ] ] ; then
opt_msg "User directory permissions repaired"
opt_msg "File access issues resolved"
else
echo -e " ${ YELLOW } ! ${ NC } Failed to repair permissions (may not be needed) "
fi
else
opt_msg "User directory permissions repaired"
opt_msg "File access issues resolved"
fi
}
# Bluetooth module reset
# Resets Bluetooth daemon to fix connectivity issues
# Only runs if no Bluetooth audio is playing
opt_bluetooth_reset( ) {
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
if has_bluetooth_hid_connected; then
opt_msg "Bluetooth already optimal"
return 0
fi
# Check if any audio is playing through Bluetooth
local bt_audio_active = false
# Check system audio output
if system_profiler SPBluetoothDataType 2>/dev/null | grep -q "Connected: Yes" ; then
# Check if any audio/video apps are running that might be using Bluetooth
local -a media_apps = ( "Music" "Spotify" "VLC" "QuickTime Player" "TV" "Podcasts" )
for app in " ${ media_apps [@] } " ; do
if pgrep -x " $app " > /dev/null 2>& 1; then
bt_audio_active = true
break
fi
done
fi
if [ [ " $bt_audio_active " = = "true" ] ] ; then
opt_msg "Bluetooth already optimal"
return 0
fi
# Safe to reset Bluetooth
if sudo pkill -TERM bluetoothd > /dev/null 2>& 1; then
sleep 1
if pgrep -x bluetoothd > /dev/null 2>& 1; then
sudo pkill -KILL bluetoothd > /dev/null 2>& 1 || true
fi
opt_msg "Bluetooth module restarted"
opt_msg "Connectivity issues resolved"
else
opt_msg "Bluetooth already optimal"
fi
else
opt_msg "Bluetooth module restarted"
opt_msg "Connectivity issues resolved"
fi
}
# Spotlight index optimization
# Rebuilds Spotlight index if search is slow or results are inaccurate
# Only runs if index is actually problematic
opt_spotlight_index_optimize( ) {
# Check if Spotlight indexing is disabled
local spotlight_status
spotlight_status = $( mdutil -s / 2> /dev/null || echo "" )
if echo " $spotlight_status " | grep -qi "Indexing disabled" ; then
echo -e " ${ GRAY } ${ ICON_EMPTY } ${ NC } Spotlight indexing is disabled "
return 0
fi
# Check if indexing is currently running
if echo " $spotlight_status " | grep -qi "Indexing enabled" && ! echo " $spotlight_status " | grep -qi "Indexing and searching disabled" ; then
# Check index health by testing search speed twice
local slow_count = 0
local test_start test_end test_duration
for _ in 1 2; do
test_start = $( date +%s)
mdfind "kMDItemFSName == 'Applications'" > /dev/null 2>& 1 || true
test_end = $( date +%s)
test_duration = $(( test_end - test_start))
if [ [ $test_duration -gt 3 ] ] ; then
( ( slow_count++) )
fi
sleep 1
done
if [ [ $slow_count -ge 2 ] ] ; then
if ! is_ac_power; then
opt_msg "Spotlight index already optimal"
return 0
fi
if [ [ " ${ MOLE_DRY_RUN :- 0 } " != "1" ] ] ; then
echo -e " ${ BLUE } ℹ ${ NC } Spotlight search is slow, rebuilding index (may take 1-2 hours) "
if sudo mdutil -E / > /dev/null 2>& 1; then
opt_msg "Spotlight index rebuild started"
echo -e " ${ GRAY } Indexing will continue in background ${ NC } "
else
echo -e " ${ YELLOW } ! ${ NC } Failed to rebuild Spotlight index "
fi
else
opt_msg "Spotlight index rebuild started"
fi
else
opt_msg "Spotlight index already optimal"
fi
else
opt_msg "Spotlight index verified"
fi
}
@@ -661,10 +652,12 @@ execute_optimization() {
sqlite_vacuum) opt_sqlite_vacuum ; ;
launch_services_rebuild) opt_launch_services_rebuild ; ;
font_cache_rebuild) opt_font_cache_rebuild ; ;
startup_items_cleanup) opt_startup_items_cleanup ; ;
dyld_cache_update) opt_dyld_cache_update ; ;
system_services_refresh) opt_system_services_refresh ; ;
dock_refresh) opt_dock_refresh ; ;
memory_pressure_relief) opt_memory_pressure_relief ; ;
network_stack_optimize) opt_network_stack_optimize ; ;
disk_permissions_repair) opt_disk_permissions_repair ; ;
bluetooth_reset) opt_bluetooth_reset ; ;
spotlight_index_optimize) opt_spotlight_index_optimize ; ;
*)
echo -e " ${ YELLOW } ${ ICON_ERROR } ${ NC } Unknown action: $action "
return 1