# How to Uninstall Applications with Mole: Complete Guide to the macOS Uninstaller

> Uninstall macOS apps completely with Mole. Safely remove applications and associated files using the `mo uninstall` command for a clean system.

- Repository: [Tw93/Mole](https://github.com/tw93/Mole)
- Tags: how-to-guide
- Published: 2026-03-20

---

**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`](https://github.com/tw93/Mole/blob/main/bin/uninstall.sh)** – CLI entry point and flow orchestration
- **`scan_applications` function** – Recursive discovery and metadata caching
- **[`lib/ui/app_selector.sh`](https://github.com/tw93/Mole/blob/main/lib/ui/app_selector.sh)** – Paginated, interactive selection interface
- **[`lib/uninstall/batch.sh`](https://github.com/tw93/Mole/blob/main/lib/uninstall/batch.sh)** – Core removal engine with safety checks

### CLI Entry Point ([`bin/uninstall.sh`](https://github.com/tw93/Mole/blob/main/bin/uninstall.sh))

The uninstallation process begins in [`bin/uninstall.sh`](https://github.com/tw93/Mole/blob/main/bin/uninstall.sh), which sets strict Bash options (`set -euo pipefail`) to ensure reliability. This script sources shared helpers from [`lib/core/common.sh`](https://github.com/tw93/Mole/blob/main/lib/core/common.sh) and UI components from [`lib/ui/menu_paginated.sh`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/app_selector.sh))

The [`lib/ui/app_selector.sh`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/batch.sh))

[`lib/uninstall/batch.sh`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/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:

```bash
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:

```bash
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:

```bash
mo uninstall

# Select "Google Chrome" or any Brew-managed app from the list

```

The `get_brew_cask_name` function in [`lib/uninstall/brew.sh`](https://github.com/tw93/Mole/blob/main/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:

```bash
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`](https://github.com/tw93/Mole/blob/main/bin/uninstall.sh), batch logic in [`lib/uninstall/batch.sh`](https://github.com/tw93/Mole/blob/main/lib/uninstall/batch.sh), and Brew handling in [`lib/uninstall/brew.sh`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/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`](https://github.com/tw93/Mole/blob/main/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.