Documentation

Command Line Interface

Every whitehall command, as whitehall --help lists them. The ones with a page of their own link to it; this is the full surface.

Global flag

FlagWhat it does
--non-interactiveNever ask a question — fail with the list instead of offering a menu
-h, --helpPrint help for the command
-V, --versionPrint the version

Interactive is the default: where a verb needs a phone and finds two, it draws a menu. --non-interactive turns that off, for a script that would rather have the error. WHITEHALL_NON_INTERACTIVE or CI in the environment does the same, and so does not being at a terminal.

Making and running

CommandWhat it does
init [name]Start something — an app, or a tool in its own language
build [source]Any source → an image in the store. The only verb that reads source
run [image | path]Start it and attach to its output — stdout for a tool, logcat for an app
devThe .wh edit loop — watch, rebuild, hot-reload
install [image | path | .apk]Put it on the phone, launchable from the drawer
uninstall <image | package>Take one thing off the phone
imagesList the store. --all includes scratch runs
package [image | path]Write an image out as <name>.apk, to hand to another phone
cleanRemove build artifacts, or the programs left on a phone
compileTranspile to Kotlin only — no APK. --watch recompiles on change

Source, or a name

build, install, run and package all take either. Which one you meant is decided the way a shell decides it — ./script versus script on $PATH:

What you typeWhat it means
. · ./foo · ../bar · x/y · main.whSource. Build it first, then act on the image that came out
fooAn image in the store — always, even if a directory called foo is sitting right there

So whitehall install . is build . piped into install, with the build's own cache deciding whether any work happens. Nothing bypasses the store, and there is one cache rather than two.

compile, build, install, run and package all accept a single .wh file as well as a project directory, so a one-file experiment does not need a whitehall.toml.

Cleaning

Plain clean belongs to a project, the way cargo clean does: with no whitehall.toml it refuses and does nothing. The flags are global and work from anywhere.

CommandWhat it does
cleanBuild output, plus the images nothing can rebuild or nobody asked for
clean <name>Remove that one image from the store
clean --programsUninstall the programs cargo run left on the phone
clean --programs --allAlso the ones install gave an icon
clean --imagesEmpty the image store
clean --packagesEmpty the Termux package cache

Checking

CommandWhat it does
checkFull transpile and lint, no output, no APK. The fast one
testRun the project's tests — every language, one report. --watch reruns on save
snapCapture every screen and compare it to its golden PNG
benchRun the benchmarks in src/benches/ on a device

Code quality

CommandWhat it does
formatFormat .wh files. Opinionated, zero-config. Alias fmt
format --checkFail if anything is unformatted. For CI
lintLint for style and idiom
lint --fixApply the fixable ones
why <file>Explain what the compiler decided about a file, and why
traceRewrite generated-Kotlin file references into .wh ones
lspRun the language server an editor talks to over stdin/stdout

Dependencies and packages

CommandWhat it does
add <name>…In an app, copy a component into src/lib/components/ui/; in a tool, add a Termux package to [packages]
remove <pkg>…Take a package back out of [packages]. Alias rm
update [pkg]…Re-resolve the lock — cargo's verb
deps add <dep>Add a Maven dependency to whitehall.toml, resolving the version
deps add --dev <dep>Add as a test dependency
deps remove <dep>Remove one
deps listList every dependency with its resolved version
whitehall deps add io.coil-kt/coil-compose
whitehall deps add --dev io.mockk/mockk
whitehall deps list

The top-level add, remove and update are the Termux package verbs — the phone's own libraries, in [packages]. Given a Maven coordinate they print the deps spelling and exit 1. The tables these write to are documented under Configuration.

Signing

CommandWhat it does
keystore initGenerate a keystore into the project and write [signing]

Toolchain

Java, Gradle and the Android SDK are downloaded and managed for you, cached in ~/.whitehall/toolchains/ and shared across projects while staying version-isolated. There is no separate setup step — the first build fetches what it needs.

CommandWhat it does
toolchain installPre-download everything this project needs
toolchain listShow what is installed, marking what this project uses
toolchain outdated · update · availableKeep the SDK current
toolchain cleanRemove all cached toolchains
doctorWhat this machine has, and what to type next

whitehall doctor

The first thing to run, and the thing to run when something is wrong. It reports the SDK and adb, the NDK, the Android target for cargo, CPython, Go, Java and Gradle, and every device on adb by name — then says which door this directory is and the one command that opens it.

       Found the Android SDK and adb in ~/.whitehall/toolchains/android
       Found the NDK 26.1.10909125
       Found CPython 3.13.9-0 for arm64-v8a
      Device Pixel · 1A2B3C4D5E6F7G

        Here a tool — Cargo.toml

  whitehall shell      then `cargo run`, on the phone

    Finished everything is here
doctor reads the disk and downloads nothing, so it is safe on a bad connection — a missing thing is a line, not a wait. Nothing it reports is an error: the toolchain fetches what it needs at the moment it needs it.

Borrowing the environment

The managed toolchain is not on your PATH, which is deliberate — it is what keeps projects from fighting over versions. These let you reach into it anyway:

CommandWhat it does
shellEnter the Android context — a subshell where cargo means the phone
exec <cmd>Run one command inside the Android context
which <cmd>Where that command resolves to. Alias for exec which
override set android · unsetPoint one directory at the phone, the way rustup override does
whitehall exec java -version
whitehall which gradle
whitehall shell

Devices and emulators

CommandWhat it does
deviceList connected devices, or pin one for every verb. Alias devices
emulatorManage emulators — list, start, create, delete
logslogcat, filtered to your app and rewritten to name your .wh files. Alias logcat
push · pulladb push and adb pull, with the device resolved
adb …Run adb with the managed SDK
fastboot …Run fastboot with the managed SDK
emu …Run the emulator binary directly, e.g. whitehall emu -avd myavd
avdmanager …Manage Android Virtual Devices
$ whitehall device
      Device Pixel · 1A2B3C4D5E6F7G

Naming a phone

Every verb that touches a device takes -d/--device, and it means the same thing everywhere. Give it a serial, the start of one, or the model name — the name the status lines have been using all along. Case and _, - and spaces are ignored, so Pixel_10_Pro_XL, "pixel 10 pro xl" and pixel10pro are the same query. Two matches is a refusal that lists them, never a guess. $ANDROID_SERIAL and whitehall device pin choose a phone when -d is absent.

whitehall run myapp -d pixel
whitehall test -d 1A2B
whitehall clean --programs -d "pixel 10 pro"
Use whitehall adb rather than a system adb. It is the one from the SDK this project builds against, so it cannot disagree with the APK you just installed.

Wear OS

whitehall build --wear
whitehall dev --wear

See Wear OS.

See Also