mirror of
https://github.com/MobAI-App/simslim.git
synced 2026-09-27 17:02:00 +02:00
The repo root becomes `package simslim`, an importable library holding every piece of slimming logic; the CLI moves to `cmd/simslim`. Previously everything was `package main`, so nothing here could be imported at all. The library carries no external dependencies — urfave/cli stays on the CLI side, along with all terminal-facing code: the interactive profile wizard, writeJSON, truncate/humanBytes, fatal and usage. The library never writes to stdout; it returns values and reports progress through the Reporter callback. Renames forced by collisions with existing types: status() -> ReadStatus, statusForDevice() -> ReadStatusForDevice, diskCleanupPlan() -> PlanDiskCleanup. The shutdown/boot timeouts move to simctl.go as ShutdownTimeout/BootTimeout. `go install` gains a path element: github.com/mobai-app/simslim/cmd/simslim. The installed binary is still named simslim, and -X main.version still applies. packaging/homebrew/simslim.rb.in is updated to match, since std_go_args passes no package path. Verified live against a real simulator: list, profiles, status, doctor, size, disk-plan, measure, boot, shutdown, on, off, on --except, on --profile, clone, rename, delete and the interactive wizard all behave identically to the previous build. JSON output, human output, help text and exit codes are unchanged.
426 lines
13 KiB
Go
426 lines
13 KiB
Go
package simslim
|
|
|
|
import "sort"
|
|
|
|
// Category groups launchd daemon labels that a slim boot disables together.
|
|
type Category struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Downside string `json:"downside"`
|
|
ApproxMemoryMB int `json:"approxMemoryMB"`
|
|
Labels []string `json:"labels"`
|
|
ServiceDescriptions map[string]string `json:"serviceDescriptions"`
|
|
AlwaysEnabled []AlwaysEnabledService `json:"alwaysEnabled,omitempty"`
|
|
}
|
|
|
|
// AlwaysEnabledService is shown alongside a category for transparency but is
|
|
// never included in a slim profile. Earlier versions may have disabled it, so
|
|
// it remains in the mutation allowlist solely to repair that legacy state.
|
|
type AlwaysEnabledService struct {
|
|
Label string `json:"label"`
|
|
Reason string `json:"reason"`
|
|
}
|
|
|
|
// Categories is the complete allowlist of daemons a profile may disable.
|
|
// ApproxMemoryMB values are rounded median increases in phys_footprint when
|
|
// only that category is kept on versus a fully slim iOS 26.5 clean boot. The
|
|
// estimates vary by runtime and workload and are not additive.
|
|
var Categories = []Category{
|
|
{
|
|
ID: "widgets",
|
|
Name: "Widgets & Wallpaper",
|
|
Description: "Home and lock screen posters, widgets, and Live Activities.",
|
|
Downside: "Home and Lock Screen widgets, wallpaper posters, and Live Activities stop updating.",
|
|
ApproxMemoryMB: 675,
|
|
Labels: []string{
|
|
"com.apple.PosterBoard",
|
|
"com.apple.chronod",
|
|
"com.apple.liveactivitiesd",
|
|
},
|
|
},
|
|
{
|
|
ID: "siri",
|
|
Name: "Siri & Intelligence",
|
|
Description: "Siri, Apple Intelligence, speech, and on-device ML model services.",
|
|
Downside: "Siri, speech features, and Apple Intelligence services are unavailable.",
|
|
ApproxMemoryMB: 265,
|
|
Labels: []string{
|
|
"com.apple.assistantd",
|
|
"com.apple.assistant_cdmd",
|
|
"com.apple.assistant_service",
|
|
"com.apple.siriactionsd",
|
|
"com.apple.siriinferenced",
|
|
"com.apple.siriknowledged",
|
|
"com.apple.sirittsd",
|
|
"com.apple.siri.context.service",
|
|
"com.apple.siri.acousticsignature",
|
|
"com.apple.corespeechd",
|
|
"com.apple.voiced",
|
|
"com.apple.voicebankingd",
|
|
"com.apple.speechmodeltrainingd",
|
|
"com.apple.intelligenceplatformd",
|
|
"com.apple.intelligencecontextd",
|
|
"com.apple.intelligenceflowd",
|
|
"com.apple.intelligencetasksd",
|
|
"com.apple.generativeexperiencesd",
|
|
"com.apple.knowledgeconstructiond",
|
|
"com.apple.naturallanguaged",
|
|
"com.apple.textunderstandingd",
|
|
"com.apple.modelcatalogd",
|
|
"com.apple.modelmanagerd",
|
|
"com.apple.mlhostd",
|
|
"com.apple.mlruntimed",
|
|
"com.apple.suggestd",
|
|
"com.apple.parsecd",
|
|
"com.apple.parsec-fbf",
|
|
"com.apple.proactiveeventtrackerd",
|
|
},
|
|
},
|
|
{
|
|
ID: "search",
|
|
Name: "Spotlight & Search",
|
|
Description: "On-device Spotlight and in-Settings search services.",
|
|
Downside: "Spotlight and Settings search return no results.",
|
|
ApproxMemoryMB: 50,
|
|
Labels: []string{
|
|
"com.apple.searchd",
|
|
"com.apple.searchtoold",
|
|
"com.apple.spotlightknowledged",
|
|
"com.apple.spotlightknowledged.updater",
|
|
"com.apple.corespotlightservice",
|
|
},
|
|
},
|
|
{
|
|
ID: "icloud",
|
|
Name: "iCloud & Apple Account",
|
|
Description: "iCloud sync, Apple Account, keychain, and backup services.",
|
|
Downside: "iCloud sync, Apple Account, Keychain, and backup workflows will not work.",
|
|
ApproxMemoryMB: 100,
|
|
Labels: []string{
|
|
"com.apple.appleaccountd",
|
|
"com.apple.appleaccounttransparencyd",
|
|
"com.apple.appleidsetupd",
|
|
"com.apple.akd",
|
|
"com.apple.amsaccountsd",
|
|
"com.apple.amsengagementd",
|
|
"com.apple.amsondevicestoraged",
|
|
"com.apple.cloudd",
|
|
"com.apple.cloudphotod",
|
|
"com.apple.ckdiscretionaryd",
|
|
"com.apple.cloudsettingssyncagent",
|
|
"com.apple.bird",
|
|
"com.apple.syncdefaultsd",
|
|
"com.apple.cdpd",
|
|
"com.apple.sosd",
|
|
"com.apple.SecureBackupDaemon",
|
|
"com.apple.TrustedPeersHelper",
|
|
"com.apple.protectedcloudstorage.protectedcloudkeysyncing",
|
|
"com.apple.icloudmailagent",
|
|
"com.apple.icloudsubscriptionoptimizerd",
|
|
"com.apple.communicationtrustd",
|
|
},
|
|
},
|
|
{
|
|
ID: "store",
|
|
Name: "App Store, Push & Media",
|
|
Description: "App Store, push notification, StoreKit, and media services.",
|
|
Downside: "Remote push notifications and StoreKit or App Store testing will not work.",
|
|
ApproxMemoryMB: 80,
|
|
Labels: []string{
|
|
"com.apple.appstored",
|
|
"com.apple.appstorecomponentsd",
|
|
"com.apple.apsd",
|
|
"com.apple.itunescloudd",
|
|
"com.apple.itunesstored",
|
|
"com.apple.storekitd",
|
|
"com.apple.videosubscriptionsd",
|
|
"com.apple.assetsubscriptiond",
|
|
"com.apple.musicd",
|
|
},
|
|
},
|
|
{
|
|
ID: "pim",
|
|
Name: "Mail, Calendar & Contacts",
|
|
Description: "Mail, Calendar, Contacts, Reminders, and related sync services.",
|
|
Downside: "Contacts, Calendar, Reminders, and Mail-backed pickers or sync may fail.",
|
|
ApproxMemoryMB: 80,
|
|
Labels: []string{
|
|
"com.apple.email.maild",
|
|
"com.apple.exchangesyncd",
|
|
"com.apple.dataaccess.dataaccessd",
|
|
"com.apple.calaccessd",
|
|
"com.apple.remindd",
|
|
"com.apple.contactsd",
|
|
"com.apple.contacts.postersyncd",
|
|
"com.apple.peopled",
|
|
},
|
|
},
|
|
{
|
|
ID: "web",
|
|
Name: "Safari Sync & Web Services",
|
|
Description: "Safari sync, web push, privacy, and universal-link services.",
|
|
Downside: "Universal links and Safari sync or background web services will not work.",
|
|
ApproxMemoryMB: 50,
|
|
Labels: []string{
|
|
"com.apple.SafariBookmarksSyncAgent",
|
|
"com.apple.Safari.History",
|
|
"com.apple.Safari.passwordbreachd",
|
|
"com.apple.Safari.SafeBrowsing.Service",
|
|
"com.apple.safarifetcherd",
|
|
"com.apple.WebBookmarks.webbookmarksd",
|
|
"com.apple.webkit.adattributiond",
|
|
"com.apple.webkit.webpushd",
|
|
"com.apple.webprivacyd",
|
|
"com.apple.swcd",
|
|
},
|
|
},
|
|
{
|
|
ID: "family",
|
|
Name: "Family & Screen Time",
|
|
Description: "Family Sharing, Screen Time, and usage tracking.",
|
|
Downside: "Family Sharing, Screen Time, and usage tracking stop working.",
|
|
ApproxMemoryMB: 65,
|
|
Labels: []string{
|
|
"com.apple.familycircled",
|
|
"com.apple.FamilyControlsAgent",
|
|
"com.apple.familynotification",
|
|
"com.apple.askpermissiond",
|
|
"com.apple.asktod",
|
|
"com.apple.ScreenTimeAgent",
|
|
"com.apple.ScreenTimeSettingsAgent",
|
|
"com.apple.UsageTrackingAgent",
|
|
},
|
|
},
|
|
{
|
|
ID: "health",
|
|
Name: "Health, Home & Fitness",
|
|
Description: "HealthKit, HomeKit, and Fitness services.",
|
|
Downside: "HealthKit, HomeKit, and Fitness integrations will not work.",
|
|
ApproxMemoryMB: 135,
|
|
Labels: []string{
|
|
"com.apple.healthd",
|
|
"com.apple.healthappd",
|
|
"com.apple.healthcontentd",
|
|
"com.apple.healtheventsd",
|
|
"com.apple.healthrecordsd",
|
|
"com.apple.finhealthd",
|
|
"com.apple.homed",
|
|
"com.apple.homeeventsd",
|
|
"com.apple.fitcore",
|
|
"com.apple.fitcore.session",
|
|
"com.apple.fitnesscoachingd",
|
|
"com.apple.fitnessintelligenced",
|
|
"com.apple.activityawardsd",
|
|
"com.apple.activitysharingd",
|
|
},
|
|
},
|
|
{
|
|
ID: "photos",
|
|
Name: "Photos & Media Analysis",
|
|
Description: "Photos library, photo analysis, and media analysis services.",
|
|
Downside: "Photo picker, Photos-library workflows, and media analysis may fail.",
|
|
ApproxMemoryMB: 60,
|
|
Labels: []string{
|
|
"com.apple.photoanalysisd",
|
|
"com.apple.photosface",
|
|
"com.apple.mediaanalysisd",
|
|
"com.apple.mediaanalysisd.service",
|
|
"com.apple.mediastream.mstreamd",
|
|
"com.apple.medialibraryd",
|
|
"com.apple.assetsd",
|
|
"com.apple.assetsd.nebulad",
|
|
},
|
|
},
|
|
{
|
|
ID: "apps",
|
|
Name: "News, Weather, Maps & Games",
|
|
Description: "News, Weather, Maps, Tips, and game services.",
|
|
Downside: "News, Weather, Maps background data, and game-controller services are unavailable.",
|
|
ApproxMemoryMB: 90,
|
|
Labels: []string{
|
|
"com.apple.newsd",
|
|
"com.apple.weatherd",
|
|
"com.apple.Maps.mapssyncd",
|
|
"com.apple.Maps.mapspushd",
|
|
"com.apple.Maps.geocorrectiond",
|
|
"com.apple.maps.destinationd",
|
|
"com.apple.MapKit.SnapshotService",
|
|
"com.apple.jetpackassetd",
|
|
"com.apple.tipsd",
|
|
"com.apple.gamed",
|
|
"com.apple.gamesaved",
|
|
"com.apple.GameController.gamecontrollerd",
|
|
},
|
|
},
|
|
{
|
|
ID: "messaging",
|
|
Name: "Messaging & FaceTime",
|
|
Description: "iMessage, FaceTime, call, and identity services.",
|
|
Downside: "iMessage, FaceTime, and related identity services will not work.",
|
|
ApproxMemoryMB: 60,
|
|
Labels: []string{
|
|
"com.apple.identityservicesd",
|
|
"com.apple.ids_simd",
|
|
"com.apple.imautomatichistorydeletionagent",
|
|
"com.apple.imcore.imtransferagent",
|
|
"com.apple.imdpersistence.IMDPersistenceAgent",
|
|
"com.apple.facetimemessagestored",
|
|
"com.apple.telephonyutilities.callservicesd",
|
|
},
|
|
},
|
|
{
|
|
ID: "connectivity",
|
|
Name: "Sharing & Device Connectivity",
|
|
Description: "AirDrop, Continuity, CarPlay, Watch, and Find My services.",
|
|
Downside: "AirDrop, Continuity, CarPlay, Watch, and Find My connectivity will not work.",
|
|
ApproxMemoryMB: 65,
|
|
Labels: []string{
|
|
"com.apple.rapportd",
|
|
"com.apple.companiond",
|
|
"com.apple.carkitd",
|
|
"com.apple.wcd",
|
|
"com.apple.tvremoted",
|
|
"com.apple.avatarsd",
|
|
"com.apple.stickersd",
|
|
"com.apple.sociallayerd",
|
|
"com.apple.announced",
|
|
"com.apple.navd",
|
|
"com.apple.findmy.findmylocated",
|
|
},
|
|
AlwaysEnabled: []AlwaysEnabledService{
|
|
{
|
|
Label: "com.apple.sharingd",
|
|
Reason: "Required for system share sheets.",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "telemetry",
|
|
Name: "Ads, Diagnostics & Telemetry",
|
|
Description: "DeviceCheck, ad privacy, analytics, diagnostics, and feedback services.",
|
|
Downside: "DeviceCheck plus analytics, diagnostics, and feedback services are unavailable.",
|
|
ApproxMemoryMB: 105,
|
|
Labels: []string{
|
|
"com.apple.ap.adprivacyd",
|
|
"com.apple.ap.promotedcontentd",
|
|
"com.apple.diagnosticextensionsd",
|
|
"com.apple.feedbackd",
|
|
"com.apple.rtcreportingd",
|
|
"com.apple.securityuploadd",
|
|
"com.apple.geoanalyticsd",
|
|
"com.apple.triald",
|
|
"com.apple.followupd",
|
|
"com.apple.purplebuddy.budd",
|
|
"com.apple.devicecheckd",
|
|
},
|
|
},
|
|
{
|
|
ID: "other",
|
|
Name: "Other Background Services",
|
|
Description: "Wallet, business services, assets, and miscellaneous background daemons.",
|
|
Downside: "Wallet, merchant, business, asset, and miscellaneous background services are unavailable.",
|
|
ApproxMemoryMB: 195,
|
|
Labels: []string{
|
|
"com.apple.financed",
|
|
"com.apple.passd",
|
|
"com.apple.merchantd",
|
|
"com.apple.coreidvd",
|
|
"com.apple.businessservicesd",
|
|
"com.apple.deviceaccessd",
|
|
"com.apple.replicatord",
|
|
"com.apple.linkd",
|
|
"com.apple.ind",
|
|
"com.apple.storagedatad",
|
|
"com.apple.StatusKitAgent",
|
|
"com.apple.countryd",
|
|
"com.apple.mobileassetd",
|
|
"com.apple.managedconfiguration.passcodenagd",
|
|
},
|
|
},
|
|
}
|
|
|
|
func CategoryByID(id string) (Category, bool) {
|
|
for _, c := range Categories {
|
|
if c.ID == id {
|
|
return c, true
|
|
}
|
|
}
|
|
return Category{}, false
|
|
}
|
|
|
|
// slimmableSet is every label a service profile may disable.
|
|
func SlimmableSet() map[string]bool {
|
|
set := make(map[string]bool)
|
|
for _, c := range Categories {
|
|
for _, l := range c.Labels {
|
|
set[l] = true
|
|
}
|
|
}
|
|
return set
|
|
}
|
|
|
|
// managedSet is the complete mutation allowlist. Most labels are slimmable;
|
|
// required labels may only transition back to enabled for compatibility.
|
|
func managedSet() map[string]bool {
|
|
set := SlimmableSet()
|
|
for _, category := range Categories {
|
|
for _, service := range category.AlwaysEnabled {
|
|
set[service.Label] = true
|
|
}
|
|
}
|
|
return set
|
|
}
|
|
|
|
// Profile selects which managed daemons a slim boot should disable.
|
|
type Profile struct {
|
|
ExceptCategories map[string]bool // category IDs to leave fully enabled
|
|
Keep map[string]bool // individual labels to leave enabled
|
|
}
|
|
|
|
// desired returns the labels this profile wants disabled.
|
|
func (p Profile) Desired() map[string]bool {
|
|
set := make(map[string]bool)
|
|
for _, c := range Categories {
|
|
if p.ExceptCategories[c.ID] {
|
|
continue
|
|
}
|
|
for _, l := range c.Labels {
|
|
if p.Keep[l] {
|
|
continue
|
|
}
|
|
set[l] = true
|
|
}
|
|
}
|
|
return set
|
|
}
|
|
|
|
// delta returns the launchctl transitions to move from current to desired,
|
|
// scoped to managed labels. Labels outside managed are never touched: a
|
|
// non-managed desired label is ignored, and a non-managed label that is already
|
|
// disabled is left disabled. Empty results mean the device is already correct.
|
|
func delta(current, desired, managed map[string]bool) (toDisable, toEnable []string) {
|
|
dis := map[string]bool{}
|
|
for l := range desired {
|
|
if managed[l] && !current[l] {
|
|
dis[l] = true
|
|
}
|
|
}
|
|
en := map[string]bool{}
|
|
for l := range current {
|
|
if managed[l] && !desired[l] {
|
|
en[l] = true
|
|
}
|
|
}
|
|
return keys(dis), keys(en)
|
|
}
|
|
|
|
func keys(set map[string]bool) []string {
|
|
out := make([]string, 0, len(set))
|
|
for k := range set {
|
|
out = append(out, k)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|