native-run
native-run is an Ionic-maintained command-line tool that installs and launches already-built Android APKs and iOS app bundles or IPA files on physical devices and emulators or simulators. It can discover targets, choose one automatically, report Android SDK contents, forward Android ports, and keep its process attached to the launched app. It does not compile, sign, provision, test, or package an app. The Ionic CLI uses it internally, but any mobile build pipeline can call the binary.
A focused, useful last-mile launcher when you already own the native build and local toolchains. Skip the direct install when a framework CLI already wraps it, or when you need building, signing, automation, remote devices, or iOS execution outside macOS and Xcode.
Use it if
- You already have a built APK, .app, or IPA and need one CLI to install and launch it from a script
- You maintain Ionic or Capacitor tooling and want the same target-selection behavior used by the Ionic CLI
- You need machine-readable device and simulator discovery for an Android or iOS development pipeline
- You want an Android command that can select hardware or an emulator and set up temporary ADB port forwarding
- You expect it to build or sign the app: --app is required for a run, and the source only inspects and deploys the supplied APK, .app, or IPA
- You need iOS deployment from Linux or Windows: simulator paths call xcrun, simctl, xcode-select, and the macOS open command, while physical-device setup reads Xcode DeveloperDiskImage files
- You want a programmatic library API: the package has no published declaration files, and its main run function reads process.argv and writes serialized CLI output
- Your framework CLI already owns deployment: Ionic and Capacitor workflows normally invoke native-run for you, so a global install adds another version to troubleshoot
- You need UI automation, assertions, screenshots, retries across a device farm, or remote devices: native-run installs and launches one local target but is not a test runner or device-cloud client
Setup reality
The npm package is written in TypeScript and ships compiled JavaScript, so installation itself has no native npm build. Version 2.0.3 requires Node 16 or newer. That is the easy part. Android runs require a valid Android SDK with platform-tools and adb, plus emulator packages and at least one suitable system image when no hardware device is attached. The tool looks first at ANDROID_HOME, then ANDROID_SDK_ROOT, then conventional SDK directories. It also needs ANDROID_EMULATOR_HOME or the standard .android directory and uses ANDROID_AVD_HOME or .android/avd. Run native-run android --sdk-info before blaming target selection. If no explicit --target is given, a connected device wins unless --virtual is set; otherwise it tries a running emulator and can attempt a default AVD during a run. Your APK still needs a valid signature, compatible minimum SDK, launchable activity, and enough device storage. iOS is effectively a macOS and Xcode workflow: simulator discovery and launch use xcrun simctl, xcode-select, Xcode's Simulator app, and open. Physical-device deployment requires a trusted, provisioned device, matching Xcode device-support images, and a bundle already signed for that device. The source waits in five-second intervals for a locked iOS device, then aborts after one minute. iOS 17 physical-device fallback requires Xcode 15 or later. The README recommends a global install, but a pinned dev dependency plus npm exec is easier to reproduce in CI. Use --target rather than automatic selection on shared runners, --json for parsing lists, and --verbose for diagnostic output. The --connect flag deliberately keeps the command alive until the app closes and may terminate the app during cleanup, so do not add it to a fire-and-forget deployment step.
Patterns
Install globally for interactive useinstall-cli
npm install --global native-run@2.0.3
native-run --versionThe README recommends a global install. For CI, pin it in devDependencies and run npm exec native-run so every runner uses the lockfile version.
Read the platform-specific flagsshow-platform-help
native-run --help
native-run android --help
native-run ios --helpThe platform help contains options absent from the short README, including --target, --connect, Android --forward, and --sdk-info.
List Android devices and emulatorslist-android-targets
native-run android --listThis requires a discoverable Android SDK even when you only want a list. Use --device or --virtual with --list to filter the output.
Get machine-readable target datalist-targets-json
native-run android --list --json
native-run ios --list --jsonList each platform separately in automation. The top-level native-run --list probes both ecosystems and can include toolchain errors from a platform the runner does not support.
Inspect the resolved Android SDKinspect-android-sdk
native-run android --sdk-info
native-run android --sdk-info --jsonResolution prefers a valid ANDROID_HOME, then ANDROID_SDK_ROOT, then the conventional SDK directory for the operating system.
Install and launch an APKrun-apk-automatically
native-run android --app ./android/app/build/outputs/apk/debug/app-debug.apkWithout --target, hardware is preferred, then a running emulator, then an available virtual device. This convenience can pick the wrong target on a busy workstation.
Run only on attached Android hardwarerequire-android-device
native-run android --app ./app-debug.apk --deviceIf no hardware device is available, --device fails instead of falling back to an emulator. Enable USB debugging and accept the host authorization prompt first.
Prefer an Android emulatorprefer-android-emulator
native-run android --app ./app-debug.apk --virtualThe Android SDK still needs emulator tools and a suitable installed system image. The npm package does not download the SDK for you.
Choose an exact Android targetselect-android-target
native-run android --list --json
native-run android --app ./app-debug.apk --target emulator-5554Use the device serial or AVD ID printed by --list. Explicit selection is the safest choice for CI and multi-device workstations.
Forward ports while the Android app runsforward-android-ports
native-run android \
--app ./app-debug.apk \
--target emulator-5554 \
--forward 8080:8080 \
--forward 9222:9222The value is device-port:host-port and the flag may be repeated. The tool removes its forwarding rules during process cleanup.
Install and launch an iOS app or IPArun-ios-binary
native-run ios --app ./build/MyApp.app --virtual
native-run ios --app ./artifacts/MyApp.ipa --deviceSimulator .app bundles and device IPA files must already be built for the correct target. Device builds must also be signed and provisioned before native-run sees them.
Choose an iOS target and stay attachedselect-ios-target
native-run ios --list --json
native-run ios \
--app ./build/MyApp.app \
--target A1B2C3D4-EXAMPLE-UDID \
--connect \
--verbose--target takes a device or simulator UUID. --connect keeps the process alive until the app closes and can terminate the app when the CLI exits.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| @capacitor/cli | npm | You have a Capacitor project and want build, sync, IDE opening, and run commands in the framework's supported workflow |
| cordova | npm | You maintain a Cordova application and want its build and run lifecycle rather than a binary-only launcher |
| appium | npm | You need cross-platform UI automation, assertions, driver sessions, and test-runner integration |
| adbkit | npm | You need a programmatic Node API for Android Debug Bridge operations and do not need iOS |