ReviewOS

stacks/system-cleaner

Orphan scan misses Application Support and app-named directories (5.6 GB of uninstalled-app data invisible)

#26
Closed glennmichael123 opened this 8 days ago ·
8 days ago

findOrphanedAppData() works, and the safety design is sound — NEVER_DELETE guarding password managers and credentials, a 30-day age threshold, and a check against installed bundle IDs. The problem is reach: it cannot see the directories where apps actually put their bulk.

Evidence

A real case from this machine. Cursor had been uninstalled — no Cursor.app in /Applications, nothing from mdfind — yet 5.6 GB of its data remained, none of which the orphan scan could surface:

PathSizeWhy it was missed
~/Library/Application Support/Cursor4.1Gdirectory not in ORPHAN_DIRS, and Cursor is not a reverse-DNS name
~/.cursor1.0Gdotfile in $HOME, outside every scanned root
~/.local/share/cursor-agent355MXDG data path, outside every scanned root
~/Library/Application Support/Caches/cursor-updater144Mnested under Application Support, not scanned

Inside the 4.1 GB: 3.7 GB of User/globalStorage (a 1.7 GB agent worker directory, a 1.0 GB state.vscdb and a 1.0 GB .backup of it) plus 384 MB of User/History.

Two independent causes

1. ORPHAN_DIRS omits Application Support (packages/clean/src/orphans.ts):

const ORPHAN_DIRS = [
  { basePath: macPaths.caches,       ... },
  { basePath: macPaths.logs,         ... },
  { basePath: macPaths.savedState,   ... },
  { basePath: macPaths.webkit,       ... },
  { basePath: macPaths.httpStorages, ... },
]

Caches and logs are the small leftovers. Application Support is where an uninstalled app leaves gigabytes — it is the highest-value root for this feature and the one not covered.

2. The name pattern only matches reverse-DNS:

const BUNDLE_ID_PATTERN = /^(com|org|net|io)\.[a-z]/i

Plenty of apps name their directory after the app, not the bundle ID — Cursor, Code, Slack, Postman, Notion. Every one of those is invisible today even inside the roots that are scanned.

Proposed

  • Add ~/Library/Application Support to ORPHAN_DIRS, and ~/Library/Containers and ~/Library/Group Containers alongside it.
  • Match two name shapes: the existing reverse-DNS pattern, and a plain app-name form resolved against installed app names (from readAppInfoPlist's CFBundleName / CFBundleDisplayName) rather than bundle IDs alone.
  • Add an opt-in set of non-Library roots for dotfile and XDG leftovers — ~/.<appname>, ~/.local/share/<appname>, ~/.config/<appname>. These need care: ~/.ssh, ~/.gnupg, ~/.aws and similar must be excluded, and the existing NEVER_DELETE list is the right mechanism, extended with path-based rules.

Safety notes

Application Support holds real user data, not just caches, so this needs more care than the cache/log roots do:

  • Keep the 30-day age threshold, and consider raising it for this root specifically.
  • Never auto-select. These should be reported for explicit confirmation, with size and last-modified shown per item.
  • Flag the ones that may hold recoverable user content. conversation-search.db in Cursor's globalStorage held past AI conversations — worth surfacing as "may contain data you cannot read without the app" rather than deleting silently.
  • Project-local build caches, the other blind spot found in the same audit — tracked separately.

Sign in to comment on this issue.