Guide Profiles Model Configs Container Lifecycle Using the TUI Dev Builds

Using the TUI

The TUI is llmux's default interface — a single Textual dashboard that manages vLLM and llama.cpp profiles side by side. Everything the headless CLI does is available here as keyboard-driven screens and forms.

Launching

llmux          # no arguments → launches the TUI
llmux tui      # explicit

Running llmux with no subcommand drops you straight into the unified dashboard.

Language (English / Korean)

The TUI is bilingual. It follows your system locale by default (a ko_* LANG/LC_ALL gives Korean, anything else English). Force one with LLMUX_LANG=en llmux or LLMUX_LANG=ko llmux. Table column headers and engine-flag names stay in English in both modes.

The dashboard

The dashboard is one DataTable showing every profile from both backends. Running containers float to the top so the active workload is always visible without scrolling; within the running / stopped groups, rows stay sorted by (backend, name).

┌ llmux ─ vLLM + llama.cpp ───────────────────────────────────────────────────────────────────┐
│  vLLM 1/2  ·  llama.cpp 0/1  ·  Enter = actions                   │
├─────────────────────────────────────────────────────────────────────┤
│ Status      Backend    Profile      Port   tok/s  Model        Detail  │
│ ● running   vLLM       qwen3-8b     8000   62.4   Qwen3-8B     TP=1    │
│ ○ stopped   llama.cpp  gemma-3-4b   8080   —      gemma-3-4b   —       │
│ ○ stopped   vLLM       qwen3-0-6b   8001   —      Qwen3-0.6B   —       │
└─────────────────────────────────────────────────────────────────────┘
 GPU0 ████████░░░░ 64%  12.1/24GB
 🔍  Estimate HF model memory (press m then type, Enter to run)

A status bar shows running / total counts per backend. Container status preserves healthy, running, starting, unhealthy, paused, restarting, removing, created, exited, dead, unknown, and stopped rather than reducing every non-running state to stopped. The tok/s column shows live generation throughput for each running model, polled from its /metrics endpoint every 3 seconds (see llmux stats). Missing metrics display —, while an HTTP polling failure displays error and raises a notification. A GPU bar below the table auto-refreshes every few seconds, and the table itself re-scans every 5 seconds. The memory-estimator search row is hidden by default to keep the dashboard compact — press m to reveal it (and Esc to hide it again).

Keyboard shortcuts

Move the cursor with ↑ / ↓, then act on the selected row.

Dashboard

KeyActionNotes
EnterOpen the action menu for the selected profileContext-aware (running vs. stopped)
nNew profileOpens the backend picker, then Quick Setup
mMemory estimatorToggles the HF model search row (hidden by default); Esc hides it
CConfigsOpens the config list for the selected row's backend — new, edit, clone, rename, delete
sSystem infoFor the selected row's backend (or asks)
tTerminal monitorThe v monitor in a plain terminal (suspends the TUI); q returns
rRefreshRe-scan all profiles and container status
qQuit
uStart containerPower-user shortcut (hidden from footer)
pPrepareDownload the model + render setup without starting; stopped profiles only
dStop containerPower-user shortcut
lView logsWorks for stopped containers too (last-run logs)
vLive monitorbtop-style system view — GPUs always, plus every running model (throughput/KV graphs, cache-hit, latency percentiles, PCIe)
eEdit profilePower-user shortcut
cEdit configPower-user shortcut
xDelete profileStopped containers only
UCheck for updatesAsks GitHub on demand (same as llmux update); offers to pull a newer release
?HelpQuick key reference popup

The u / p / d / l / e / c / x keys are deliberately hidden from the footer — they do exactly the same thing as picking the matching item from the Enter action menu.

App-level

KeyAction
qQuit
F1Return to the dashboard
?Help

Log / startup viewers

KeyAction
fToggle auto-follow on/off
↑ / ↓ / PgUp / PgDnScroll
q / EscBack / close

The action menu

Pressing Enter on a profile opens a context menu. The options depend on whether the container is running:

StateAvailable actions
RunningStop Container · View Logs · Monitor · Benchmark · Edit Profile · Clone Profile · Render Runtime Env · Edit Config
StoppedStart Container · Prepare (download only) · View Logs · Edit Profile · Clone Profile · Render Runtime Env · Edit Config · Delete Profile

Prepare (download only) fetches the image and the weights and stops there — see prepare. Benchmark discards one warmup request, runs 3 measured /v1/chat/completions requests, and reports median tokens/second. Render Runtime Env regenerates the selected profile's .runtime file from profiles.yaml. Delete is blocked while a container is running — stop it first. To rename a profile, edit its Name field in the profile form (also only while the container is stopped, since it's named after the profile).

