Replace jq with bash-native JSON parsing helpers (json_get_value,
json_validate, parse_optimization_items) so that mo optimize no
longer requires jq to be installed.
Closes#588
Allow users to press 'q' or 'Q' to quit the Touch ID setup menu,
in addition to ESC key. This fixes the "Invalid key" error when
users press Q as suggested by the prompt.
Fixes#575
- Replace inline dynamic formatting with shared bytes_to_human_kb()
- Apply to both clean and purge commands
- Simplify movie comparison with integer arithmetic
Replace blocking read with a timed read (default 3 s) so the prompt
exits automatically instead of waiting forever. Timeout is configurable
via MOLE_UNINSTALL_RETURN_PROMPT_TIMEOUT_SEC. Use a read_ok flag to
distinguish timeout (exit) from Enter (return to list).
- Capture terminal width in parent before forking; avoids unreliable
tput calls inside the background subshell
- Write spinner output directly to /dev/tty to prevent stdout state
contention between parent and background processes
- Use \033[2K (erase entire line) instead of \033[K (erase to EOL)
- Add handle_interrupt() so Ctrl-C cleanly stops spinner, restores
cursor, and exits 130
- cleanup_monitor now writes \r\033[2K\n so subsequent output starts
on a clean line rather than on the cleared spinner line
The dry-run mode hardcoded SYSTEM_CLEAN=false, which meant
the entire system section was silently skipped during preview.
Users had no way to see what /Library/Caches, /private/var/log,
diagnostics, or other sudo-required paths would be cleaned.
Now dry-run checks for a cached sudo session (sudo -n) and
includes the system preview when available. When sudo isn't
cached, a hint tells the user how to get the full preview
without running the whole script as root.
- reorganize perform_cleanup sections and naming
- merge macOS + sandbox caches into clean_app_caches
- move recent items and mail downloads into user essentials
- update core/user tests for renamed internal helpers
- Add guard flag in cleanup_monitor to prevent duplicate execution
- Check for existing trap in project.sh before setting new one
- Prevents crash when user presses Ctrl-C or scan process fails
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
Fixes text remnants and extra blank lines when spinner messages change.
Issues fixed:
1. Text remnants when switching from longer to shorter messages (e.g., 'Cleaning...ems...')
2. Extra blank lines appearing after section headers
Root causes:
- \033[K only clears from cursor to end of line, leaving remnants when new messages are shorter
- stop_section_spinner was clearing lines even when no spinner was running
Changes:
- lib/core/base.sh:
- Changed stop_section_spinner(), safe_clear_line(), safe_clear_lines() to use \033[2K
- Added guard in stop_section_spinner to only clear when spinner is actually running
- lib/core/ui.sh:
- Clear line once when starting spinner (before loop) to ensure clean start
- Normal spinner rotation uses \r without clearing (performance optimization)
Performance: Line clearing happens only once per spinner start, not on every loop iteration.
Fixes#390
- Add get_timestamp() helper and optimize log rotation
- Create mo log viewer with search/filter capabilities
- Improve test coverage to 18.4% with better assertions
- Add security fixes for grep injection prevention