Desktop App experimental
mold ships an experimental native macOS desktop app — a Tauri 2 shell around a Vue 3 + TypeScript frontend with its own Safelight design language, a warm, matte "digital darkroom" that treats every generation as a print being developed.
Experimental
The desktop app lives in desktop/ on the experiment/desktop branch and is under active development. It is macOS-first (Apple Silicon, Metal) and not yet part of a tagged release. Build it from source with the devshell commands below.
What it is
A single native window that puts the full mold workflow behind a keyboard-driven UI, instead of the CLI or the browser SPA. The same mold-ai-server HTTP + SSE surface powers it, so anything the app does maps to a documented endpoint.
Features
- Generation workspace — a capability-driven inspector that shows only the controls a model's family supports (negative prompt, scheduler, CFG++, LoRA stack, img2img source/mask/control, video frames/fps/audio). Generation is visualized as a print developing: a deterministic grain field, seeded from the job's real seed, resolves in lockstep with
DenoiseStepevents. Batches run sequentially withbase_seed + i, and a VRAM preflight forecasts fit before you press Generate. - Gallery — a justified, virtualized contact-sheet grid. Space opens Quick Look, ←/→ navigate, and Reuse settings jumps back to Generate with every parameter restored. ⌘0 / ⌘+ / ⌘− adjust thumbnail size.
- Models & catalog — installed models grouped by family with residency and disk usage, plus a live HuggingFace/Civitai catalog. Pulls render SIZE vs FETCH honestly (model weights vs. the full download including shared components) and stream through a downloads tray.
- Chains — a filmstrip editing bench for multi-stage video (
mold.chain.v1): per-stage prompts and frame counts (validated8n+1), splice transitions (smooth / cut / fade) you click to cycle, a live fits/duration forecast against/api/capabilities/chain-limits, TOML import/export, and a durable jobs list with resume, cancel, and retake. - History — a fast, searchable list of past prompts; ↩ refills the composer.
- Settings — a full preferences bench with a section rail and cross-section search: Engine (connection, native folder pickers for the models/output directories), Performance (the
MOLD_*engine knobs as real controls, applied on engine restart), Generation defaults, a Prompt expansion form, Accounts & tokens (Hugging Face / Civitai keys in the macOS Keychain, exported to the engine asHF_TOKEN/CIVITAI_TOKEN), Appearance (System/Dark/Light — media never inverts), Profiles (switch or create), and Advanced — every remaining/api/configrow with its provenance tag (⌂ db / ⛁ file / ⚿ env); environment-overridden rows are locked with the variable that owns them. - Command palette — ⌘K for navigation, actions, model search, and prompt-history search in one field.
- Native macOS — menu bar, keyboard shortcuts, and background notifications on generation, chain, and pull completion.
Keyboard map
| Shortcut | Action |
|---|---|
| ⌘1–⌘5 / ⌘, | Screens / Settings |
| ⌘K | Command palette |
| ⌘N | New generation (clear composer, focus) |
| ⌘↩ | Generate |
| ⌘E | Expand prompt |
| ⌘R | Randomize seed |
| ⌘. | Cancel the running job |
| ⌘\ | Toggle sidebar |
| Space | Quick Look in Gallery |
| ←/→, ⌫ | Gallery navigate / delete |
| ⇧⌘C | Copy seed (lightbox) |
| ⌘0 / ⌘+ / ⌘− | Gallery thumbnail zoom reset / in / out |
Generation templates
Save the current Generate form as a named, recallable preset. Open the Templates panel below the LoRA stack, give the current settings a name, and it is stored as a template you can load, rename, or delete later. Loading a template restores every parameter — model, prompt, dimensions, steps, guidance, scheduler, LoRA stack, and the rest — in one click.
Templates capture parameters, not media: source, mask, and control images (and LTX-2 source video / keyframes) are referenced but never stored, so after loading a template that used them the app reminds you to re-select the files. If the template's model isn't installed you still get its settings, with a prompt to pull the model.
Templates are stored locally, per machine (in the app's own storage), and are never shared with the browser SPA or synced to the server — they travel with the Mac you saved them on.
Device placement
Settings → Advanced → Device placement saves a per-model default for where a model's components run. Pick an installed model, then set its Text encoders — the Tier-1 group knob covering T5, CLIP, and Qwen encoders — to Auto, CPU, or a specific GPU. For Tier-2 families (FLUX, Flux.2, Z-Image, Qwen-Image) an Advanced disclosure exposes per-component overrides for the transformer, VAE, and each text encoder; any encoder can also be left to follow the group knob.
Save as default persists the choice for that model and Clear removes it. Placement is applied the next time the model loads, so save it before you generate. GPU choices come from the connected engine's live device list.
This is the desktop surface for the same mechanism the CLI's --device-* flags and MOLD_PLACE_* variables drive — see Configuration → Per-component device placement for the full component list and semantics.
How it connects
The app talks to a mold-ai-server over localhost HTTP + SSE using the same wire types as the CLI and web UI:
- Built-in engine — embeds the server in-process and runs on Metal, so no separate
mold serveis required. - Existing server — auto-detects a running
mold serveonlocalhost:7680. - Remote host — point it at a remote GPU box (e.g. a Linux CUDA machine for LTX-2), configured in Settings → Engine, with the API key stored in the macOS Keychain.
Development
Run inside nix develop (the devshell wires up Metal, Bun, and the Tauri toolchain):
desktop-dev # Tauri app with hot reload (Vite on :1430)
desktop-build # build the Mold.app bundle
desktop-check # CI gate: rustfmt, clippy, vue-tsc, prettier
desktop-test # cargo test (CPU) + vitest
desktop-ui # frontend-only Vite server (pair with a running `serve`)
desktop-bun-lock # regenerate desktop/bun.nix from bun.lockThe Rust crate under desktop/src-tauri is its own cargo root (excluded from the workspace); the frontend lives in desktop/src. CI runs the desktop-check and desktop-test gates via .github/workflows/desktop.yml.
