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:

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:

  1. Calls scan_applications to build or refresh the application list
  2. Loads applications into Bash arrays via load_applications
  3. Invokes select_apps_for_uninstall for 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_deletion vets every target path before removal
  • Sensitive Data Detection – has_sensitive_data scans for credentials before deletion
  • Bundle ID Validation – Prevents glob injection when stopping launch services
  • Process Checks – Uninstall aborts for specific apps if force_kill_app fails to terminate running processes
  • Brew Verification – is_brew_cask_installed confirms 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 in lib/uninstall/batch.sh, and Brew handling in lib/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 --zap with timeout protection.
  • Metadata caching at $HOME/.cache/mole/uninstall_app_metadata_v1 accelerates 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →