一键导入
tui-uat
Run acceptance tests on the mold TUI. Use when asked to test, verify, or UAT the TUI, or after making TUI changes that need visual verification.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Run acceptance tests on the mold TUI. Use when asked to test, verify, or UAT the TUI, or after making TUI changes that need visual verification.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | tui-uat |
| description | Run acceptance tests on the mold TUI. Use when asked to test, verify, or UAT the TUI, or after making TUI changes that need visual verification. |
| argument-hint | test-scope |
Run the mold TUI inside a native Ghostty terminal window for automated acceptance testing. Uses Ghostty 1.3+ AppleScript API for real terminal rendering — proper fonts, true colors, and pixel-perfect screenshots with no conversion artifacts.
macos-applescript = true (default)cargo build -p mold-cli --features tui
Or use the devshell helper: build
All TUI interaction goes through scripts/tui-uat.sh:
# Lifecycle
scripts/tui-uat.sh launch [--fresh] [--env K=V]* [--local] [--host URL]
scripts/tui-uat.sh quit # Close the tracked session's Ghostty window
scripts/tui-uat.sh cleanup # Reap any orphan mold-TUI Ghostty window (state-file-free)
scripts/tui-uat.sh status
scripts/tui-uat.sh env # Print MOLD_HOME / MOLD_DB_PATH
# Screen I/O
scripts/tui-uat.sh capture # Print current screen (plain text)
scripts/tui-uat.sh screenshot [output.png]
scripts/tui-uat.sh view <1-5|name> # 1=Generate 2=Gallery 3=Models 4=Queue 5=Settings
scripts/tui-uat.sh send <key>...
scripts/tui-uat.sh wait-for <pattern> [timeout]
scripts/tui-uat.sh assert <pattern>
# DB / persistence helpers
scripts/tui-uat.sh db [--write] [--force] <sql> # sqlite3 against session DB
scripts/tui-uat.sh db-get <key> # One value from settings table
scripts/tui-uat.sh db-assert <key> <value> # Pass/fail equality check
scripts/tui-uat.sh db-dump # Pretty-print settings + model_prefs
# Settings helpers
scripts/tui-uat.sh settings-focus <appearance|configuration>
scripts/tui-uat.sh theme-set <slug> # mocha|latte|ristretto|gruvbox|tokyo|nord|dracula
# Model + per-model prefs helpers
scripts/tui-uat.sh model <name> # Full picker dance — Parameters → Model → type filter → Enter. Pass the exact `model:tag` to avoid matching the wrong variant.
scripts/tui-uat.sh db-model-assert <model> <col> <v> # Pass/fail on a single `model_prefs` column
--fresh creates a tmp MOLD_HOME and injects it into the TUI's env — zero chance of clobbering the user's real ~/.mold/ state. The isolated directory persists across quit so you can relaunch with --env MOLD_HOME=$(mktemp -d)/… or reuse the path from status to validate persistence.
db-* commands refuse to write to the user's real DB without --force. Use --fresh for any test that mutates state.
Always trap cleanup. Wrap every UAT flow so the Ghostty window is closed even if an assertion fails or the script is interrupted.
cleanupis safe to call repeatedly and will reap orphan windows whose state file was lost:trap 'scripts/tui-uat.sh cleanup >/dev/null 2>&1 || true' EXIT INT TERM
scripts/tui-uat.sh launch --local
This opens a new Ghostty window running mold tui. The --local flag runs inference locally without a server. Use --host http://server:7680 to test against a remote server.
scripts/tui-uat.sh view generate # or: view 1
scripts/tui-uat.sh view gallery # or: view 2
scripts/tui-uat.sh view models # or: view 3
scripts/tui-uat.sh view settings # or: view 4
The view command handles the Generate prompt-focus quirk automatically — it detects prompt focus and uses Tab + Escape to reach Nav mode before sending the view key.
scripts/tui-uat.sh send tab # Tab key
scripts/tui-uat.sh send enter # Enter key
scripts/tui-uat.sh send escape # Escape key
scripts/tui-uat.sh send ctrl+c # Ctrl+C
scripts/tui-uat.sh send ctrl+g # Ctrl+G (generate)
scripts/tui-uat.sh send ctrl+m # Ctrl+M (model selector)
scripts/tui-uat.sh send ctrl+r # Ctrl+R (randomize seed)
scripts/tui-uat.sh send j # Literal 'j' key (sent as text input)
scripts/tui-uat.sh send j k enter # Multiple keys in sequence
Key name reference:
enter, escape, tab, space, up, down, left, right, backspace, delete, home, end, page_up, page_down, f1-f12ctrl+<key>, alt+<key>, shift+<key>, cmd+<key>C-c, C-g, etc. (still supported)input textscripts/tui-uat.sh capture # Full screen dump (plain text)
scripts/tui-uat.sh assert "Parameters" # Check text exists on screen
scripts/tui-uat.sh wait-for "Loaded" 10 # Wait up to 10s for text
capture uses Ghostty's write_screen_file action to get the terminal's rendered text content.
scripts/tui-uat.sh screenshot # Default: tui-screenshot.png
scripts/tui-uat.sh screenshot /tmp/gallery-view.png # Custom output path
Screenshots are taken with screencapture -l<windowID> — capturing the actual Ghostty window with native font rendering, true terminal colors, and proper image display. No ANSI-to-HTML conversion, no scanline artifacts.
scripts/tui-uat.sh quit
| View | Key | Unique landmark | Content |
|---|---|---|---|
| Generate | 1 | ┌ Parameters or ┌ Prompt | Prompt, Parameters, Preview, Info, Progress |
| Gallery | 2 | ┌ Gallery | Image thumbnails in grid, detail view on Enter |
| Models | 3 | ┌ Installed or ┌ Available | Model list with name, family, size, status |
| Settings | 4 | ┌ Settings | Config values: model, dirs, server, expand |
Global: Ctrl+C = quit, Alt+1-4 = switch view
Generate (prompt focused): Enter = generate, Tab = next focus, Escape = nav mode, Ctrl+G = generate, Ctrl+M = model selector, Ctrl+R = randomize seed
Generate (nav mode): 1-4 = switch view, q = quit, Enter = focus prompt
Gallery (grid): hjkl/arrows = navigate, Enter = detail, e = edit, d = delete, u = upscale, o = open
Models: j/k = navigate, Enter = select, p = pull, r = remove, u = unload, / = filter
Settings: j/k = navigate, +/- = adjust values
Escape from prompt focus: The view command works around Generate's prompt focus by detecting "Esc Nav" in the footer and sending Tab + Escape to reach Nav mode.
First key after Nav mode: The first character key after entering Generate nav mode may be consumed by a crossterm timing issue. The view command retries automatically.
Session persistence (since #264): TUI state lives in the SQLite metadata DB at ~/.mold/mold.db — settings table for global TUI prefs (theme, last_model, last_prompt, negative_collapsed), model_prefs table for per-model generation parameters (one row per resolved model tag), prompt_history table for the prev/next prompt stack. ~/.mold/tui-session.json and ~/.mold/prompt-history.jsonl are imported once on first launch and renamed to .migrated; they're no longer written. For a clean slate, isolate the DB with MOLD_DB_PATH=$(mktemp -d)/mold.db scripts/tui-uat.sh launch … (legacy: deleting ~/.mold/mold.db also works but wipes the gallery DB too). MOLD_DB_DISABLE=1 boots the TUI with in-memory-only defaults — useful for verifying the fail-safe fallback.
MOLD_BIN: Override the binary path: MOLD_BIN=./target/release/mold scripts/tui-uat.sh launch
Clipboard: The capture command temporarily uses the clipboard (via write_screen_file:copy,plain). It saves and restores the previous clipboard content.
Per-model prefs auto-save (since #264): switching model via Ctrl+M → pick → Enter snapshots the outgoing model's generation params into model_prefs keyed on the resolved tag, then overlays the incoming model's saved row on top of manifest/catalog defaults. Prompts are not restored on switch — only generation params (width/height/steps/guidance/scheduler/seed_mode/batch/format/lora/expand/offload/strength/control_scale). To UAT: set FLUX to 512×512 steps=4, switch to SDXL, verify SDXL's own defaults appear; switch back to FLUX, verify 512×512 steps=4 returned.
trap 'scripts/tui-uat.sh cleanup >/dev/null 2>&1 || true' EXIT INT TERM
scripts/tui-uat.sh launch --local
scripts/tui-uat.sh view generate
scripts/tui-uat.sh assert "Parameters"
scripts/tui-uat.sh assert "Model"
scripts/tui-uat.sh assert "Preview"
scripts/tui-uat.sh screenshot /tmp/generate-view.png
scripts/tui-uat.sh view gallery
scripts/tui-uat.sh assert "Gallery"
scripts/tui-uat.sh view models
scripts/tui-uat.sh assert "flux2-klein"
scripts/tui-uat.sh screenshot /tmp/models-view.png
scripts/tui-uat.sh view settings
scripts/tui-uat.sh assert "Settings"
scripts/tui-uat.sh quit
Full quit/relaunch round-trip against an isolated DB. --fresh allocates a
tmp MOLD_HOME; stash its path from env so the re-launch can reuse it.
trap 'scripts/tui-uat.sh cleanup >/dev/null 2>&1 || true; [ -n "${MOLD_HOME:-}" ] && rm -rf "$MOLD_HOME"' EXIT INT TERM
# Round 1: fresh isolated env, set theme via helper, write a prompt
scripts/tui-uat.sh launch --fresh --local
eval "$(scripts/tui-uat.sh env)" # exports MOLD_HOME + MOLD_DB_PATH
scripts/tui-uat.sh theme-set dracula # cycles + asserts
scripts/tui-uat.sh view generate
scripts/tui-uat.sh send "a test prompt" # single arg is sent as literal text
scripts/tui-uat.sh send escape # exit textarea focus
scripts/tui-uat.sh send ctrl+c # quit (writes settings + model_prefs)
# Round 2: relaunch with the *same* MOLD_HOME → DB survives
scripts/tui-uat.sh launch --env "MOLD_HOME=$MOLD_HOME" --local
scripts/tui-uat.sh db-assert tui.theme dracula
scripts/tui-uat.sh db-assert tui.last_prompt "a test prompt"
scripts/tui-uat.sh screenshot /tmp/uat-persistence.png
scripts/tui-uat.sh quit
rm -rf "$MOLD_HOME" # tmp dir cleanup is manual
The cleanest strategy is DB-seed-then-verify-UI, plus a model switch
that exercises update_model's snapshot/restore path. Every field in
model_prefs gets checked: width, height, steps, guidance, scheduler,
seed_mode, batch, format, lora_path, lora_scale, expand, offload,
strength, control_scale.
ISO=$(mktemp -d /tmp/mold-uat.XXXXXX)
trap 'scripts/tui-uat.sh cleanup >/dev/null 2>&1 || true; rm -rf "$ISO"' EXIT INT TERM
scripts/tui-uat.sh launch --env "MOLD_HOME=$ISO" --local
sleep 2
# Seed two models with DISTINCT values across every preserved field.
scripts/tui-uat.sh db --write "
INSERT OR REPLACE INTO model_prefs
(model, width, height, steps, guidance, scheduler, seed_mode, batch, format,
lora_path, lora_scale, expand, offload, strength, control_scale, updated_at_ms)
VALUES
('flux2-klein:q8', 832, 1152, 7, 2.5, 'ddim', 'fixed', 3, 'jpeg',
'/a.safetensors', 0.75, 1, 1, 0.8, 1.5, 1000),
('flux-dev:q4', 1024, 768, 30, 4.0, 'eulerancestral', 'increment', 2, 'png',
'/b.safetensors', 0.50, 0, 0, 0.6, 1.0, 1000);
INSERT OR REPLACE INTO settings (key, value, value_type, updated_at_ms)
VALUES ('tui.last_model', 'flux2-klein:q8', 'string', 1000);
"
scripts/tui-uat.sh quit
scripts/tui-uat.sh launch --env "MOLD_HOME=$ISO" --local
sleep 3
# Starts on flux2-klein:q8, which should load its seeded values.
scripts/tui-uat.sh assert "832"
scripts/tui-uat.sh assert "1152"
scripts/tui-uat.sh assert "Steps 7"
scripts/tui-uat.sh assert "Guidance 2.5"
# Switch to flux-dev:q4 via the real popup flow.
scripts/tui-uat.sh model 'flux-dev:q4'
sleep 0.5
scripts/tui-uat.sh assert "1024"
scripts/tui-uat.sh assert "Steps 30"
scripts/tui-uat.sh assert "Guidance 4.0"
# Switch back — flux2-klein's saved row must overlay manifest defaults.
scripts/tui-uat.sh model 'flux2-klein:q8'
sleep 0.5
scripts/tui-uat.sh assert "832"
scripts/tui-uat.sh assert "Steps 7"
# Direct DB assertions for the fields that don't always render in the UI
# (scheduler, lora, strength, control_scale are conditionally visible).
for col in width height steps guidance scheduler seed_mode batch format \
lora_scale expand offload strength control_scale; do
scripts/tui-uat.sh db-model-assert flux2-klein:q8 "$col" \
"$(sqlite3 "$ISO/mold.db" "SELECT $col FROM model_prefs WHERE model='flux2-klein:q8';")"
scripts/tui-uat.sh db-model-assert flux-dev:q4 "$col" \
"$(sqlite3 "$ISO/mold.db" "SELECT $col FROM model_prefs WHERE model='flux-dev:q4';")"
done
scripts/tui-uat.sh quit
rm -rf "$ISO"
trap 'scripts/tui-uat.sh cleanup >/dev/null 2>&1 || true' EXIT INT TERM
scripts/tui-uat.sh launch --fresh --env MOLD_DB_DISABLE=1 --local
scripts/tui-uat.sh view settings
scripts/tui-uat.sh assert "Appearance" # still renders
scripts/tui-uat.sh quit # no crash on shutdown save
Run all three fast checks in sequence — suitable for CI.
set -e
trap 'scripts/tui-uat.sh cleanup >/dev/null 2>&1 || true' EXIT INT TERM
scripts/tui-uat.sh launch --fresh --local
scripts/tui-uat.sh view settings
scripts/tui-uat.sh theme-set gruvbox
scripts/tui-uat.sh db-assert tui.theme gruvbox
scripts/tui-uat.sh view generate
scripts/tui-uat.sh assert "flux2-klein"
scripts/tui-uat.sh view gallery && scripts/tui-uat.sh assert "Gallery"
scripts/tui-uat.sh view queue && scripts/tui-uat.sh assert "Queue"
scripts/tui-uat.sh view models && scripts/tui-uat.sh assert "FAMILY"
scripts/tui-uat.sh quit