How to Uninstall Applications with Mole: Complete Guide to the macOS Uninstaller
Mole provides a self-contained, multi-stage uninstaller accessed via the mo uninstall command that performs safe, complete removal of macOS applications including their associated files, launch services, and Homebrew Casks.
The tw93/Mole repository delivers a robust command-line tool for macOS application management. Uninstalling applications with Mole goes far beyond dragging apps to the trash—it orchestrates service stopping, file validation, metadata cleanup, and dependency removal through a carefully structured pipeline.
The Mole Uninstall Architecture
Mole implements a four-layer uninstaller architecture, with each layer handled by dedicated scripts in the repository:
bin/uninstall.sh– CLI entry point and flow orchestrationscan_applicationsfunction – Recursive discovery and metadata cachinglib/ui/app_selector.sh– Paginated, interactive selection interfacelib/uninstall/batch.sh– Core removal engine with safety checks
CLI Entry Point (bin/uninstall.sh)
The uninstallation process begins in bin/uninstall.sh, which sets strict Bash options (set -euo pipefail) to ensure reliability. This script sources shared helpers from lib/core/common.sh and UI components from lib/ui/menu_paginated.sh.
After parsing command-line arguments (--dry-run, --help), the script enters a loop that:
- Calls
scan_applicationsto build or refresh the application list - Loads applications into Bash arrays via
load_applications - Invokes
select_apps_for_uninstallfor user selection
If the user cancels, the loop restarts; otherwise, execution proceeds to the batch removal phase.
Application Scanning (scan_applications)
The scan_applications function recursively discovers .app bundles across standard directories: /Applications, $HOME/Applications, and any /Volumes/*/Applications.
For each bundle, Mole gathers:
- Path, display name, and bundle identifier
- File modification time via
get_file_mtime - Size calculated through
get_path_size_kb - Last-used timestamp via
mdls(falling back to mtime)
This data merges with a metadata cache stored at $HOME/.cache/mole/uninstall_app_metadata_v1. The cache refreshes only when an app's modification time changes or after a 7-day TTL, ensuring subsequent scans execute quickly.
Interactive UI Selection (app_selector.sh)
The lib/ui/app_selector.sh script provides the human interface. It reads the sorted application list and renders a paginated, searchable menu using the menu_paginated.sh helper.
Users can toggle selections, view application details, and confirm their choices. Selected entries populate the global selected_apps array, which the batch processor consumes.
Batch Removal Engine (batch.sh)
lib/uninstall/batch.sh contains the batch_uninstall_applications function—the heart of Mole's uninstaller. For each selected application, it executes the following sequence:
Launch Services Stop – Calls stop_launch_services to unload any LaunchAgents or LaunchDaemons associated with the bundle ID.
LaunchServices Unregister – Executes unregister_app_bundle using lsregister -u to remove the app from the system registry.
Login-Item Removal – Runs remove_login_item via AppleScript to eliminate stale login entries.
Process Termination – Invokes force_kill_app using pkill to halt running processes. If the app remains active, Mole aborts uninstallation for that specific bundle.
Homebrew Cask Handling – Detects Brew-managed applications through lib/uninstall/brew.sh and executes brew uninstall --cask --zap via brew_uninstall_cask with a size-based timeout (5-30 minutes). If Brew removal fails, Mole falls back to manual removal while warning about potential state inconsistency.
File Deletion – Uses remove_file_list (wrapped rm/sudo rm) on the app bundle and associated files. Every path passes through validate_path_for_deletion and has_sensitive_data checks to prevent credential loss.
System Cleanup – Runs defaults delete for the bundle identifier, wipes ByHost plist files, and calls remove_apps_from_dock and refresh_launch_services_after_uninstall.
Privileged operations rely on ensure_sudo_session, which prompts once and maintains the timestamp throughout the batch run.
How to Use the Mole Uninstall Command
Basic Interactive Uninstall
Run the uninstaller without arguments to launch the interactive UI:
mo uninstall
This scans your system, presents the paginated selector, and guides you through confirmation before removing selected applications.
Dry-Run Mode for Safe Previewing
Preview all actions without making destructive changes:
mo uninstall --dry-run
In dry-run mode, Mole short-circuits every destructive operation. Functions like remove_file_list, brew_uninstall_cask, and defaults delete log debug messages prefixed with [DRY RUN] instead of executing. The final summary displays "Would..." statements, allowing safe impact assessment.
Homebrew Cask Uninstallation
Mole automatically detects and properly removes Homebrew Casks:
mo uninstall
# Select "Google Chrome" or any Brew-managed app from the list
The get_brew_cask_name function in lib/uninstall/brew.sh performs deterministic checks (resolved paths, Caskroom searches, symlink inspection) before falling back to brew list --cask. If detected, Mole executes brew uninstall --cask --zap to ensure complete removal including associated files.
CI-Friendly Non-Interactive Mode
For automated environments, disable UI elements and authentication prompts:
export MOLE_DRY_RUN=1
export MOLE_TEST_MODE=1 # Skips AppleScript login-item removal
export MOLE_TEST_NO_AUTH=1 # Skips sudo prompts
mo uninstall
Safety Mechanisms and File Removal Logic
Mole implements multiple safeguards during the uninstallation process:
- Path Validation –
validate_path_for_deletionvets every target path before removal - Sensitive Data Detection –
has_sensitive_datascans for credentials before deletion - Bundle ID Validation – Prevents glob injection when stopping launch services
- Process Checks – Uninstall aborts for specific apps if
force_kill_appfails to terminate running processes - Brew Verification –
is_brew_cask_installedconfirms Homebrew removal status before falling back to manual deletion
All file operations use wrapped rm commands with sudo escalation gated behind the single ensure_sudo_session prompt, preventing repeated authentication interruptions during batch processing.
Summary
- Mole's uninstaller operates through four distinct layers: CLI bootstrap, application scanning, interactive UI selection, and batch removal.
- File locations: Entry point at
bin/uninstall.sh, batch logic inlib/uninstall/batch.sh, and Brew handling inlib/uninstall/brew.sh. - Safety features include dry-run mode (
--dry-run), path validation, sensitive data detection, and sudo session management. - Homebrew integration automatically detects Casks and executes
brew uninstall --cask --zapwith timeout protection. - Metadata caching at
$HOME/.cache/mole/uninstall_app_metadata_v1accelerates subsequent scans using a 7-day TTL.
Frequently Asked Questions
How do I preview what Mole will delete before uninstalling?
Use the --dry-run flag. According to the source code in lib/uninstall/batch.sh, this mode short-circuits all destructive functions and logs [DRY RUN] messages instead of executing rm, brew uninstall, or defaults delete commands. The final summary prefixes all actions with "Would..." to show exactly which files and services would be affected.
Can Mole uninstall Homebrew Casks automatically?
Yes. When you select a Homebrew-managed application, the get_brew_cask_name function in lib/uninstall/brew.sh detects the Cask through path resolution and symlink inspection. Mole then calls brew_uninstall_cask to execute brew uninstall --cask --zap, ensuring complete removal including associated preference files and binaries. If Brew fails, Mole falls back to manual file removal.
What happens if an application is still running during uninstallation?
The force_kill_app function attempts to terminate the process using pkill. If the application remains active after this attempt, Mole aborts the uninstallation for that specific bundle and reports the failure in the final summary. This prevents removal of executing binaries, which could cause system instability or data loss.
Where does Mole store application metadata for faster scanning?
Mole caches application metadata at $HOME/.cache/mole/uninstall_app_metadata_v1. The scan_applications function in bin/uninstall.sh refreshes this cache only when an application's modification time changes or after a 7-day TTL expires. This design keeps subsequent uninstall operations fast while ensuring data accuracy.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →