Model or dataset
MobAI-App/simslim avatar
MobAI-App/simslim

simslim: Cut iOS Simulator Memory by Disabling Daemons You Do Not Need

Run more iOS simulators on one Mac by disabling background daemons a simulator doesn't need

1,947 stars69 forksGoMIT

At a glance

What is it?
simslim is a macOS-only Go CLI that turns off roughly 170 background launchd services in a booted iOS Simulator, and the README reports memory falling from 4.0 GB to 0.9 GB on one M1 Pro. It is built for people who need many simulators at once, not for anyone who needs Siri or iCloud inside the simulator.
Who is it for?
Adopt simslim if you run several simulators on one Mac, especially for CI or agent-driven test fleets, and you can live without Siri, Spotlight, iCloud sync or push inside the simulator. Do not adopt it if your tests exercise those subsystems, and do not run it on Linux or Windows, since it drives xcrun simctl and is macOS only.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem simslim solves: 180 daemons per simulator

A freshly booted iOS Simulator starts around 180 background services, according to the README: Siri, Spotlight indexing, photo analysis, News, wallpaper posters, iCloud sync. None of them do anything for a test run, but each one holds memory. On a 16 GB M1 Pro the README reports a stock simulator settling at 4.0 GB of phys_footprint and 258 processes, against 0.9 GB and 70 processes after slimming. The audience follows from that: developers running several simulators in parallel, and CI jobs that boot a fleet on a shared macOS runner. The README's own example is 12 slim simulators on one 16 GB M1 Pro, each driven by an agent, where stock simulators start thrashing at around 5. If you boot one simulator at a time and close it before the next, simslim buys you little.

How simslim works: launchd label control through simctl

simslim is a Go binary that shells out to xcrun simctl and manipulates launchd inside the simulator. The repository layout reflects that split: simctl.go wraps the Apple tooling, slim.go applies the disable pass, profiles.go and service_descriptions.go hold the category definitions, and verify.go checks the result against a profile file. The slim pass is not a single command. According to the README, simslim on boots the simulator, disables roughly 170 daemons one launchctl call at a time, then reboots, all under a single 10-minute deadline. Each individual launchctl transition carries its own 2-minute bound, and failed transitions are retried automatically. That per-daemon loop is why slow hosts fail: a cold boot can push the first transitions past 2 minutes, and the whole pass past 10, producing context deadline exceeded errors mid-reconfigure. The two timeout flags, --boot-timeout and --spawn-timeout, exist precisely because the loop is long and serial. Two commands answer different questions and the README is explicit about the distinction. status counts only the allowlisted launchd labels SimSlim manages, so it is not a live-process count; a slim boot still runs required core services plus system apps and extensions. measure walks every process under that simulator's launchd_sim and sums phys_footprint. The README warns that summing ps RSS values is not comparable, because RSS counts shared mappings once per process that maps them.

Installing simslim and slimming a first simulator

The README gives two install paths, both macOS only, and both require Xcode with an iOS Simulator runtime because simslim drives simulators through xcrun simctl. Homebrew first:

bash
brew install mobai-app/tap/simslim

The Go toolchain alternative installs the same binary from source:

bash
go install github.com/mobai-app/simslim/cmd/simslim@latest

Before changing anything, list what you have. The list command shows simulators and their slim status, and --booted narrows it to running ones:

bash
simslim list --booted

The README recommends cloning before service or disk changes so the copy can serve as a backup. Take that advice literally:

bash
simslim clone <udid> <name>

Now slim the original. This boots the simulator, disables the daemons, and reboots it slim:

bash
simslim on <udid>

If the machine is a slow shared runner, raise the global deadline before the pass starts, either per command or for the whole job:

bash
simslim on <udid> --boot-timeout 15m
export SIMSLIM_BOOT_TIMEOUT=15m

After the reboot, measure the result. The README says measure prints phys_footprint, the figure Activity Monitor shows, which counts compressed and swapped pages:

bash
simslim measure <udid>

