Documentation

whitehall dev

The .wh edit loop: watch, rebuild, hot-reload.

Usage

whitehall dev [target] [options]

target defaults to .: a project directory or a single .wh file. dev builds the app, installs it, launches it, and then watches src/. Save a file and the running app changes.

$ whitehall dev
      Device Pixel · 1A2B3C4D5E6F7G
    Dev mode hot reload enabled
    Compiled .wh → .kt (12 files) in 340ms
    Compiled .kt → APK (32 tasks) in 11.20s
    Finished rebuild in 12.30s
       Press r to rebuild, q to quit

     Changed AppTopBar.wh
    Finished hot reload of AppTopBarKt in 2.28s (transpile 1ms, compile 784ms, dex 314ms, patch 1.18s)

Every line is a cargo-shaped status: the verb on the left, what it did and how long it took on the right. While a phase runs, a bar at the bottom of the terminal names what is in flight, and it is erased when the phase leaves its finished line behind.

Options

FlagWhat it does
-d, --device <id>Which phone. A serial, the start of one, or the model name. Auto-selects when only one is connected
-r, --releaseRelease build. Release builds always do full rebuilds
--debugForce a full debug build on every save; hot reload off
--no-cacheIgnore the build cache and rebuild every file
--no-compileSkip .wh → .kt; use the Kotlin already in build/
--settle <ms>Wait this long after the last change before rebuilding. Default 300
--wearBuild for Wear OS and run on the watch
--reinstallUninstall first, then install: a clean install

While dev runs, press r to rebuild on request and q to quit.

What a patch redraws

A patch redraws as little as it can, and what it does not redraw keeps its state.

You savedWhat redrawsWhat keeps its state
a screen's own +screen.whthat screenevery other screen on the back stack — scroll position, typed text, anything remembered — the layouts around it, and the back stack itself
anything else: a +layout.wh, a loader, a store, a $lib filethe whole app, since any screen may call itstate hoisted out of the composition: stores, ViewModels, the route cache

The patched screen itself starts over: its remembered values, its $state, its scroll position. A patch cannot tell which of the old values the new code still means, so it shows the new code running from the top.

A failed save, on the phone

When a save does not compile — the lint gate refuses it, or kotlinc does — the diagnostic the terminal printed is drawn over the running app, word for word:

The last save did not reach the phone

error[unknown-component]: `<Colum>` is not an element, and nothing in this project
declares or imports it. Did you mean `<Column>`?
  --> src/routes/+screen.wh:3:1

It sits over the app rather than replacing it, so the app keeps its state underneath, and the next save that works clears it and lands on that state intact. A source error is not retried as a full rebuild, because it would fail the same way later; dev waits for the next save.

When a patch is not possible

When a change cannot be patched, dev says why and rebuilds in full:

     Changed User.wh
     Skipped hot reload — structural change: field added
  Rebuilding in full
    Finished rebuild in 8.20s

Hot reload redefines classes in the running process, so it needs a debuggable app on Android 8.0 (API 26) or newer. Adding or removing fields and methods needs Android 11 (API 30). Changes to the class hierarchy, new classes, whitehall.toml and several files saved at once are full rebuilds. When the device or the build cannot patch, a Note line names the reason and dev keeps working as a rebuild loop.

If patching keeps failing, whitehall adb logcat -s WhitehallRedefine:* shows the redefinition errors.

This is the app loop only

dev is for a .wh app, which has no other toolchain. A tool iterates with its own language's commands inside whitehall shell. There is no run --watch and no build --watch. To watch the transpile alone, without a device, use whitehall compile --watch; to rerun tests on save, use whitehall test --watch.

See Also