← /work/mac cleaner pro
# case · 03 / 04 · 2024
● shippingmacOSindiepay-once

Mac Cleaner Pro — native macOS cleaner that breaks down System Data without a subscription.

role
sole engineer · product design
stack
swift 5.9 · swiftui · xpc · next.js
timeline
q2 — q4 2024
pricing
$39 personal · $69 family (5 Macs)
Mac Cleaner Pro — native macOS disk cleaner
mac cleaner pro · v1.0
macOS 13 Ventura+ · universal binary
#01 · the problem
// brief

Apple's System Data bucket is a black box — and subscription cleaners exploit that opacity.

CleanMyMac charges $40/year to do what a transparent, auditable utility should do for a one-time price. Users want to understand what they're deleting, not just click "Clean".

Staged deletion to Trash, 30-day undo, and a signed rule pack mean nothing gets permanently removed without intent.

// product requirements
  • full disk accessnon-sandboxed for deep scan capability
  • privileged helperxpc daemon for protected directory access
  • staged deletionall cleanups go to ~/.Trash/MacCleanerPro/
  • signed rulesed25519 rule pack, verified at runtime
  • zero telemetryfully offline, no usage tracking ever
#02 · system design

Three targets. XPC boundary between app and daemon.

app shell
· swiftui views
· hardened runtime
· full disk access
xpc · ipc
core framework
· 14 scan rules
· taskgroup parallel
· rules engine
privileged helper
· smappservice daemon
· protected directories
· xpc contract
ed25519 verify
rule pack
· signed rule definitions
· updateable separately
· runtime verification
deletion
· ~/.trash/maccleanerpro/
· 30-day undo window
· permanent removal opt-in
module · 01
smart scan
14 cleanup categories run in parallel Swift TaskGroups — user caches, Xcode artifacts, browser caches, app leftovers, logs. Results grouped and ranked by reclaimed size.
module · 02
app uninstaller
Finds leftover support files across 18 system locations per app. Preference plists, application support, launch agents, caches — nothing orphaned behind.
module · 03
large & old files
Walk any folder by size or age with Quick Look preview. Move directly to the staged Trash with one click — no permanent deletion without explicit confirmation.
#03 · engineering detail

14 rules. All parallel. One TaskGroup.

SmartScan.swift
1// all rules run concurrently
2func runSmartScan() async throws -> [ScanResult] {
3 try await withThrowingTaskGroup(of: ScanResult.self) { g in
4 for rule in RulesEngine.verified {
5 g.addTask { try await rule.scan() }
6 }
7 return try await g.reduce(into: []) { $0.append($1) }
8 }
9}
// rule categories
· user caches
· xcode artifacts
· browser caches
· app leftovers
· system logs
· derived data
· simulator runtimes
· crash reports
· mail attachments
· language support
· duplicate fonts
· old ios backups
· unused dmg
· stale pkg files
#04 · the product
24.6GB
avg space reclaimed
14
parallel scan rules
33
core unit tests
$39
pay-once · no subscription
← prev case
Lynkboard
next case →
TradesLynk