# How the Vorssaint-utils Uninstaller Identifies and Removes Leftover Application Files

> Discover how the Vorssaint-utils uninstaller effectively removes leftover app files. Learn about its two-phase process, daemon detachment, permission resets, and identity-based scanning for thorough cleanup.

- Repository: [vorssaint/vorssaint-utils](https://github.com/vorssaint/vorssaint-utils)
- Tags: internals
- Published: 2026-09-12

---

**The Vorssaint-utils uninstaller executes a two-phase removal process that first detaches system daemons and resets macOS TCC permissions via shell commands, then performs identity-based scanning of Library folders using bundle ID verification, path safety checks, and exclusivity validation to identify and trash leftover files.**

The Vorssaint-utils repository provides a comprehensive macOS application removal system designed to eliminate all traces of an installed program. The uninstaller in Vorssaint-utils coordinates shell-based system teardown with Swift-based file system analysis to locate and remove orphaned preferences, caches, and container data that standard deletion misses. This approach targets both root-level system components and user-specific Library directories while implementing rigorous safety checks to prevent collateral damage.

## Phase One: Detaching System Services and Cleaning Core Components

The uninstallation process begins with [`Tools/uninstall.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/Tools/uninstall.sh), a shell script that orchestrates the immediate removal of running processes and system-wide registrations. According to the Vorssaint-utils source code, this script first terminates the application process using `pkill -x Vorssaint` (lines 16-19), then invokes the bundled binary with the `--uninstall` flag to deregister auxiliary services.

The `Uninstaller.runAndExit()` method in [`Sources/Vorssaint/Support/Uninstaller.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Support/Uninstaller.swift) (lines 14-50) handles the daemon teardown by calling `FanControlService.restoreAndUnregisterForRemoval()` to unregister the fan-helper daemon, followed by `SMAppService.mainApp.unregister()` to eliminate the login item. The script subsequently resets macOS privacy permissions using `tccutil reset All "$BUNDLE"` (line 55), clearing Accessibility and Screen Recording allowances from the TCC database.

Final system cleanup includes removing the app bundle via `rm -rf`, deleting preference plists, saved state, HTTP storage, ByHost preferences, and a secret keychain entry (lines 59-76). If the application previously modified sleep settings, the script checks `pmset -g` and restores normal sleep behavior (lines 92-99).

## Phase Two: Scanning for Leftover Application Files

Once system components are detached, the uninstaller transitions to file system scanning via `AppUninstaller` in [`Sources/Vorssaint/Services/Uninstall/AppUninstaller.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Uninstall/AppUninstaller.swift). The process starts with `select(appURL:)` (lines 99-121), which validates the target bundle and extracts its identifier using `UninstallerSupport.verifiedBundleID`.

The scanner builds an **identity** object through `UninstallerSupport.identity` (lines 86-99 in [`UninstallerSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/UninstallerSupport.swift)), which aggregates:

- The primary and legacy bundle IDs
- Normalized display name tokens via `normalizedToken`
- Team IDs and signed group IDs from code signatures

This identity drives the search through predefined `SearchFolder` locations including Application Support, Caches, Containers, and Library/Preferences. The `collect` method (around line 152) generates `Leftover` objects for files matching specific criteria.

### File Matching and Confidence Classification

The `UninstallerSupport.leftoverMatch` enum (lines 30-35) categorizes discoveries into two confidence levels:

- **`.exact`**: Files owned by the application's bundle ID or signed group
- **`.related`**: Files matching normalized name tokens but not directly owned

Each `Leftover` object records the file path, size, category, and confidence level, enabling the UI to present sorted results for user review before deletion.

## Safety Mechanisms: Preventing Accidental Deletion

