notes/architecture/02-CLI.md
The dx CLI is a comprehensive build tool for Dioxus applications, supporting development, building, bundling, and cross-platform deployment.
Entry point: main.rs with async tokio runtime and TraceController for error handling.
Serve - Watch and serve with hot-reloadingBuild - Full production buildBundle - Package for distributionRun - Run without hot-reloadCreate / Init - Project scaffoldingCheck - Lint/validate RSXTranslate - Convert HTML/JSX to RSXAutoformat - Format RSX codeConfig - Manage Dioxus.tomlDoctor - Diagnose environmentComponents - Component registrySelfUpdate - Update CLITools - Internal tools (build-assets, hotpatch)Web - wasm32-unknown-unknownMacOS / Windows / Linux - Desktop webviewIos / Android - Mobile webviewServer - SSR/fullstack serverLiveview - WebSocket streamingUnknown - Auto-selectAllows separate client/server args for fullstack:
dx serve @client --features web @server --features server
Decomposes into client BuildArgs, server BuildArgs, and shared args.
The "plan" for a single build:
BuildRequest
├── workspace: Workspace metadata
├── config: DioxusConfig
├── package: Package details
├── features: Vec<String>
├── target: Triple
├── bundle: BundleFormat
├── profile: Profile
├── rustflags: Vec<String>
└── custom_linker: Option<PathBuf>
Responsible for:
Base { run: bool } - Normal cargo rustc buildFat - Full build with all symbols for hot-patchingThin { rustc_args, changed_files, aslr_reference, cache } - Fast rebuildRuntime configuration with progress channel:
ProgressTx for status updatesBuildId enum: PRIMARY (client), SECONDARY (server)compiling(), linking(), bindgen(), etc.State machine managing ongoing builds:
Primary orchestration:
AppServer
├── workspace: Workspace metadata
├── client / server: AppBuilder instances
├── watcher: File system watcher
├── file_map: Cached RSX files for hot-reload diffing
├── devserver: WebServer
└── flags: use_hotpatch_engine, automatic_rebuilds, hot_reload, etc.
HTTP + WebSocket server providing:
Terminal UI with ratatui:
File modified → detect type
├── Rust file → diff RSX using dioxus_rsx_hotreload::diff_rsx()
│ ├── Extract changed templates
│ ├── Build HotReloadMsg
│ └── Send via WebSocket
├── Asset file → copy to bundle, signal reload
└── If can't hot-reload → queue full rebuild
Uses tokio::select! to multiplex:
__ASSETS__ symbols from binaryPlatform-specific packaging:
gradle bundleRelease for AABBundleConfig
├── identifier: String
├── publisher: String
├── icon: Vec<PathBuf>
├── resources: Vec<PathBuf>
├── deb / macos / windows / android: Platform-specific
Caches compiled dependency symbols:
create_windows_jump_table() - x86/x64 jump stubscreate_native_jump_table() - macOS/Linux function overridescreate_wasm_jump_table() - WASM indirect call table updates[application]
asset_dir = "assets"
out_dir = "dist"
tailwind_input/output = "..."
ios_info_plist = "Info.plist"
android_manifest = "AndroidManifest.xml"
[web]
app.title = "My App"
https.enabled = true
pre_compress = false
[bundle]
identifier = "com.example.app"
publisher = "Company"
Workspace
├── krates: Krates (cargo metadata, dependency graph)
├── settings: CliSettings (user settings ~/.config/dioxus/)
├── sysroot: Rust target sysroot
├── rustc_version: Version
├── wasm_opt: Optional path
├── cargo_toml: Parsed Cargo.toml
└── android_tools: Optional NDK/SDK
Lazy-loaded via Workspace::current() with tokio Mutex.
BundleFormat enumRenderer enumMyPlatformSettings)Bundle::bundle()Commands enumcli/TraceController::main() matchStructuredOutput variant for resultsBuild Task → BuilderUpdate Channel → AppBuilder → ServeUpdate → Output TUI
Decouples build process from UI for real-time updates.
Single workspace load with tokio Mutex, shows spinner if cargo-metadata takes >1 second.
--web, --webview, --native--ios, --android, --desktop