Zornux docs
Get started Spec

Mobile

Mobile Tooling

The zornux mobile CLI covers the full development lifecycle — from first run to Play Store submission — without leaving the terminal.

Environment check

Run doctor before anything else. It verifies your SDK, JDK, ADB, connected devices, and project configuration in one pass:

bash
zornux mobile doctor

Build and run

Build the app and install it on a connected device or emulator:

bash
zornux mobile run android

Build without installing:

bash
zornux mobile build android

Validate the project without building:

bash
zornux mobile check android

Device and emulator management

bash
zornux mobile devices                     # list connected devices
zornux mobile emulators                    # list available AVDs
zornux mobile emulator start Pixel_7_API_34  # boot an emulator

Each device shows its serial, state (Online, Offline, Unauthorized), type (Physical or Emulator), model, Android version, and API level.

Multiple devices

Pass --device <serial> to any command that targets a device. Without it, Zornux picks the first online device.

Hot reload

Add --watch to run and the toolchain watches your .zx files for changes. When you save, it re-generates the Compose code, rebuilds, reinstalls, and relaunches the app automatically:

bash
zornux mobile run android --watch

Changes to text, layout, and state within existing screens are hot-reloaded without a full restart. Changes that affect permissions, capabilities, or the project file trigger a full rebuild — the watcher tells you which path it took.

What triggers a full rebuild

Adding a new permission, a new capability (camera, biometrics, etc.), or changing zornux.project requires a full rebuild. The watcher detects this and rebuilds automatically.

Logs

Stream the device logcat filtered to your app's process:

bash
zornux mobile logs android

Debugging

Launch a debug session with breakpoint support:

bash
zornux mobile debug android

The debugger injects a runtime bridge into the app, forwards a debug port over ADB, and connects. You can:

  • Set breakpoints on Zornux source lines — the toolchain maps them to the generated Kotlin. Breakpoints snap to the nearest executable line within 3 lines.
  • Step through code: continue, pause, step over, step into, step out.
  • Inspect variables in the current scope.
  • View stack traces mapped back to your Zornux source locations.

Debug events are tracked at five location types: lifecycle, action, state mutation, navigation, and capability call. When a breakpoint hits, the debugger shows which type of operation you are in.

IDE integration

The debug bridge uses a TCP protocol compatible with standard debug adapters. ZnxStudio connects to it natively.

Testing

Write tests in .zx files alongside your app code, then discover and run them:

bash
zornux mobile test android

Test kinds

The test runner classifies tests automatically based on what they do:

KindWhat it testsNeeds a device?
Host logicPure logic — functions, calculations, data transforms.No
UI componentScreen structure — screens exist, widgets are present.No
Android interactionOn-device behavior — tap, enter text, assert visible.Yes

Host logic and UI component tests run on the host machine with no device attached — fast and CI-friendly. Interaction tests launch the app on a device or emulator.

Test options

bash
zornux mobile test android --filter "login"    # run matching tests
zornux mobile test android --device emulator-5554
zornux mobile test android --verbose           # full output
zornux mobile test android --json              # machine-readable results
zornux mobile test android --timeout 120       # per-test timeout (seconds)

Results are written to .zornux-test-results/android/.

Test doubles

The test framework provides mock implementations for device capabilities and HTTP, so host-logic tests can exercise code that calls them without a real device:

  • Capability doubles — camera, location, biometrics, connectivity, files, notifications, sharing.
  • HTTP doubles — mock responses with OnGet, OnPost, OnPut, OnDelete, OnAny. Simulate timeouts and offline mode.

Profiling

Profile the app on a real device to find performance problems:

bash
zornux mobile profile android
zornux mobile profile android --duration 30    # profile for 30 seconds

What the profiler measures

CategoryMetrics
StartupCold/warm start time, startup phases.
Screen renderingOpen-to-ready time per screen.
RecompositionCount per screen — flags excessive (> 20).
HTTPMethod, URL, status, size, timeout detection.
State updatesTiming per state mutation.
Capability callsTiming for camera, biometrics, and other device calls.
NavigationTransition timing between screens.
MemoryCurrent, peak, Java heap. Flags growth > 20% across the session.
FramesSlow (> 16ms), frozen (> 700ms), jank %, P95 frame time.
Main-thread blockingOperations exceeding 32ms on the main thread.

The profiler also analyzes package size — DEX, resources, native libraries, assets, generated Kotlin — and compares against your performance budgets.

Performance budgets

Set budgets in zornux.project and the profiler warns when they are exceeded:

zxcfg
android.performance.startup_ms = 2000
android.performance.apk_mb = 20
android.performance.aab_mb = 15

Sessions are saved to .zornux-profile/android/ as both a human-readable report and a JSON file.

Release builds

When the app is ready for distribution, the release pipeline validates, builds, and optionally publishes in three steps.

Step 1: Pre-flight check

bash
zornux mobile release check

This validates:

  • Application ID is set and follows reverse-domain format.
  • Version code is positive and incremented from the previous release.
  • Signing configuration is complete (keystore, alias, password env vars).
  • Certificate is valid and not expired.
  • Icons are configured.
  • Cleartext traffic is disabled.
  • Extension dependencies are pinned (no SNAPSHOT or + versions).
  • Privacy declarations match capability usage (Data Safety).
  • Store metadata (title, descriptions, feature graphic) is present.

