Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Frontends

One character, one set of settings, five ways to sit down and play — pick the one that matches where you are right now.

What it’s for

You hunt at your desk, but you also want to check on a bounty from the couch, or keep a character parked over SSH on a box that has no desktop at all. VellumFE gives you five interfaces over one core, so the highlight that colors your critical hits, the keybind on your numpad, and the layout you spent an evening arranging follow you from the terminal to the desktop window to your phone. You configure a thing once. It shows up everywhere it can be shown.

The differences between the five are about what the surface can physically do — a terminal cannot draw a skin image, a phone cannot let you drag a window to a new corner — not about which one is the “real” client.

📷 screenshot pending
The same character in three frontends at once: the Desktop GUI hunting layout, the same layout in a terminal, and the phone's status drawer.

The five at a glance

FrontendHow you start itReach for it whenMaturity
Terminal (TUI)--frontend tui (the CLI default)You live in a terminal, play over SSH, or want the smallest possible footprintStable
Desktop GUI--frontend gui, or launch a saved connection (its default)You want mouse-first layout work, graphics, skins, and the stay-open toolbar hubsStable
Mobile WebEnable the web server (--web-port, or [web] in config.toml), then open the address in a browserYour PC is running the session and you want a second screen, or you want to play from a browser with no local UI at allStable
Android appSideloaded APKThe whole client on an Android phoneIn progress
iOS appTestFlightThe whole client on an iPhoneBeta — via TestFlight

Two of those rows carry a wrinkle worth stating plainly.

“Mobile Web” is two different products depending on how you start it. Run the TUI or GUI with the web server on and the browser is a sidecar — a second screen driving the session your PC already owns. Run --frontend headless and there is no local UI at all: the core plus the web server is the client, and the browser gets a login screen. Same code, different shape.

The Android and iOS apps are not a third thing. They are the same Rust core in a native shell, showing the web client’s UI in a WebView. What the shell adds is a saved Characters picker — the one native screen — so a phone can scan a pairing QR code and seal a saved server into the Keychain or Keystore. On a phone the login screen shows two tabs (play.net and Lich) plus that picker, reached through the person icon; a desktop browser shows three tabs, because it keeps the in-page Remote tab the phone replaces.

Set it up

Pick where you’re playing, then start the client that way. Every one of these connects the same character to the same game.

  1. Run vellum-fe with no arguments (or double-click it). The VellumFE Launcher window opens, headed VellumFE over “Choose a connection to launch”.
  2. Click ➕ New connection, fill in the New connection form, and click Save.
  3. Click Launch on the row you just made.

To start the GUI without going through the Launcher, run vellum-fe --frontend gui --port 8000 --character YourName.

Which frontend a saved connection uses is set per row under AdvancedFrontendGUI / Terminal. A saved connection defaults to GUI, but the --frontend command-line flag defaults to tui — the same character started two ways lands in two different interfaces. That surprise is worth knowing before you go looking for a bug.

📷 screenshot pending
A connection's Advanced section with the Frontend submenu open on GUI / Terminal.

Expected result: a native window opens with your layout, and the top toolbar shows the Windows, Settings, Zones, and Editors hubs.

Common setups

One character, desk and couch

Start the GUI from the Launcher and enable the web server on the same run. Play at the desk normally. When you get up, run .webinfo, scan the QR with your phone, and the phone joins the same session — the same roundtime, the same room, the same active spells. Nothing syncs, because nothing needed to: there is one session and two views of it.

You’ll see: your health bar moving on the phone at the same instant it moves on the monitor, and a command typed on either one landing in the game once.

A character parked on a headless box

On a server or a Raspberry Pi with no desktop, run vellum-fe --frontend headless --port 8000 --character YourName --web-port 8080 --web-bind 0.0.0.0. There is no local UI at all. Point any browser on your network at that box’s address and the browser is the entire client — including its own login screen, since there’s no desktop session to attach to.

You’ll see: the browser presenting a login overlay rather than immediately showing a game already in progress — that is how you tell headless from sidecar at a glance.

Tips & gotchas

⚠️ Ctrl+C means two different things. In the Terminal (TUI) it copies your selection and does not quit. In the Desktop GUI it quits. To leave the client from the terminal, use .quit or .exit. This is the single biggest trap when you move between the two.

⚠️ .quit may not close the window. By default it disconnects but leaves the client open — run it again, or use .exit, to close. Turn this off with ui.keep_open_on_quit in Settings.

  • The two “Launchers” are unrelated. The Launcher is the graphical connection list you get by running with no arguments. The SSH Launcher is an in-session panel (.launcher / .launch <character>) that cold-starts a headless Lich on another machine. They share a word and nothing else.
  • The terminal cannot render images, and that is deliberate. Skins, per-window background art, and the graphical injury doll, compass, and hand icons are GUI-only forever — a character cell has no pixels to put them in. The TUI renders the same information with glyphs and color. Nothing is missing from your character; only the artwork is.
  • Layouts are shared, appearance is not entirely. .savelayout and .loadlayout work in both desktop frontends against the same pool, so a layout you build in the GUI opens in the TUI. Skin frames inside it simply have nothing to draw on the terminal side.
  • Saving a layout is always typed. There is no GUI button for it — .savelayout <name> in either desktop frontend. The Windows catalog says so itself.

See also

Config reference (TOML)

Frontend selection is a command-line and per-connection concern; these are the settings that decide which face you get and how it reaches the network.

Command line

FlagTypeDefaultWhat it does
--frontendtui | gui | headlesstuiWhich interface to run. headless runs the core plus web server with no local UI.
--launcherflagoff (on when run with no arguments)Opens the graphical Launcher. GUI only.
--launch-profile <NAME>stringRuns a saved connection by name from launcher.toml. Conflicts with --direct, --key, --launcher.
--portu168000Lich proxy port. Overrides config.toml.
--hoststring127.0.0.1Lich proxy host. Overrides config.toml.
--characterstringCharacter to log in as (direct mode); also the fallback config-directory name.
--profilestringfalls back to --characterConfig-directory name, kept separate from the login name.
--directflagoffConnects to play.net without Lich. Enables --account, --password, --game.
--web-port <PORT>u16Enables the embedded web server on this port. Overrides [web].
--web-bind <ADDR>stringAddress the web server binds to. Overrides [web].
--data-dir <DIR>path~/.vellum-feConfig directory root. Also settable via VELLUM_FE_DIR.

Per-connection (launcher.toml, written by the Launcher)

FieldTypeDefaultWhat it does
frontend"gui" | "tui""gui"Which frontend this saved connection launches. Note the mismatch with the --frontend CLI default of tui.
save_passwordboolfalseStores the password in the OS credential store (service id vellum-fe, keyed by the lowercased account). Never written to a file.

Session behavior (config.toml)

FieldTypeDefaultWhat it does
ui.keep_open_on_quitbooltrueAfter .quit, disconnect but keep the window open. Run .quit again or .exit to close.