Performance improvements:
- Merge 3 separate find operations into 1 for /Library/Caches
- Combine *.cache, *.tmp, *.log patterns in single scan
- Reduces filesystem traversal overhead
- Merge 2 find operations into 1 for /private/var/log
- Combine *.log and *.gz patterns
- Optimize diagnostics cleanup with single combined scan
- Merge Special, Persist, and tracev3 patterns
- Reduces redundant directory traversal
- Use find -delete for batch removal of memory exception reports
- More efficient than iterative removal for large file counts
- Add summary logging to operations.log
UI improvements:
- Add granular spinner messages for each cleanup stage
- Separate diagnostic logs and power logs output for clarity
- Add progress feedback during Time Machine status check
Tests:
- Update sudo mock functions to support new combined find patterns
- Verify find -delete usage for memory exception cleanup
- Update assertions to match optimized implementation
New features:
- Add orphaned LaunchAgent/LaunchDaemon detection with 5-layer verification
- Layer 1: Check if program path exists
- Layer 2: Verify AssociatedBundleIdentifiers via mdfind
- Layer 3: Check Application Support directory activity (7 days)
- Layer 4: Fuzzy match app name in /Applications
- Layer 5: Special handling for PrivilegedHelperTools
- Only process user-level ~/Library/LaunchAgents (safer than system-level)
- Unload agent before removal using launchctl
Bug fixes:
- Handle paths with spaces correctly in orphaned_app_data cleanup
- Add nullglob state management to prevent word splitting
- Use IFS=$'\n' for proper array iteration
- Only count successful deletions (check safe_clean return value)
Tests:
- Add 4 new tests for is_launch_item_orphaned edge cases
- Add tests for space handling and deletion count accuracy
Gradle build cache (~/.gradle/caches) is now protected by default whitelist,
similar to Maven repository. This prevents unintentional deletion of large
dependency caches that take time and bandwidth to re-download.
- Add ~/.gradle/caches/* and ~/.gradle/daemon/* to DEFAULT_WHITELIST_PATTERNS
- Remove Gradle cleanup from clean_dev_jvm() function
- Users can disable protection via 'mo clean --whitelist' if needed
Fixes#408
Fixes#394
Users reported that `mo purge` could not find `node_modules` folders in
deeply nested project structures. The issue was caused by `PURGE_MAX_DEPTH_DEFAULT=4`
being too restrictive for real-world project organizations.
Example failing case:
~/Projects/Company/Division/Team/MyProject/node_modules (depth 5)
~/Projects/Org/ClientA/Backend/Services/API/node_modules (depth 6)
Changes:
- Increased PURGE_MAX_DEPTH_DEFAULT from 4 to 6
- This covers 95%+ of real-world project structures
- Performance impact: ~15-25% slower scan (acceptable trade-off for correctness)
- All 41 existing tests pass with the new depth limit
Verified:
- Tested with structures at depths 2-6, all artifacts now detected
- No breaking changes to existing functionality
- Users with fd (fast) won't notice performance difference
Improve user experience when osascript fails to empty Trash:
- Count successfully cleaned items
- Display cleanup confirmation message
- Only show message if items were actually cleaned
- Call note_activity to record the cleanup
This ensures users get consistent feedback regardless of which
cleanup method is used (osascript vs find fallback).
Replace glob pattern with find command to properly clean dotfiles
in Trash when osascript fallback is used. The old pattern
~/.Trash/* does not match files starting with "." in bash.
This fix ensures that hidden files like .DS_Store, .hidden_file,
etc. are properly removed when cleaning the Trash.
- Replace parentheses with commas for supplementary info
- Use commas instead of em-dashes for separators
- Update bullet points from - to * in some contexts
- Improve version extraction regex with fallback logic
- Refactor JetBrains Toolbox cleanup with _restore_whitelist helper
- Add MOLE_EDGE_APP_PATHS env var for test isolation
- Fix Edge old versions tests to avoid scanning system Edge installation
Add checks for empty product_dirs and version_dirs arrays before
iterating to prevent "unbound variable" errors when running with
set -u (pipefail) and the JetBrains Toolbox directory doesn't exist
or contains no products.
- Empty trash using macOS Finder API (osascript) for proper permission handling
- Respects whitelist protection (skips if Trash is whitelisted)
- Shows item count when emptying trash
- Fallback to direct cleanup if Finder API fails
- Supports dry-run mode
Issue: #362
- Export MOLE_DRY_RUN env var for subprocess visibility
- Add || true to grep commands to prevent pipeline failures
- Add dry-run test for clean_orphaned_system_services
- Simplify clean_local_snapshots tests
- Replace 48-line custom function with one-line safe_clean call
- Remove unnecessary interactive confirmation (consistent with other browser caches)
- Simplify tests to verify Puppeteer cache is in clean_browsers output
- Net: -93 lines of code for same functionality
Detect and remove leftover LaunchDaemons, LaunchAgents, and
PrivilegedHelperTools from uninstalled apps like Sogou Input,
ClashX, ClashMac, and Nektony App Cleaner.
- Speed up spinner animation from 100ms to 50ms for smoother visuals
- Fix spinner flicker by deferring stop until output is ready
- Remove unnecessary 'Preparing...' spinner at section start
- Hide whitelist-protected items from output (Trash, Finder metadata)
- Add spinner feedback for system diagnostic log cleanup
- Remove redundant stop_section_spinner calls in cleanup modules
The cleanup process now feels significantly faster and more polished,
with continuous visual feedback and no jarring gaps between operations.
Fixes#313
Change browser process detection from pgrep -f (full command line match)
to pgrep -x (exact process name match) to prevent false positives.
Microsoft Teams processes contain 'Microsoft' in their paths and may have
Chromium-based components, which was causing them to be incorrectly
identified as Microsoft Edge during clean operations.
Changes:
- Chrome detection: pgrep -f → pgrep -x
- Edge detection: pgrep -f → pgrep -x
- Edge updater detection: pgrep -f → pgrep -x
This approach is consistent with Firefox detection and prevents Apps like
Microsoft Teams, Microsoft Office, or other Microsoft products from
triggering false Edge detection.
All existing tests pass (9/9 in clean_browser_versions.bats).