Two escape hatches keep a category you actually need. Keeping Spotlight search:

bash
simslim on <udid> --except search

Or keeping one specific daemon, push notifications:

bash
simslim on <udid> --keep com.apple.apsd

To undo everything, simslim off <udid> puts the simulator back to stock.

What a slim boot costs you: the categories table

Slimming is subtraction, and the README publishes the full catalogue of what gets removed across 15 categories. The largest single category is widgets at roughly 675 MB, covering Home and lock screen posters, widgets and Live Activities. Siri and Apple Intelligence is listed at about 265 MB, and the catch-all other category at 195 MB, covering Wallet, business services, assets and miscellaneous daemons. Smaller entries matter too: search at 50 MB, icloud at 100 MB, store at 80 MB for App Store, push notification, StoreKit and media services, and web at 50 MB for Safari sync, web push, privacy and universal-link services. The README states these figures are iOS 26.5 clean-boot medians and are not additive, and that memory estimates are guidance rather than additive savings, pointing to docs/category-memory.md for the method. That caveat is honest and worth repeating: you cannot add the column and predict your savings. The practical consequence is that a test suite touching push notifications, StoreKit or universal links will break under a default slim boot. simslim doctor exists for that: simslim doctor <udid> --requires push,storekit,universal-links checks whether the capabilities you name are still available after the pass.

Verify and profile files: making slimming reproducible in CI

An ad-hoc simslim on call is not reproducible, which is a problem when the same CI job must produce the same environment twice. The README's answer is profile files, committed alongside the test code, plus simslim verify <udid> --profile ci.json, which checks for an exact profile match and exits non-zero on drift. That combination is the strongest part of the design: the profile is the contract, verify is the gate, and drift fails the build instead of turning into a test that passes locally and fails on the runner. The README notes that read-only and simulator-management commands accept --json for integrations and the macOS app, so the same state can be consumed by tooling rather than scraped from terminal output. The repository ships profile_file.go and profile_file_test.go, which is where the parsing and matching live. What the README does not document is rollback semantics for a partially applied profile: if the pass dies mid-reconfigure, the simulator is left in an intermediate state, and the documented recovery path is simslim off <udid> followed by another attempt with a longer timeout. There is no documented resume-from-checkpoint behaviour.

Where simslim is the wrong tool

Three cases argue against it. First, any test that depends on the disabled subsystems: push notification delivery, StoreKit purchase flows, universal links, iCloud sync, HealthKit or HomeKit. The --except and --keep flags let you keep a category or a single daemon, but each exception gives back the memory you were trying to reclaim, and the README's numbers are medians, not guarantees, so the trade is not linear. Second, single-simulator workflows. The whole premise is fitting more simulators on one machine; if you boot one at a time, the reboot cycle that simslim on performs costs more than the memory it frees. Third, non-macOS hosts. simslim is macOS only and requires Xcode with an iOS Simulator runtime, so it has no place in a Linux container pipeline. There is also a measurement trap: the README explicitly says status is not a live-process count, and that summing ps RSS values is not comparable to phys_footprint. Anyone who benchmarks simslim with ps and reports a number is measuring something else. The README also notes SimSlim recommends cloning before service or disk changes, which is an acknowledgement that the operations are not trivially reversible.

Alternatives and the difference in approach

The most direct alternative is not another tool but the simulator's own lifecycle management through xcrun simctl: create, boot, erase and delete simulators, and accept stock memory per boot. The difference is that simctl has no concept of disabling background daemons, so the only lever is running fewer simulators. simslim's approach is to change what a booted simulator contains, not how many you start, which is why the README frames the result as going from a handful of simulators to a screenful on the same laptop. A second alternative is running the tests on a larger machine or a hosted CI fleet with more RAM per job: that scales horizontally and requires no knowledge of which daemons matter, but it costs money per runner and does not reduce the memory any single simulator consumes. A third is the SimSlim macOS app itself, which the README describes as bundling the CLI and adding searchable status, disk-size and live RAM columns, per-daemon controls with purpose summaries, read-only disk analysis plus confirmed cleanup of allowlisted data, and clone, rename, erase, delete and Finder shortcuts. The app is built locally with make app and opened from build/SimSlim.app; it is a convenience layer over the same binary, not a different mechanism. On disk rather than memory, simslim also exposes disk-plan for read-only measurement and disk-clean --categories caches,logs --confirm <udid> for confirmed cleanup, which competes with manually deleting simulator data directories.