Live monitor

Press v on any row (or pick 📊 Monitor from the action menu) to open a full-screen, btop-style system view. It polls nvidia-smi and each running server's /metrics once a second. Opening it does not require a running container — with nothing up you still get the GPU panel, which is usually the reason to open a monitor at all.

Always shown:

Then one panel per running model — the running list is re-scanned every tick, so a model started elsewhere appears on its own. With exactly one model up you get the full detail view; with several, each gets a compact summary row (tok/s, KV, running/waiting, TTFT, TPOT).

Both backends work — the differing Prometheus metric names are matched by family, and any metric a backend doesn't expose reads — rather than a made-up value. GPU, backend, and metrics request failures appear as monitor notices; the header lag includes GPU, PCIe, model discovery, and metrics collection for the whole tick. Keys: p pause, r reset peaks, +/- poll interval, l language, Esc/q back.

Terminal monitor (plain)

Press t on any row to suspend the Textual UI and open the same monitor — the same GPU panel, braille graphs, cache-hit, and latency percentiles — as a plain-terminal page in your normal terminal, auto-refreshing every second. No Textual rendering, so it holds up over low-bandwidth SSH or on terminals that render the TUI poorly. Same keys; q (or Ctrl+C) returns.

The same monitor is available without the TUI at all: llmux top [PROFILE]. Omit the profile to show every running model. With a profile, one backend's confirmed match is enough to start the monitor even if the other backend scan fails. If no backend confirms the target and a scan failed, the command exits 2 because the target is unknown; after a complete scan confirms that it is stopped, it exits 1.

Quick Setup

n opens a backend picker, then a Quick Setup form that creates a matching profile + config in one step. For vLLM the form takes a Hugging Face model id, an optional profile name, GPU id, port, GPU-memory-utilization, an Enable-LoRA toggle, an optional config to copy, and optional official-recipe review. llama.cpp provides the equivalent GGUF repository/file and runtime settings. Its Hugging Face file lookup fails explicitly on malformed or partial listings and when the pagination safety cap is reached. Authentication is sent only to the configured Hugging Face origin, never to an off-origin pagination or redirect target.

System screen

Press s to open the selected backend's System screen. Its Docker Images tab can refresh, pull, remove, or build a dev image without starting a container. The Environment tab validates .env.common and renders runtime env files for every profile of that backend; profile action menus can render one selected profile. Token values are never displayed.

Memory estimator

Press m (or click the search box) and type a Hugging Face model id, then Enter. llmux estimates the model's memory footprint and renders it against your detected GPUs:

This runs entirely on the dashboard — no profile or container needed.

Container start screen

Picking Start Container opens a full-screen launcher with a Version radio set. The options differ per backend:

Five startup modes:

ModeWhat it does
Local LatestHighest local vllm/vllm-openai versioned tag
Official ReleasePulls Docker Hub's latest stable version (explicit semver, never :latest)
NightlyPulls vllm/vllm-openai:nightly
Dev BuildUses / builds vllm-dev:<branch> from source — reveals Repo URL + Branch inputs
Custom TagAn arbitrary image tag you type in

Three startup modes — llama.cpp has a single official ghcr.io tag, so "Local / Official / Nightly" collapses into one:

ModeWhat it does
Default ImageLLAMACPP_IMAGE from .env.common, or ghcr.io/ggml-org/llama.cpp:server-cuda when unset
Dev BuildUses / builds llamacpp-dev:<branch> from source — reveals Repo URL + Branch inputs
Custom TagAn arbitrary <repo>:<tag> you type in

If the profile is already pinned to a llamacpp-dev: image via its image_tag, the screen shows that pin — selecting Default Image or Custom Tag overrides it for that launch only.

Selecting Dev Build reveals Repo URL and Branch inputs, pre-filled from .env.common. Pressing Start streams the startup log live, then switches to following the container's logs. See Dev Builds for the build mechanics.

Conflict gate before start

After you select a version and press Start, llmux lists running profiles sharing the target GPUs and offers Stop and start. Confirming stops those models, verifies they have exited, then starts the selected model. Opening or cancelling the version screen leaves existing models running. Port conflicts and failed port probes block startup unless the port belongs to a model being replaced. A failed stop prevents the new model from starting; a failed new start does not restart the old models automatically.

Profile and config forms

Edit Profile and Edit Config open modal forms:

The profile delete confirmation includes an off-by-default switch to remove the linked config when it is no longer shared. Tracked example configs and configs still referenced by another profile are protected.

Both forms map straight onto profiles.yaml and the config YAML — there is no separate TUI state.

See also