microsoft-webui-cli
Command-line tool for the WebUI framework — build, serve, and inspect WebUI applications.
Install
This installs the webui binary.
Commands
webui build
Build a WebUI application into a compiled protocol and CSS files.
| Option | Default | Description |
|---|---|---|
APP |
. |
Template/component directory |
--out |
(required) | Output directory for protocol.bin + CSS, or a .bin file path to customize the protocol filename (e.g. ./dist/app1.bin) |
--entry |
index.html |
Entry HTML file |
--css |
link |
CSS mode: link (external files) or style (inline) |
--plugin |
(none) | Plugin identifier (see Plugins for available identifiers) |
--asset-file-name-template |
[name].[ext] |
Emitted asset filename template. Tokens: [name], [hash], [ext] |
--css-public-base |
(none) | Optional base URL/path prepended to Link-mode stylesheet hrefs |
webui serve
Start a development server with live rebuild and HMR.
| Option | Default | Description |
|---|---|---|
APP |
. |
Template/component directory |
--state |
(none) | JSON state file for rendering |
--servedir |
(none) | Static assets directory served at /* |
--port |
3000 |
Server port |
--api-port |
(none) | Proxy API requests; JSON provides buffered state and application/x-webui-stream drives progressive boundaries |
--plugin |
(none) | Plugin identifier (see Plugins for available identifiers) |
--watch |
off | Enable file watching + HMR |
--shutdown-timeout <SECONDS> |
(none) | Opt in to supervised shutdown with a positive integer grace period, with or without --watch |
--asset-file-name-template |
[name].[ext] |
Emitted asset filename template. Tokens: [name], [hash], [ext] |
--css-public-base |
(none) | Optional base URL/path prepended to Link-mode stylesheet hrefs |
By default, shutdown waits for an active rebuild without a deadline. Add
--shutdown-timeout 10 to terminate the owned server process tree when a stop
request cannot finish within ten seconds; a second stop request escalates
sooner. Forced shutdown returns nonzero and can leave incomplete outputs.
Supervised mode reserves stdin, so interactive build tools are unsupported.
See bounded shutdown
for platform limits.
Features:
- Renders HTML at
/and all route paths - Serves static files from
--servedir - JSON partials for client-side navigation (
Accept: application/json) - HMR polling at
/hmrwhen--watchis enabled - API proxy when
--api-portis set. Backends may return JSON state or a versioned, newline-delimitedapplication/x-webui-streamcontrol response; the CLI retains the Rust renderer, caps precommit output staging at 4,000,000 bytes, and cancels the backend when the browser disconnects.
The control response uses version 2 and exactly three command types:
start is first and supplies the initial object state. Each resume must echo
the pending runtime descriptor's owner, name, and optional string-or-number
key; declarationId may also be supplied for validation. The CLI retains
committed descriptors, so update uses the same target without a reverse
acknowledgement channel. Ambiguous unkeyed update targets are rejected.
The CLI drives the Rust step machine as follows:
| Rust step state | CLI action |
|---|---|
| descriptor present | Wait for the matching backend resume, then call resume |
| no descriptor and not done | Call advance internally |
| done | Complete the browser response |
Rust resume emits only the pending boundary through its checkpoint. The
following internal advance emits parent or tail bytes through the next
descriptor or terminal. The backend does not send an advance control record.
It closes its NDJSON body after sending the resume for the final descriptor;
the CLI's final advance completes the response. There is no terminal control
command.
webui inspect
Convert a compiled protocol to JSON for debugging.
webui desktop
Run desktop commands through the desktop sidecar backend. webui remains the
only user-facing CLI; the sidecar is resolved automatically from the installed
desktop support package, next to the webui binary, or from the workspace during
local development. Set WEBUI_DESKTOP_BINARY only to override sidecar discovery.
The sidecar currently creates immutable desktop bundles with protocol.bin,
copied assets, startup state, manifest.webui-desktop.json, and SHA-256
integrity hashes. Native window backends and platform package emitters are
implemented in the desktop sidecar so the default CLI stays lean.
The Rust packager currently writes runnable macOS .app bundles and portable
folder layouts. For app roots, supply source, assets, build scripts, identity,
window, and runner settings as webui desktop package flags; legacy
webuiDesktop package metadata remains supported and explicit flags override it.
The sidecar builds the app-specific Cargo runner crate, stages non-generated
assets, builds the bundle, and packages the runner-backed app. Use --runner
for lower-level existing-bundle flows with
route providers or typed IPC commands; omitting it packages the generic sidecar
for file-backed/static seed-state bundles. Installer targets return actionable
missing-tool diagnostics until the platform packagers are enabled.
Use --devtools on desktop build/run to make development webviews inspectable.
On macOS, inspect from Safari's Develop menu.
Rust desktop apps that need dynamic route data can configure .route(...) on
webui_desktop::DesktopApp::from_bundle(path)? or, with the source feature,
DesktopApp::from_source(config). Both builders produce a desktop frame.
See the desktop SDK guide
for setup and customization. The CLI --state flag is a file-backed fallback
for simple demos.
App Layout
my-app/
├── src/
│ ├── index.html # entry template
│ ├── my-card.html # component template
│ └── my-card.css # component styles
├── data/
│ └── state.json # render state
└── dist/ # build output
├── protocol.bin
└── my-card.css
License
MIT