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

Utility & Layout Widgets

The five windows that hold your layout together rather than reporting on the game — and the four of them you can only add by typing the long form.

What it’s for

Most windows in this manual show you something about your character. These five do a job instead: they pad a layout, host your typing, report on the client itself, or hand a panel to something outside the game.

You reach for them rarely and deliberately. The catch is that four of the five are close to invisible in the interface, which is what the rest of this page is mostly about.

⚠️ Only spacer is in the catalog. The other four exist, but nothing offers them. command_input, performance, webui, and dialogpanel are all valid window types, and none of them appears in the GUI Windows catalog or in the picker you get from a bare .addwindow. The full six-argument .addwindow form is the only way to type one into existence — and for two of them, typing it is the wrong move anyway (see below).

A window already in your layout is a different matter: command_input and spacer both show up in the hide and edit pickers once they exist. It is only adding that is closed.

⚠️ A misspelled widget type does not error — it silently gives you a text window. There is no “unknown type” message. Three of these five accept two spellings, and the near-misses are exactly the ones you’d guess wrong:

TypeAlso acceptedGuessing wrong gives you
command_inputcommandinputa text window
performancea text window
webuilichuia text window
dialogpaneldialog_panela text window
spacera text window

If you typed .addwindow and got an empty bordered box, check your spelling first.

Set it up

This tabbed block covers the shared gesture — adding a window that isn’t in the catalog. Each widget’s own section below adds what’s specific to it.

  1. For spacer, click Windows in the top toolbar, expand Other, and tick the spacer row. Repeat for as many as you need — each gets its own generated name.
  2. For the other four, type the full form in the command input, for example .addwindow gaps spacer 10 4 6 2 or .addwindow perf performance 0 0 40 10. The catalog will not offer them, and there is no right-click Add anywhere in the GUI.
  3. Position it by dragging, and set borders and background through right-click ▸ Appearance like any other window.
📷 screenshot pending
A performance window added by typed command, showing frame, render, and network timings beside a text window.

Expected result: the window appears at the coordinates you gave. A spacer shows as blank space; a performance window immediately starts printing timings.

Common setups

spacer — layout padding

The only widget here that is in the catalog, and the only one most players will use.

A spacer draws nothing. It occupies grid space so the windows around it land where you want them, which is how you get a gap between two bars or push a strip to one side without giving those windows sizes that fight you on the next resize.

It never draws a border and never draws a title — the preset turns both off, deliberately. It respects your theme background rather than punching a hole in the layout.

Its minimum size is 1 by 1, the smallest of any widget. That matters: a thin alignment spacer survives a resize. Everything else in the layout floors at 5 cols by 3 rows, so a narrow strip of any other type gets clamped up and shoves the layout along after it.

Spacers are dynamically named — spacer_1, spacer_2 — and they show up in the hide and edit pickers under Other. .editwindow on a spacer offers no widget fields, only the standard geometry and border ones.

You’ll see: blank space that holds its place, letting the windows on either side keep the sizes you gave them.

command_input — your typing line as a real window

Every frontend always has somewhere to type. So why would you add one?

Because the command input is a normal dockable window, and the always-there version is a fallback. In the desktop GUI the input is a placeable window like any other — you can move it, resize it, style it, and park it in a shell zone. The GUI watches whether that window actually rendered this frame; if it didn’t — because the definition is missing, the window is hidden, or its zone is collapsed — it paints a fixed panel at the bottom of the screen instead, so the input can never be lost. That fallback panel is not movable and has no grip.

So: the input you see by default is either your window or the safety net, and adding or styling a command_input window is how you take charge of which.

The default layout already ships a command_input window, so in practice you edit that one rather than adding a second.

Settings. This is the widest widget form on this page. TUI .editwindow exposes Prompt icon, Prompt icon color, Text color, Cursor color, Cursor background, and Completion color — the color of the greyed history suggestion. The GUI has no widget section for it, so those six fields are terminal-authored; the GUI reads them from the layout.

You’ll see: a prompt character in your chosen color ahead of the cursor, and a dimmed history suggestion completing as you type.

performance — the client’s own vitals

A window of frame timings, render and UI times, text-wrap cost, network and parse throughput, event counts, CPU, and memory. It reports on VellumFE, not on your character.

Reach for it when the client feels slow and you want to know which part is slow — or when you’re reporting a problem and want numbers to attach.

Metrics collection runs at all times, so the window is accurate the moment you open it; there’s nothing to enable first. Every section has its own toggle, and all ten default to on.

TUI .editwindow gives you an Edit metrics entry for those toggles. The GUI has no widget section, so which metrics show is terminal-authored.

The Performance Monitor reference documents what every number means — read it there rather than guessing from the labels.

You’ll see: live timings that move as you play, with the slow section standing out from the rest.

webui — a Lich script’s own panel

A WebUI window hosts a page published by a Lich script, so a script can give you real controls inside your layout instead of printing text at you.

⚠️ Do not add this one with .addwindow. Type .webui <script/page> instead — for example .webui creaturebar/main. That builds the window and binds it to the page, sizing it from the page’s own hint. .webui with no argument opens a picker of registered pages, and .webui off closes the panel.

A window you add by hand with .addwindow … webui … has an empty page binding and shows nothing, with no way to fill it in: neither frontend’s editor exposes the page field.

Windows made this way are named webui:<page>, which is why you may see that prefix in your window lists.

