mix mob.uninstall (mob_dev v0.5.1)

Copy Markdown View Source

Uninstall a Mob app from one or more connected devices.

By default, uninstalls the current project's app from the auto-detected device (when exactly one device is connected). For other scopes, pass the relevant flag.

Usage

mix mob.uninstall                                    # this app, one device
mix mob.uninstall --all-devices                      # this app, all emulators/sims (NOT phones)
mix mob.uninstall --all-physical                     # this app, every physical device
mix mob.uninstall --all-devices --all-physical       # literally everything
mix mob.uninstall --device emulator-5554             # this app, one named device
mix mob.uninstall --device foo --device bar          # this app, several
mix mob.uninstall --all-apps                         # one device, every mob app
mix mob.uninstall --all-devices --all-apps           # every mob app on every emulator/sim
mix mob.uninstall --bundle-id com.x.y                # override the project's bundle_id
mix mob.uninstall --bundle-prefix com.acme           # override the prefix for --all-apps
mix mob.uninstall --yes                              # skip the confirmation prompt
mix mob.uninstall --help                             # this help
mix mob.uninstall -h                                 # this help

Options

  • --device <id> — Target a specific device by serial or name. Repeat for multiple devices: --device a --device b. Works for any device type — --device is the explicit override that bypasses the emulator/physical filter.
  • --all-devices — Target every connected emulator or simulator. Physical devices are NEVER swept by this flag — that requires --all-physical or --device <id> explicitly. Rationale: emulators are disposable; physical devices are someone's personal phone, with potential to do real damage.
  • --all-physical — Target every connected physical device (iPhones over USB/Wi-Fi, Android devices via adb). Opt-in. Composes with --all-devices to mean "literally everything."
  • --bundle-id <id> — Uninstall this specific bundle id instead of auto-detecting the project's.
  • --all-apps — Match every installed package whose id starts with bundle_prefix (defaults to MOB_BUNDLE_PREFIX env or com.example). Useful for clearing stale test apps in one shot.
  • --bundle-prefix <prefix> — Override the prefix used by --all-apps. Defaults to MobDev.Config.bundle_prefix/0.
  • --yes — Skip the y/N confirmation prompt. The prompt is skipped automatically when targeting exactly one app on exactly one device (low blast radius).
  • --help / -h — Print this help text.

Default scope behaviour

When you pass no flags:

  • 0 devices connected → exit with "no devices found"
  • 1 emulator/sim connected → auto-target it (physical devices are never the auto-target — they require explicit selection)
  • 1 devices or only physical devices → exit with an instruction to pass --device, --all-devices, or --all-physical. Never silently fans out without consent.

Per-platform mechanics

  • Androidadb -s <serial> uninstall <pkg>. "Unknown package" responses bucket as skipped (the app wasn't installed), everything else non-zero is a failure.
  • iOS simulatorxcrun simctl uninstall <udid> <bundle>, followed by a probe through simctl listapps to distinguish actual uninstall from "wasn't installed in the first place".
  • iOS physical devicexcrun devicectl device uninstall app --device <udid> <bundle>. ContainerLookupErrorDomain in output → not installed (skipped). Requires the device to be paired and trusted via Xcode.

Summary

Functions

Build the summary lines for an uninstall run. Pure — pinned by tests in test/mix/tasks/mob_uninstall_test.exs. Public so the rendering invariants (skipped never gets counted as failed, etc.) can be asserted independent of connected hardware.

Decides whether to skip the y/N confirmation prompt before executing a plan. Returns true when

Functions

format_summary(uninstalled, failed, skipped)

Build the summary lines for an uninstall run. Pure — pinned by tests in test/mix/tasks/mob_uninstall_test.exs. Public so the rendering invariants (skipped never gets counted as failed, etc.) can be asserted independent of connected hardware.

should_skip_prompt?(plan, opts)

@spec should_skip_prompt?(
  MobDev.Uninstaller.plan(),
  keyword()
) :: boolean()

Decides whether to skip the y/N confirmation prompt before executing a plan. Returns true when:

  • the user passed --yes (any truthy value at opts[:yes]), OR
  • the plan targets exactly one device with exactly one bundle id (low blast radius — destructive intent is unambiguous and the preview already showed exactly what's about to happen).

Pure for testability — the original inline opts[:yes] or single_target? form crashed on BadBooleanError because opts[:yes] is nil when the flag isn't passed and Elixir 1.20's type checker enforces boolean operands on or. Pinning this as a helper means the boolean-coercion mistake can't happen again.