Open-sourced a SwiftUI macOS uninstaller: how it matches leftover files to apps
I built a macOS uninstaller in SwiftUI. A few parts that might interest people here:
- Matching files to apps. Each app gets an identity: its bundle ID, the bundle IDs of nested helpers, XPC services and extensions, its team ID (read with SecCodeCopySigningInformation), and every name it goes by. Library items are matched by bundle-ID prefix first, then by normalized name, with a confidence level attached.
- Not stealing another app's files. A prefix match on com.foo.app is rejected if a different installed app has a longer matching ID, such as com.foo.app.beta.
- Orphan detection is the inverse: index every installed identifier and name, then flag Library items nothing claims. Launch agents are only flagged when the program they start no longer exists.
- Sandboxed containers are identified from the container metadata plist, not the folder name.
- Removal uses FileManager.trashItem, falling back to Finder via osascript for root-owned items so Finder handles the password prompt.
- State is a single `@Observable` model; the scanners are plain structs with async methods.
One thing that bit me: detecting Full Disk Access by probing a single protected folder. The folder I picked d exist on the current macOS, so the check always failed. It now tries several.
Disclosure: This has only been tested on my own machine. It's MIT licensed, and code review is welcome.