waterui-cli
Cross-platform build orchestration and development tooling for WaterUI applications.
Overview
waterui-cli is the command-line interface that powers the water binary, the primary tool for building, running, and managing WaterUI applications across iOS, macOS, and Android. It abstracts platform-specific build systems (Xcode for Apple, Gradle for Android) and provides a unified developer experience with device management, project scaffolding, and instant view previews.
The crate is split into two components:
- Library (
src/lib.rs): Core abstractions for platforms, devices, builds, and project management - Terminal (
src/terminal/): User-facing CLI with argument parsing and formatted output
This separation ensures all business logic lives in the library, while the terminal layer handles only user interaction.
Installation
Install the CLI from a clone of this repository:
Or build for development (not added to PATH):
Quick Start
Create a new WaterUI project and run it on iOS Simulator:
# Create a new project
# Run on iOS Simulator
# Run on Android
Create a playground for quick experimentation (auto-managed backends):
Preview Views
Preview individual view functions without running the full app:
# Preview a view function and save as PNG
# With custom frame size
Drive the App over MCP
Serve the app to an agent over MCP — the accessibility tree, actions, and screenshots become tools:
# In the project root (or pass --path)
# Custom viewport and scale factor
water create writes a .mcp.json that registers the server for MCP clients
launched in the project root. The CLI fronts the generated app process, so
initialize and tools/list answer immediately even while a cold build is
still compiling; restart rebuilds from the current sources. The preview
tool renders a #[preview] function or expr expression and returns the PNG
image content directly — the same render water preview produces, without a
shell round trip.
Mark functions with #[preview] to make them previewable:
use waterui::prelude::*;
#[preview]
fn my_card() -> impl View {
vstack((
text!("Hello Preview!"),
text!("This renders instantly"),
))
.padding()
.background(Color::srgb(100, 150, 200))
}
The preview system generates symbols with the format waterui_preview_{crate_name}_{fn_name} to avoid conflicts between crates.
Core Concepts
Platform Abstraction
A build target is a TargetPlatform — an enum of the concrete targets
(MacOS, IOS, IOSSimulator, TvOS, Android, …) paired with a
TargetBackend naming which backend renders it (Apple, Android, Gtk4,
Hydrolysis, …). It replaced an earlier Platform trait: the set of targets
is fixed and known, so an enum says so, and the per-target work — scanning for
devices, building for the triple, packaging into a .app or .apk, cleaning —
lives in the module for that platform rather than behind an associated type.
pub enum TargetPlatform {
MacOS,
IOS,
IOSSimulator,
TvOS,
TvOSSimulator,
Android,
// …
}
Device Management
The Device trait represents something that can run an app (simulator, emulator, or physical device). Each device has a two-phase lifecycle:
- Launch: Boot the emulator/simulator (no-op for physical devices)
- Run: Install and execute the artifact, returning a
Runningstream
Example from src/workflows/device.rs:
pub trait Device: Sized + Send {
fn name(&self) -> &str;
fn launch(&self) -> impl Future<Output = eyre::Result<()>> + Send;
fn run(&self, artifact: Artifact, options: RunOptions) -> impl Future<Output = Result<Running, FailToRun>> + Send;
fn platform(&self) -> Self::Platform;
}
Implementations: AppleSimulator, MacOS, AndroidDevice, AndroidEmulator
Project Management
The Project type manages the Water.toml manifest and coordinates builds across platforms. Key methods:
Project::open(): Open existing projectProject::create(): Scaffold new projectProject::run(): Build, package, and run on a device
Rust Build
The RustBuild type wraps cargo build with platform-specific configuration:
- Target triple selection (e.g.,
aarch64-apple-ios-sim) - Simulator-specific clang args for bindgen
- Optional sccache integration for faster builds
Toolchain Management
The Toolchain trait checks for required dependencies and provides installation plans:
pub trait Toolchain: Send + Sync {
type Installation: Installation;
fn check(&self) -> impl Future<Output = Result<(), ToolchainError<Self::Installation>>> + Send;
}
pub trait Installation: Send + Sync {
type Error: Into<eyre::Report> + Send;
fn install(&self) -> impl Future<Output = Result<(), Self::Error>> + Send;
}
Example: AppleToolchain checks for Xcode, simulators, and rust targets. AndroidToolchain checks for Android SDK, NDK, and JDK.
Examples
Run with Device Logs
This streams device logs at debug level or above to the terminal.
Run on Specific Device
# List available devices
# Run on specific device by ID
Create Project with Local WaterUI Development
This creates a project that uses the local WaterUI repository.
Build Without Running
Clean Build Artifacts
Check Development Environment
This validates toolchain dependencies (Xcode, Android SDK, Rust targets).
API Overview
Library (src/lib.rs)
platform: Platform trait and implementations (Apple, Android)device: Device trait, device types, run options, and eventsproject: Project management, manifest parsing, create/openbuild: Rust build orchestration with cargodebug: Crash handling and diagnosticstoolchain: Toolchain checking and installationbackend: Backend configuration and scaffoldingtemplates: Project scaffolding templatesapple: Apple platform, devices, and backendandroid: Android platform, devices, and backendbrew: Homebrew package management utilitieswater_dir: GlobalWaterUIdirectory managementutils: Command execution helpers
Terminal (src/terminal/)
main.rs: CLI entry point, argument parsingshell.rs: Output formatting, spinners, colorscommands/create.rs: Project scaffolding commandcommands/run.rs: Build and run commandcommands/build.rs: Build-only commandcommands/package.rs: Packaging commandcommands/clean.rs: Cleanup commandcommands/doctor.rs: Toolchain validation commandcommands/devices.rs: Device listing commandcommands/mcp.rs: MCP server command (drives the app headless for agents)
Features
The CLI supports:
- Multi-platform: iOS, macOS, Android with unified workflow
- Instant previews: Render individual views to PNG without running the full app
- Device management: Automatic device discovery and simulator launching
- Interactive creation: Guided project setup with prompts
- Playground mode: Auto-managed backends for quick prototyping
- Parallel builds: Device launch overlaps with compilation
- Log streaming: Real-time device logs with level filtering
- JSON output: Machine-readable output with
--jsonflag - Graceful cancellation: Ctrl+C cleanup without errors