From 6301250cc16ba885997ade015fac37f718f02d15 Mon Sep 17 00:00:00 2001 From: Roland Kaibull <6277393+bubleg@users.noreply.github.com> Date: Wed, 7 Oct 2026 05:33:51 +0200 Subject: [PATCH 1/2] fix: keep the sound library when Logic Pro or MainStage uses it --- Sources/removemacai/Storage.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Sources/removemacai/Storage.swift b/Sources/removemacai/Storage.swift index 59aa3fe..4c27988 100644 --- a/Sources/removemacai/Storage.swift +++ b/Sources/removemacai/Storage.swift @@ -38,6 +38,9 @@ enum Storage { ("pages", "Pages", []), ] + /// Apps that share GarageBand's sound library. + static let soundLibraryApps = ["Logic Pro", "Logic Pro X", "MainStage", "MainStage 3"] + /// Finds what can go and how big it is. Slow on big caches; call it off the main thread. static func scan() -> [StorageItem] { var items: [StorageItem] = [] @@ -90,13 +93,16 @@ enum Storage { caveat: "Quit your apps first. Apple's own caches are left alone.", paths: children(home + "/Library/Caches").filter { !($0 as NSString).lastPathComponent.hasPrefix("com.apple.") })) + let sharing = soundLibraryApps.filter { FileManager.default.fileExists(atPath: "/Applications/\($0).app") } for app in appleApps { let path = "/Applications/\(app.app).app" guard FileManager.default.fileExists(atPath: path) else { continue } + let keepExtra = !app.extra.isEmpty && !sharing.isEmpty items.append(files( id: app.id, title: app.app, detail: "One of Apple's optional apps. It reinstalls free from the App Store.", - paths: [path] + app.extra.filter { FileManager.default.fileExists(atPath: $0) })) + caveat: keepExtra ? "Its sound library stays, because \(sharing.joined(separator: " and ")) uses it too." : nil, + paths: [path] + (keepExtra ? [] : app.extra.filter { FileManager.default.fileExists(atPath: $0) }))) } var snapshots = StorageItem( From 08ab59e5c91c9502dd052ef062fe7c1b3e65dd45 Mon Sep 17 00:00:00 2001 From: Roland Kaibull <6277393+bubleg@users.noreply.github.com> Date: Wed, 7 Oct 2026 05:50:04 +0200 Subject: [PATCH 2/2] fix: find Logic Pro and MainStage wherever they are installed --- Sources/removemacai/SelfTest.swift | 3 +++ Sources/removemacai/Storage.swift | 14 +++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Sources/removemacai/SelfTest.swift b/Sources/removemacai/SelfTest.swift index e260482..d284653 100644 --- a/Sources/removemacai/SelfTest.swift +++ b/Sources/removemacai/SelfTest.swift @@ -217,6 +217,9 @@ func selfTest() -> Bool { program: "/Library/PrivilegedHelperTools/dev.orbstack.OrbStack.privhelper", system: true) check(script.owner == "sync.sh" && helper.owner == "OrbStack", "background items are named after what they run") + check(Storage.soundLibraryUsers(["com.apple.finder": "Finder", "com.example.missing": "Missing"]) == ["Finder"], + "apps that share the sound library are found by bundle identifier") + print(failed == 0 ? Term.green("all checks passed") : Term.red("\(failed) failed")) return failed == 0 } diff --git a/Sources/removemacai/Storage.swift b/Sources/removemacai/Storage.swift index 4c27988..a327216 100644 --- a/Sources/removemacai/Storage.swift +++ b/Sources/removemacai/Storage.swift @@ -1,3 +1,4 @@ +import AppKit import Foundation /// Space RemoveMacAI can give back. Files go to the Trash, so nothing is @@ -38,8 +39,15 @@ enum Storage { ("pages", "Pages", []), ] - /// Apps that share GarageBand's sound library. - static let soundLibraryApps = ["Logic Pro", "Logic Pro X", "MainStage", "MainStage 3"] + /// Apps that share GarageBand's sound library, by bundle identifier. + static let soundLibraryApps = ["com.apple.logic10": "Logic Pro", "com.apple.mainstage3": "MainStage"] + + /// The sound library apps installed anywhere Launch Services knows of, + /// including an external disk. + static func soundLibraryUsers(_ apps: [String: String] = soundLibraryApps) -> [String] { + apps.filter { !NSWorkspace.shared.urlsForApplications(withBundleIdentifier: $0.key).isEmpty } + .map(\.value).sorted() + } /// Finds what can go and how big it is. Slow on big caches; call it off the main thread. static func scan() -> [StorageItem] { @@ -93,7 +101,7 @@ enum Storage { caveat: "Quit your apps first. Apple's own caches are left alone.", paths: children(home + "/Library/Caches").filter { !($0 as NSString).lastPathComponent.hasPrefix("com.apple.") })) - let sharing = soundLibraryApps.filter { FileManager.default.fileExists(atPath: "/Applications/\($0).app") } + let sharing = soundLibraryUsers() for app in appleApps { let path = "/Applications/\(app.app).app" guard FileManager.default.fileExists(atPath: path) else { continue }