Skip to content

feat: on --no-reboot slims the current boot session without a reboot - #42

Merged
Interlap01 merged 2 commits into
mainfrom
feat/on-this-boot
Sep 7, 2026
Merged

feat: on --no-reboot slims the current boot session without a reboot#42
Interlap01 merged 2 commits into
mainfrom
feat/on-this-boot

Conversation

@Interlap01

@Interlap01 Interlap01 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements #38: simslim on <udid> --no-reboot [--profile | --except | --keep] slims a simulator for the current boot session without a reboot. For each label it runs launchctl disable system/<label> then launchctl bootout system/<label>, so the daemon stops now and cannot respawn (disable alone only blocks the next bootstrap; a killed job would just be restarted).

  • Works on every runtime. On iOS 17.x / 18.3, which keep overrides in memory only, it is the only way to slim; the fail-closed rejection from fix: fail closed on non-persistent iOS runtimes #35 now points at the flag. On iOS 18.5+ it is simply the faster path, and the overrides are stored as well.
  • The success line says what the next boot brings: stock again on non-persistent runtimes, slim on persistent ones.
  • status warns when the runtime cannot persist the state, and status --json gains an additive persistent field (extra key, so the GUI decoder is unaffected).

Design decisions from the issue

  1. Asymmetry with off: live slimming only moves toward more-disabled. Managed labels disabled beyond the profile are reported and left alone; off keeps its reboot flow. --no-reboot is rejected together with --preserve-boot-state since a shutdown would discard the result.
  2. Status honesty: persistent on Status, plus a text warning.
  3. Safety re-validation: see below. No label in the full profile wedged the simulator when booted out live, so no separate "safe to bootout" subset was needed.

Robustness

Every profiled managed label is booted out on every run, not only those lacking an override. An override says nothing about whether the job is still loaded, so an earlier run that disabled a label and then failed to boot it out is repaired by re-running. Bootout of an already-missing job exits 3 (No such process) and counts as done; a re-run on an already-slim simulator takes about half the time of the first run.

Validation on real simulators (disposable, deleted afterwards)

Runtime Before After --no-reboot (full profile) Time
iOS 18.3 254 processes, 3.92 GB 101 processes, 1.46 GB 52 s
iOS 26.5 182 processes, 2.43 GB 78 processes, 1.0 GB 58 s

On both: SpringBoard stayed running, Settings and Safari launched, simctl stayed responsive, status reported 170/170 and verify passed, booted-out daemons were still absent from the launchd domain after 60 s and a UI screenshot showed the live Settings screen. On 18.3 simslim off restored stock through its reboot flow. On 26.5 the simulator came up 170/170 slim after a reboot, and a second --no-reboot run reported already slim and stayed responsive.

Tests

  • New fake-xcrun test: iOS 18.3 device, every profiled label gets disable + bootout (including one whose override already existed), bootout exit 3 is accepted, and no shutdown or second boot happens.
  • Flag conflict test for --no-reboot + --preserve-boot-state.
  • Updated the fix: fail closed on non-persistent iOS runtimes #35 rejection message test.
  • make check green.

Reviewed with Codex (gpt-6-astra, high reasoning): the first pass found the retry gap above, which is fixed; the second pass reported no findings.

Closes #38

Add a `--this-boot` flag to `simslim on` that stops the profile's daemons
in the running boot session: each label is `launchctl disable`d and then
`launchctl bootout`ed, so the job leaves the launchd domain now and the
disable override keeps it from being bootstrapped again. No shutdown/boot
cycle.

This is the only slimming possible on runtimes that cannot persist launchd
overrides (iOS 17.x, 18.3; see #34), and a faster no-reboot path on the
ones that can. The persistent-path rejection now points at the flag.

- Every profiled managed label is booted out on every run, not just the
  ones lacking an override, so a run that wrote the override but failed
  to boot the job out is repaired by re-running. A bootout of an
  already-missing job (exit 3) counts as done.
- Live slimming only moves toward more-disabled; `off` keeps its reboot
  flow. `--preserve-boot-state` is rejected with `--this-boot`.
- `status` warns when a runtime cannot persist the state, and
  `status --json` gains an additive `persistent` field.

Validated on disposable simulators with the full 170-label profile:
iOS 18.3 (3.92 GB -> 1.46 GB, 254 -> 101 processes) and iOS 26.5
(2.43 GB -> 1.0 GB, 182 -> 78 processes). SpringBoard, Settings and
Safari stayed responsive; booted-out daemons stayed gone; on 26.5 the
state also survived a reboot.

Closes #38
The flag names what it skips rather than a scope. Library entry point and
test follow: EnableSlimNoReboot, slim_no_reboot_test.go.
@Interlap01 Interlap01 changed the title feat: on --this-boot slims the current boot session without a reboot feat: on --no-reboot slims the current boot session without a reboot Sep 7, 2026
@Interlap01
Interlap01 merged commit f3b979e into main Sep 7, 2026
1 check passed
enumcase added a commit to enumcase/simslim that referenced this pull request Sep 8, 2026
xcodebuild parallel testing creates a stock clone per worker in its own
device set and deletes them per run; disable overrides do not survive
simctl clone, so there is no device to pre-slim. watch polls the device
sets and applies a no-reboot slim to each simulator once it boots, then
leaves it alone, reusing EnableSlimNoReboot from MobAI-App#42.

Answers the ephemeral-clone case raised in MobAI-App#41.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: on --this-boot: slim the current boot session without reboot (works on non-persistent runtimes)

1 participant