You’ll see: a script’s own interface — buttons, lists, whatever it published — sitting in your layout as a native window.

dialogpanel — a resident game dialog, kept on screen

The game sends some interfaces as dialogs rather than text: the combat panel and similar resident controls. A dialog panel window renders one of them by id, from the accumulated store of dialog data the client keeps.

⚠️ These arrive on their own — you don’t add them. When the game opens a resident dialog, the client records it and builds the panel, placing it from the dialog’s own declared position and size hints. It then appears in your Windows list, where you tick it to show and untick it to hide.

A dialogpanel you add by hand with .addwindow has an empty dialog id and renders nothing, and no editor in either frontend exposes that id — the game defines these controls.

Game-created panels are session windows. They don’t persist to your layout the way a text window does, and a panel that was placed by the game reopens where the game’s hints put it, unless you’ve moved it and it saved a position for that id.

Effect dialogs are a separate story with their own widget — see Active Effects, which is fed by four named dialogs and is what you actually want for buffs, debuffs, cooldowns, and active spells.

You’ll see: the game’s own panel as a window you can place, rather than as text scrolling past in your story pane.

Tips & gotchas

⚠️ “Not in the catalog” is not the same as “not supported”. All five render fully and reload from your layout file correctly. What four of them lack is a way to add them by pointing — and for webui and dialogpanel, that’s because a different route creates them properly bound.

⚠️ Hiding the command input means two different things. In the desktop GUI the window goes away and the fixed fallback bar takes over. In the terminal the flag is saved but the input stays on screen, with a message explaining why: “Command input hidden in the layout (GUI shows its fallback bar); the TUI keeps it visible.” One layout, two behaviors, on purpose.

⚠️ Bare .hidecontainers closes dialog panels too. It reports the count as “container window(s)”, which is misleading — it closes every session window, panels included. Name a container explicitly if you only meant to close a bag.

Use a spacer rather than oversizing a neighbor. A spacer’s 1 by 1 floor is what lets it stay thin. Padding a layout by making the window next to it wider works until the next resize redistributes the space and moves everything after it.

The editors are lopsided here, and the terminal usually wins. command_input and performance both have real terminal forms and no GUI widget section at all. If a setting on this page seems to have no home in the desktop GUI, that is why — author it once in the terminal and the GUI reads it from the layout.

See also

  • Performance Monitor — what every metric in the performance window means
  • Active Effects — the dialog-fed widget you probably want instead of a raw dialog panel
  • Containers — the other session-only windows .hidecontainers reaches
  • Creating Layouts — placing, saving, and restoring all of these
  • Widgets — the full roster, and the three routes for adding any of them
Config reference (TOML)

All five accept the standard window keys — row, col, rows, cols, show_border, border_style, border_sides, title, show_title, locked — as any window does. Only spacer can be created from the catalog.

Type strings and aliases

Widgetwidget_typeAliasIn the catalog?Minimum size
Spacerspacer✅ yes1 col x 1 row
Command inputcommand_inputcommandinput❌ no5 x 3 (default floor)
Performanceperformance❌ no20 cols x 4 rows
WebUI panelwebuilichui❌ no5 x 3 (default floor)
Dialog paneldialogpaneldialog_panel❌ no14 cols x 4 rows

An unrecognized widget_type falls back to text with no error.

spacer

[[windows]]
name = "spacer_1"
widget_type = "spacer"
row = 10
col = 4
rows = 2
cols = 6
show_border = false
show_title = false

No widget fields. Borders and titles are off by design.

command_input

[[windows]]
name = "command_input"
widget_type = "command_input"
row = 44
col = 0
rows = 1
cols = 120
locked = true
prompt_icon = ">"
FieldTypeDefaultWhat it does
prompt_iconstringnoneCharacter or short string before the cursor
prompt_icon_colorstringnoneIts color
input_text_colorstringnoneTyped text color. Reads a legacy text_color key from old files
cursor_colorstringnoneCursor foreground
cursor_background_colorstringnoneCursor background
completion_colorstringnoneThe greyed inline history suggestion

Preset pins the window to exactly 1 row and ships it locked = true.

performance

[[windows]]
name = "performance"
widget_type = "performance"
rows = 10
cols = 40
show_fps = true
show_memory = true
FieldTypeDefaultWhat it does
enabledbooltrueDraw the window’s contents
show_fpsbooltrueFrame rate
show_render_timesbooltrueRender timings
show_ui_timesbooltrueUI build timings
show_wrap_timesbooltrueText-wrap cost
show_netbooltrueNetwork throughput
show_parsebooltrueParser throughput
show_eventsbooltrueEvent counts
show_cpubooltrueCPU usage
show_memorybooltrueMemory usage

webui

[[windows]]
name = "webui:creaturebar/main"
widget_type = "webui"
page = "creaturebar/main"
FieldTypeDefaultWhat it does
pagestring""The script/page id this window hosts. Written by .webui; no editor exposes it

dialogpanel

[[windows]]
name = "combat"
widget_type = "dialogpanel"
dialog_id = "combat"
FieldTypeDefaultWhat it does
dialog_idstring""Which dialog’s controls to render. Set by the client when the game opens the dialog; no editor exposes it

Where the settings live

WidgetGUI widget sectionTUI .editwindow
spacernoneno widget fields
command_inputnonesix color and prompt fields
performancenoneEdit metrics toggles
webuinonenone — page set by .webui
dialogpanelnonenone — the game defines the controls