Licence, maintenance and upgrade cost

simslim is MIT licensed, which permits commercial and internal use with the usual requirement to carry the licence text; this is a description of the licence identifier in the repository, not legal advice, and anyone redistributing the bundled SwiftUI app should check the packaging directory and gui/Info.plist for what ships alongside the Go binary. The repository is not archived and the last push was on 2026-09-16, the same day as the v0.9.0 release, following v0.8.0 on 2026-08-31 and v0.7.0 on 2026-08-30. That is a fast release cadence over a short window, and the practical upgrade cost sits in the category definitions rather than the CLI surface: profiles.go and service_descriptions.go encode which daemons belong to which category, and a new iOS runtime can rename, add or remove services. Anyone pinning simslim in CI should pin the version and re-run simslim verify against the committed profile after every simulator runtime upgrade, because the profile match is what tells you the daemon set still lines up. The Makefile's check target runs go test ./..., go vet, swift-format lint on gui, a zsh syntax check on scripts/build-app.sh and plutil -lint on gui/Info.plist, which is a reasonable signal of what the maintainers gate on. The README does not document a deprecation policy or a supported-runtime matrix, so the iOS 26.5 medians are the only runtime version named.

Editorial conclusion

Adopt simslim if you run several simulators on one Mac, especially for CI or agent-driven test fleets, and you can live without Siri, Spotlight, iCloud sync or push inside the simulator. Do not adopt it if your tests exercise those subsystems, and do not run it on Linux or Windows, since it drives xcrun simctl and is macOS only. Before committing, clone a simulator, run simslim on <udid>, then simslim doctor <udid> --requires with the capabilities your test suite actually needs, and check simslim verify <udid> --profile against a committed profile file so drift fails the job instead of surfacing as a flaky test.

Frequently asked questions

How do I install simslim?

The README gives two routes on macOS: brew install mobai-app/tap/simslim, or go install github.com/mobai-app/simslim/cmd/simslim@latest. Both require Xcode with an iOS Simulator runtime, because simslim drives simulators through xcrun simctl.

How much memory does simslim save per iOS Simulator?

The README reports one M1 Pro 16 GB simulator going from 258 processes and 4.0 GB to 70 processes and 0.9 GB, measured as phys_footprint. The per-category figures in the table are iOS 26.5 clean-boot medians and the README states they are not additive.

What is the difference between simslim status and simslim measure?

status counts only the allowlisted launchd labels SimSlim manages, so it is not a live-process count, and a slim boot still runs required core services plus system apps and extensions. measure walks every process under that simulator's launchd_sim and sums phys_footprint, the figure Activity Monitor shows.

Can I keep Siri, Spotlight or push notifications in a slim simulator?

Yes, with exceptions. simslim on <udid> --except search keeps a whole category such as Spotlight, and simslim on <udid> --keep com.apple.apsd keeps one specific daemon such as push notifications. Each exception returns some of the memory you were trying to reclaim.

Why does simslim on fail with context deadline exceeded on CI runners?

The README states that simslim on disables roughly 170 daemons one launchctl call at a time under a single 10-minute deadline, and that shared CI runners are slower and less predictable. Raise the limit with --boot-timeout 15m or SIMSLIM_BOOT_TIMEOUT=15m, and raise the per-transition bound with --spawn-timeout 5m or SIMSLIM_SPAWN_TIMEOUT=5m.

Official sources

  1. Issues
  2. License: MIT
  3. MobAI-App/simslim on GitHub
  4. README
  5. Releases
Community notes

Community notes