# How to uninstall apps on a Mac, completely

Uninstalling a Mac app completely means the bundle plus everything it wrote outside itself - preferences, caches, launch items, permission entries - and Unroot moves all of it to the Trash rather than deleting it, so one click puts every file back.

- URL: https://swiftfox.studio/handbook/how-to-uninstall-apps-on-mac
- About: https://swiftfox.studio/apps/unroot
- Published: 2026-08-10
- Updated: 2026-09-06
- Publisher: Swiftfox Studio (https://swiftfox.studio)

## In short

- The Trash takes an app's bundle and nothing else: preferences, caches, containers, launch agents, installer receipts and its Privacy & Security entries all stay behind.
- Permission grants have to be cleared while the app is still on disk, because tccutil resolves an app through LaunchServices - once the bundle is gone the entries are stranded for good.
- Unroot moves every approved item into one dated folder in your Trash with a manifest beside it, so Undo is exact and an interrupted removal is recovered on the next launch.
- Every row shows the reason it matched before you tick it, nothing is proposed on a vendor prefix alone, and it is pay what you want with a suggested price of $4.99.
- Every removal it has ever made stays on one screen and stays undoable, and a right-click item in the Finder starts one without opening the app - top-level in ~/Applications, in the Services submenu everywhere else.

## The three ways to uninstall a Mac app, and what each leaves behind

**Drag it to the Trash.** Built in, free, and it removes the bundle. It removes
nothing the app wrote outside itself: preferences, caches, containers, saved
state, launch agents, installer receipts, and the entries under Privacy &
Security in System Settings. Those last ones macOS gives you no button for.
`tccutil`, the tool that clears them, resolves an app through LaunchServices, so
once the bundle is in the Trash it answers "No such bundle identifier" and the
grants sit in the permissions database forever. That is why apps you deleted
last year are still listed under Accessibility.

**The vendor's own uninstaller.** When one ships - Adobe, Microsoft, most VPN
clients - it is the right answer, because the vendor knows where it put things.
Most apps ship none.

**A dedicated uninstaller.** **AppCleaner** has done this for free for years and
is enough if what you want is the bundle plus the obvious `~/Library` folders;
**Pearcleaner** is the open-source take. [Unroot](https://swiftfox.studio/apps/unroot) is built around
a narrower question: not what can we find, but what can we prove, and what can
we put back. Everything below is in the shipping version.

## Where it looks, and why every row says why

A scan reads 58 locations - the ones you would guess (Application Support,
Preferences, Caches, Containers, Saved Application State) and the ones you would
not (HTTPStorages, WebKit, Cookies, the per-user trees under `/var/folders`, the
audio plug-in roots, QuickLook generators), plus `/Library/LaunchDaemons`,
`/Library/PrivilegedHelperTools`, `/var/db/receipts` and `/Users/Shared` outside
your home folder. Two are read specially: Application Support one level deeper,
because the nested folder is what should be proposed rather than the vendor
folder that would take every sibling product with it, and launch item plists on
their `Label` and `ProgramArguments`, because vendors name the file after the
daemon.

Then the matching, where an uninstaller either earns trust or destroys data. An
exact bundle identifier is certain, and so is that identifier as a whole
dot-delimited run, an app group the app declared in its own code signature, or a
path in an installer receipt `pkgutil` can prove installed this bundle. A name
match is merely possible, and is graded as such.

What is missing from that list is the point. Rules for the vendor prefix and for
the signing team both existed and were both deleted: between them they matched
45 times across two live scans, every one another app's data, and never once a
real leftover. Same developer is not same app. The strongest rule fires last - a
file filed under another installed app's identifier belongs to that app - and
every row shows the reason it matched, which is the difference between a list
you trust and a list you take on faith.

## Three tiers, and what starts ticked

![The Unroot review screen listing every trace found for an app, grouped under Safe to remove with each row showing its path and the reason it matched](https://swiftfox.studio/unroot/listing/shot-2.jpg "Every row carries the reason it matched, and the header carries the count in each of the three tiers.")

Findings are graded safe to remove, worth a look, or sensitive, and the grading
answers one question: how careful do you need to be about this row. **Safe** is
reversible, inside your home folder, and certainly the app's. **Worth a look**
is matched by name only, or shared with an app you still have. **Sensitive** is
keychain entries, privileged helpers, system extensions and anything outside
your home folder - the only tier that can produce the failure everyone is afraid
of.

The counter-intuitive part is what arrives ticked, because it is not the safe
tier. A row is ticked when the match is certain, not when it is reversible.
Conflating those made the product dishonest: an app's license lives in the
keychain, so leaving those rows unticked meant the default removal quietly left
the app activated. A sensitive keychain row is ticked; a name-only match is not.

The same screen carries the other mode. **Reset** keeps the app and removes
everything it stored, except the installer receipts, because `pkgutil`
forgetting a package that is still installed breaks its own updater. Keychain
entries stay in scope on purpose: a factory-fresh app is signed out.

## Nothing is deleted

![The Unroot removal report reading 11 of 11 removed, with the quarantine folder path in the Trash and an Undo button](https://swiftfox.studio/unroot/listing/shot-3.jpg "One dated folder in the Trash, a manifest beside it, and Undo still on the table.")

Removed items go into one dated folder inside your Trash - `Unroot - Spectacle -
2026-08-21 11-01-33` - each in its own numbered slot, so `com.vendor.app.plist`
from `~/Library/Preferences` cannot silently overwrite the one from
`/Library/Preferences`.

One folder rather than four hundred loose items is partly legibility and partly
capability: Finder's Put Back only restores the first item of a batch, and there
is no public API to restore programmatically, so an undo built on it would be a
promise the system cannot keep. Beside the files sits `unroot-manifest.json`, a
plain list of where every item came from. It is what Undo reads, and it stays
readable even if Unroot itself is gone.

One part of a removal genuinely is permanent, and the footer counts it in red. A
keychain entry is not a file, so it cannot be moved into a folder; deleting it
signs the app out and takes any license it stored with it. The confirmation
sheet names each one rather than counting them, because a number is not consent.

## Undo that survives a crash

The manifest can only record what was observed to succeed, so it can only be
written after the run - and a crash in between would leave moved files with no
record of where they came from, which is precisely the promise it exists to
keep. So before anything moves, a journal of every planned entry goes into the
same folder, and a completed run deletes it. A journal with no manifest is
therefore the signature of an interrupted removal, and the next launch rebuilds
the manifest from it, keeping only the entries whose files are demonstrably
sitting in their slots.

Undo is then a reverse replay. If something now occupies the original path -
you reinstalled the app - the restore diverts to a numbered sibling instead of
overwriting it, because undo must never destroy anything in order to succeed.
Launch jobs are re-bootstrapped rather than just re-filed, since putting a plist
back and leaving the daemon booted out would restore the files and quietly not
the behavior. Both directions pass a policy that assumes everything upstream
got it wrong: `/System`, the keychain directories, iCloud Drive and your
Documents, Desktop, Downloads, Pictures, Movies and Music can never be an
endpoint no matter what matched.

The one step undo does not put back is the permission reset, and the app says so
on the row rather than in a footnote: privacy grants are reset, not restored.
Each app asks again the next time it needs one.

None of that expires. Every removal Unroot has ever made stays on one screen with
the space its folder is holding, so a removal from two months ago undoes exactly
like the one from two minutes ago - and whether it still can be is settled by
looking at the disk, not by a flag written at the time.

Keeping everything does mean a Trash full of quarantine folders. Emptying it is
the normal answer; failing that, Unroot will delete one folder on request. That
is the only place in the app that deletes anything, so it is fenced: three checks
that the path really is one of its own, and an automatic sweep that stays off
unless you turn it on.

## The permission entries nobody can clear by hand

Before you remove anything, Unroot reads the permissions database - read-only,
with the same Full Disk Access it needs to see `~/Library` - and shows what the
app was holding. Accessibility, Full Disk Access, Screen Recording, Input
Monitoring, Automation and some thirty grant types in all are decoded by name.
Almost nothing else shows you this, and it is the best argument there is for why
the order of a removal matters.

Because it does. The reset has to run while the bundle is still on disk, so the
bundle moves last, after the launch jobs are booted out and the keychain entries
are gone. Removing it first is the one-way mistake, and it is why so many
uninstalled apps still haunt System Settings.

Afterwards the report re-reads the database rather than assuming the tools
worked. macOS is known to refuse some Full Disk Access resets, so it either says
the grants are verified clear or names the one that survived and tells you to
clear it by hand.

Running apps are dealt with first of all. Each is asked to quit, and if it
refuses you get a decision rather than a silent force-quit: force it, or skip
that app and leave every one of its files untouched.

## Apps you deleted years ago, and what they left running

![The Unroot leftovers sweep listing orphaned caches and logs grouped by bundle identifier, with only the safe rows ticked](https://swiftfox.studio/unroot/listing/shot-4.jpg "The sweep lists identifier-shaped leftovers only, and ticks nothing but the caches and logs macOS rebuilds on demand.")

The other half of a narrow matcher is that leftovers belonging to apps which are
already gone have nowhere to turn up. So they get their own sweep, and it is
deliberately conservative. It lists only identifier-shaped things - a name with
at least three dot-separated segments and no spaces - because a folder named
after a company could belong to anything, and guessing is how an uninstaller
deletes something it should not have.

Only caches and logs arrive ticked. App data and settings do not, and the screen
says why: some of what is listed is cache written by a framework inside an app
you still use, which looks identical from the outside. The list is a starting
point, not a verdict.

A leftover file is inert. A leftover launch agent is not, and it is why an app
you removed years ago can still put a background item in System Settings that
System Settings gives you no way to remove. So the same idea is pointed at
launchd: one screen lists everything that starts without being asked - launch
agents, daemons, and the login jobs apps register through `SMAppService` - and
names the owner of each.

Only the ones whose program is missing can be selected in bulk, and that
restraint is the design. A job like `com.docker.vmnetd` shares a vendor prefix
with an app you still have; grading it as related rather than orphaned exists
precisely to keep something live off a list headed "safe to remove". A job that
still has a program to run is never an orphan, however abandoned its name
looks.

## What it deliberately does not do

It needs **Full Disk Access**, switched on by hand, because macOS offers no way
for an app to ask for it; without it a scan still runs but covers only the
locations outside your home folder, and says so rather than letting a short list
pass for a clean one. Removing anything outside your home folder asks for your
administrator password once.

Some jobs it refuses outright - Apple's own software, itself, and system
extensions, which get a section headed "Unroot cannot remove these" with the
exact place to do it yourself.

It does not sit in your menu bar, and nothing watches for you to drag an app to
the Trash - Unroot scans when you open it and does nothing at all the rest of
the time. The one resident piece is a Finder extension, and it stays off until
you switch it on in System Settings -> Extensions -> Finder. After that,
right-clicking an app offers to uninstall it. Where that lands is worth knowing,
because macOS is not consistent about it: in `~/Applications` it is a top-level
item naming the app, and everywhere else - `/Applications` included, which is
where most apps live - it sits in the Services submenu, under the plainer
"Uninstall with Unroot". It removes nothing by
itself. It hands the app your selection, and the same review screen opens.

It is also not a disk cleaner. It looks for the traces of one app you name rather
than for things you could free up, and it never goes near another user's account.

And there is no Mac App Store version, because reading `~/Library`, resetting
permission entries and moving root-owned files are all impossible from inside a
sandbox.

## What it costs, and what else to look at

Unroot needs **macOS 14 or later**, runs on Apple Silicon and Intel, and takes
about 10 MB. It is **pay what you want** with a suggested price of $4.99 - an
amount that genuinely includes zero - and the license is permanent either way.
The full specification is on [the Unroot page](https://swiftfox.studio/apps/unroot).

If what you are chasing is disk space rather than one specific app,
[Sweep](https://swiftfox.studio/apps/sweep) is the neighbor - it files the Downloads folder by rules
you write and bins installers older than a month, covered feature by feature in
[sorting files automatically on a Mac](https://swiftfox.studio/handbook/auto-sort-files-on-mac). There is a
survey of the rest in [Mac utility apps](https://swiftfox.studio/blog/mac-utility-apps).