Step 2: Build the release

bash
zornux mobile release build

This produces:

  • A signed release APK and AAB (Android App Bundle).
  • ProGuard mapping file for crash de-obfuscation.
  • Release manifest (JSON) with artifact hashes, permissions, SDK levels.
  • SBOM in CycloneDX 1.5 format.
  • SHA-256 checksums.
  • Build provenance record (Zornux version, source revision, build timestamp).
bash
zornux mobile release artifacts          # list what was built

Step 3: Publish

bash
zornux mobile release publish --track internal   # internal testing
zornux mobile release publish --track production  # production release
zornux mobile release publish --dry-run           # validate without uploading

Supported tracks:

TrackAudience
internalInternal testers only.
closedClosed alpha testers.
openOpen beta — anyone can opt in.
productionAll users on the Play Store.
Dry run first

Always run --dry-run before your first real publish. It validates the entire pipeline — credentials, metadata, artifact integrity — without uploading anything.

Signing configuration

Release builds must be signed. Configure the keystore in zornux.project:

zxcfg
android.signing.keystore_path = release.jks
android.signing.key_alias = release
android.signing.keystore_password_env = KEYSTORE_PASSWORD
android.signing.key_password_env = KEY_PASSWORD

Passwords are read from environment variables — they never appear in the project file. Set them in your shell or CI secrets:

bash
export KEYSTORE_PASSWORD="..."
export KEY_PASSWORD="..."
Never commit passwords

The keystore password env vars (KEYSTORE_PASSWORD, KEY_PASSWORD) must be set in the environment, not in the project file. The signing configuration stores only the names of the env vars.

Store metadata

Play Store listing fields go in zornux.project:

zxcfg
store.title = My App
store.short_description = A short tagline for the store listing
store.full_description = A longer description of what the app does
release.notes = Bug fixes and performance improvements
FieldLimit
store.title30 characters.
store.short_description80 characters.
store.full_descriptionNo fixed limit.
release.notesNo fixed limit.

Publishing credentials

Google Play publishing requires a service account JSON key. Point to it in zornux.project:

zxcfg
publishing.credential_file = play-service-account.json

Or reference an environment variable that holds the path:

zxcfg
publishing.credential_file_env = PLAY_CREDENTIALS

Privacy declarations (Data Safety)

The Play Store requires a Data Safety section. Declare what your app collects in zornux.project — the release check validates that these declarations match the capabilities your code actually uses:

zxcfg
privacy.location = true
privacy.photos = true
privacy.identifiers = false
privacy.auth_data = false
privacy.user_content = false
privacy.analytics = false

Cleaning up

Remove generated Android project files (the .zx source is never touched):

bash
zornux mobile clean

Inspect the generated Kotlin and Compose code:

bash
zornux mobile generated

Project configuration reference

Every mobile-specific key in zornux.project:

KeyDefaultPurpose
typeMust be mobile.
entrymain.zxEntry source file.
android.application_idcom.zornux.appReverse-domain app ID.
android.version_name1.0User-facing version string.
android.version_code1Play Store integer version.
android.min_sdk24Minimum Android API level.
android.target_sdk34Target Android API level.
android.compile_sdk34Compile SDK version.
android.allow_cleartextfalseAllow HTTP traffic.
android.icon.foregroundAdaptive icon foreground image path.
android.icon.background_color#FFFFFFAdaptive icon background color.
android.splash.iconSplash screen icon path.
android.splash.background_color#FFFFFFSplash screen background color.
android.environmentdevelopmentEnvironment name.
android.build_config.<FIELD>Custom BuildConfig string fields.

CI mode

Pass --ci to any mobile command for non-interactive, stricter validation. Pair with --json for machine-readable output:

bash
zornux mobile test android --ci --json
zornux mobile release check --ci
zornux mobile release build --ci

CLI command reference

CommandPurpose
zornux new mobile <Name>Scaffold a new mobile project.
zornux mobile doctorCheck environment prerequisites.
zornux mobile build androidCompile to an Android project and build.
zornux mobile run androidBuild, install, and launch on device.
zornux mobile run android --watchRun with hot reload.
zornux mobile check androidValidate without building.
zornux mobile devicesList connected devices.
zornux mobile emulatorsList available AVDs.
zornux mobile emulator start <avd>Boot an emulator.
zornux mobile logs androidStream filtered logcat.
zornux mobile debug androidLaunch a debug session.
zornux mobile test androidDiscover and run tests.
zornux mobile profile androidProfile on-device performance.
zornux mobile release checkPre-flight release validation.
zornux mobile release buildBuild signed release artifacts.
zornux mobile release artifactsList release build outputs.
zornux mobile release publishPublish to the Play Store.
zornux mobile extension listList installed extensions.
zornux mobile extension info <alias>Show extension details.
zornux mobile extension checkValidate extension compatibility.
zornux mobile cleanRemove generated files.
zornux mobile generatedInspect generated Kotlin code.

What's next

  • Mobile Development — screens, layouts, widgets, state, and navigation.
  • Mobile Capabilities — camera, location, notifications, secure storage, biometrics, HTTP, and native extensions.