Last Week on My Mac: Can we make cleaning up our Macs simpler?
One of the better trends in recent versions of macOS has been to make apps more self-contained, and to disperse their dependent files less. It’s not that long ago that any app of substance needed its own folder in either of the Library/Application Support folders, in various more obscure locations, as well as in the user’s ~/Library/Preferences folder. When you migrate from one Mac to the next, this leads to inherited clutter that requires painstaking manual clean-up.
This in turn has led to a flourishing industry hiring out housekeeping services and other utilities that attempt to perform the clean uninstall that is surely the responsibility of any app that scatters its files to the four corners of your Mac. After all, if it doesn’t know what files it installs, it shouldn’t be offered to the public.
A few remaining apps that still come as Installer packages may offer uninstaller scripts, and macOS now automatically removes any system extensions installed by an app when that app is removed. LaunchAgents, LaunchDaemons and other helper executables that used to require installation of their property lists into Library folders can now retain them within the app bundle. Containerisation of sandboxed and some other apps has the useful side-effect that it can provide clues as to what might need to be removed with an app, but in other respects can confuse instead of clarifying.
Apple’s motivation for these changes in macOS is more about improving security, and less about convenience to the user. Containers are the sandbox within which an app is constrained. Keeping more of an app’s components inside its bundle gives them the protection afforded by the CDHashes in its signature, and verification against those obtained during notarization, making it far harder for those components to be hijacked maliciously.
Starting from the premise that an app developer should know full well what their app does install and where those files are to be found, wouldn’t it be best for that app to provide a list? Perhaps a property list of the app’s manifest of files it installs outside its bundle might be a workable solution? Then a user who wants to completely uninstall an app can use that list to hunt and remove stragglers like a private log file tucked away in ~/Library/Logs. This would also facilitate the task of cleaning up using a housekeeping utility or app remover.
A simple example might be my app Mints. In normal use, the only file it installs outside the app bundle is that containing its preference settings, in ~/Library/Preferences/co.eclecticlight.Mints.plist. However, it does have a feature that will create a folder of test files inside ~/MintsSpotlightTest4syzFiles, and provides a button to delete that folder and its contents.
A manifest property list might provide two entries to account for those:
a mandatory item for ~/Library/Preferences/co.eclecticlight.Mints.plist,
an optional item for ~/MintsSpotlightTest4syzFiles and its contents.
A person or app wanting to clean up after the removal of Mints should then delete the first and, if the second is present, should delete that too. As Mints isn’t sandboxed, no folder should be created in ~/Library/Containers, and it doesn’t write private logs in ~/Library/Logs either, so there’s no point in checking for its mortal remains in either of those locations.
Almost every app already has a Resources folder inside its app bundle, which should be a suitable place to save this manifest.plist file, although as that is deleted when the app is removed, it would perhaps be most helpful for those manifests to be copied into a separate folder in /Library for reference and later use once the app has gone.
I’d be interested to read your opinions, and suggestions for better alternatives.