The Vorssaint-utils uninstaller implements multiple validation layers to prevent system damage. The `UninstallerSupport.removalPathIsSafe` function (lines 102-116 in [`UninstallerSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/UninstallerSupport.swift)) verifies that candidate paths reside within the expected root directory and contain no symbolic links, mitigating directory traversal attacks.

For shared resources, `UninstallerSupport.sharedDataIsExclusive` (lines 31-41) checks whether folders contain data used by other installed applications through `exclusiveBundleIDs` validation. The uninstaller only marks shared folders for removal when they contain exclusively the target application's data, preventing collateral deletion of cross-app resources.

## Programmatic Usage Examples

You can trigger the uninstallation process either through the command-line script or directly via the Swift API.

### Running the Full Uninstaller from Command Line

```bash

# From the repository root

./Tools/uninstall.sh

```

The script performs the complete teardown sequence, printing progress symbols such as "▸ Quitting…", "UNINSTALL: fan helper daemon unregistered", and finally "✓ Vorssaint fully removed."

### Using the Swift Uninstaller Class

```swift
import Vorssaint

// Called when the user selects "Advanced → Uninstall" inside the app
Uninstaller.runAndExit()   // never returns; exits with EXIT_SUCCESS or EXIT_FAILURE

```

This method detaches the fan helper, restores sleep if needed, unregisters the login item, and then terminates the process.

### Scanning for Leftovers Programmatically

```swift
import Vorssaint

let url = URL(fileURLWithPath: "/Applications/Editor.app")
AppUninstaller.shared.select(appURL: url)

// After a short async scan:
DispatchQueue.main.async {
    let leftovers = AppUninstaller.shared.items
    leftovers.forEach { leftover in
        print("\(leftover.category): \(leftover.url.path) – size: \(leftover.size) – confidence: \(leftover.confidence)")
    }
}

```

The `items` array holds `Leftover` objects that can be filtered, displayed, or sent to the Trash based on their confidence classification.

## Summary

- The uninstaller uses a two-phase approach: shell-based system teardown followed by Swift-based file scanning
- [`Tools/uninstall.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/Tools/uninstall.sh) handles process termination, daemon deregistration, TCC permission resets, and bundle deletion
- `AppUninstaller.select(appURL:)` initiates scanning by building an identity from bundle IDs, name tokens, and team IDs
- `UninstallerSupport.removalPathIsSafe` prevents symlink attacks by validating path containment and link absence
- `UninstallerSupport.sharedDataIsExclusive` ensures shared folders aren't deleted if other apps depend on them
- Leftover files receive confidence classifications (`.exact` or `.related`) before UI presentation and user-confirmed trashing

## Frequently Asked Questions

### How does the uninstaller prevent deleting files used by other applications?

The `UninstallerSupport.sharedDataIsExclusive` function validates folders against `exclusiveBundleIDs` to ensure no other installed applications reference the same data. Additionally, the `leftoverMatch` logic distinguishes between files owned exclusively by the target bundle (`.exact`) and those merely related by name (`.related`), allowing the UI to highlight potential conflicts before removal.

### What macOS permissions does the uninstaller reset during removal?

According to [`Tools/uninstall.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/Tools/uninstall.sh) (line 55), the uninstaller executes `tccutil reset All "$BUNDLE"` to clear all TCC (Transparency, Consent, and Control) database entries for the application. This specifically removes granted Accessibility and Screen Recording permissions, ensuring no residual privacy allowances remain after deletion.

### Can I run the Vorssaint-utils uninstaller from the command line?

Yes. The repository includes [`Tools/uninstall.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/Tools/uninstall.sh), which you can execute directly from the repository root using [`./Tools/uninstall.sh`](https://github.com/vorssaint/vorssaint-utils/blob/main/./Tools/uninstall.sh). This script performs the complete uninstallation sequence including process termination, daemon deregistration, permission resets, and bundle deletion, printing progress indicators such as "▸ Quitting…" and "✓ Vorssaint fully removed" upon completion.

### How does the uninstaller identify files that belong to the target application?

The system constructs an identity profile using `UninstallerSupport.identity`, which combines the verified bundle ID from `UninstallerSupport.verifiedBundleID`, normalized name tokens, and code-signing team IDs. The scanner then searches known Library folders and matches files where `leftoverMatch` returns `.exact` (bundle ID ownership) or `.related` (name token matches), creating `Leftover` objects that include file size and confidence metadata.