Builds commands for shelling into an app's sandbox on a device.
The recurring chore this removes: on Android, poking around the app's
private data dir needs adb shell run-as <bundle>; on iOS Simulator the
app container is a host directory you find via simctl get_app_container.
Both are easy to forget and annoying to retype — especially with a
specific UDID/serial.
Pure command builders here are public test seams; the Mix task resolves the device and either prints or executes the result.
Summary
Functions
One-shot command that runs inside the app's data area
Command that drops into the app's private data area
Resolves device_id (or the first connected device when nil) into a shell
target. Returns {:ok, target, label} or {:error, reason}.
Runs a resolved {:exec, cmd} plan through the shell, streaming output.
Returns the exit status. Only ever called with locally-built commands.
Types
Functions
One-shot command that runs inside the app's data area:
- Android →
adb ... run-as <bundle> -c '<script>' - iOS simulator → resolves the container then runs the script from it
- iOS physical →
:unsupported
Command that drops into the app's private data area:
- Android → interactive
run-asshell - iOS simulator → prints the app's data container path (
{:dir, cmd}) - iOS physical →
:unsupported(no public sandbox exec)
@spec resolve_target(String.t() | nil, (-> [DalaDev.Device.t()])) :: {:ok, target(), String.t()} | {:error, String.t()}
Resolves device_id (or the first connected device when nil) into a shell
target. Returns {:ok, target, label} or {:error, reason}.
lister/0 overrides discovery (test seam — same pattern as
NativeBuild.narrow_platforms_for_device/3).
@spec run(String.t()) :: non_neg_integer()
Runs a resolved {:exec, cmd} plan through the shell, streaming output.
Returns the exit status. Only ever called with locally-built commands.