VellumFE
A modern terminal client for GemStone IV, built in Rust.
Features
- Fast rendering - 60+ FPS with efficient text handling
- Customizable layouts - Position and size every window
- Flexible connections - Lich proxy or direct eAccess authentication
- Rich highlighting - Regex-based text coloring with sound alerts
- Full keyboard control - Rebindable keys for all actions
Quick Start
# Connect via Lich (most common)
vellum-fe --port 8000
# Direct connection (no Lich required)
vellum-fe --direct --account ACCOUNT --password PASS --character NAME
Configuration
VellumFE stores configuration in ~/.vellum-fe/:
| File | Purpose |
|---|---|
config.toml | General settings |
layout.toml | Window positions and sizes |
keybinds.toml | Keyboard shortcuts |
highlights.toml | Text highlighting rules |
colors.toml | Color palette |
Getting Help
- GitHub Issues: github.com/Nisugi/VellumFE/issues
- In-Game: Find us on the amunet channel
Getting Started
This section covers installation and your first connection to GemStone IV.
Requirements
- Operating System: Windows 10+, macOS 10.15+, or Linux
- Terminal: A terminal with 256-color or true-color support
- Connection: Either Lich running, or direct eAccess credentials
Chapters
- Installation - Download and set up VellumFE
- First Launch - Connect and explore the interface
Installation
Download
Download the latest release from GitHub Releases.
| Platform | File |
|---|---|
| Windows | vellum-fe-windows.zip |
| macOS | vellum-fe-macos.tar.gz |
| Linux | vellum-fe-linux.tar.gz |
Extract the archive and place vellum-fe (or vellum-fe.exe) somewhere in your PATH.
Building from Source
Requires Rust 1.70+.
git clone https://github.com/Nisugi/VellumFE.git
cd VellumFE
cargo build --release
The binary will be at target/release/vellum-fe.
Windows: OpenSSL for Direct Mode
Direct eAccess authentication requires OpenSSL. Install via vcpkg:
vcpkg install openssl:x64-windows
set VCPKG_ROOT=C:\path\to\vcpkg
cargo build --release
Verify Installation
vellum-fe --version
Should display the version number (e.g., vellum-fe 0.2.0-beta.11).
Configuration Directory
On first run, VellumFE creates ~/.vellum-fe/ with default configuration files.
You can override this location with the VELLUM_FE_DIR environment variable:
export VELLUM_FE_DIR=/custom/path
First Launch
Connecting via Lich (Recommended)
Most players use Lich for scripting. Start Lich first, then:
vellum-fe --port 8000 --character YourCharacter
--port- Lich’s listening port (default: 8000)--character- Your character name (used for per-character layouts)
Direct Connection
Connect without Lich using eAccess authentication:
vellum-fe --direct \
--account YOUR_ACCOUNT \
--password YOUR_PASSWORD \
--character YourCharacter \
--game prime
Games: prime, platinum, fallen, test
Note: Direct mode requires OpenSSL on Windows. See Installation.
The Interface
On successful connection, you’ll see the default layout:
┌─────────────────────────────────────────────────────────┐
│ Main Window │
│ [Game text appears here] │
│ │
├─────────────────────────────────────────────────────────┤
│ > [Command Input] │
└─────────────────────────────────────────────────────────┘
Basic Controls
| Key | Action |
|---|---|
Enter | Send command |
Page Up/Down | Scroll main window |
Ctrl+C | Copy selected text |
Escape | Close menus / cancel |
F1 | Open main menu |
Mouse Controls
- Click links to interact with objects
- Right-click for context menus
- Scroll wheel to scroll windows
- Drag window borders to resize (in edit mode)
Next Steps
- Configuration - Customize settings
- Widgets - Learn about available widgets
- Customization - Create custom layouts
Configuration
VellumFE uses TOML files for configuration, stored in ~/.vellum-fe/.
Configuration Files
| File | Purpose |
|---|---|
| config.toml | General settings (UI, connection, behavior) |
| layout.toml | Window positions, sizes, and properties |
| keybinds.toml | Keyboard shortcuts |
| highlights.toml | Text highlighting rules |
| colors.toml | Color palette definitions |
Per-Character Configuration
When you specify --character NAME, VellumFE looks for character-specific files:
~/.vellum-fe/
├── config.toml # Global defaults
├── layout.toml # Global layout
├── characters/
│ └── CharName/
│ ├── config.toml # Character overrides
│ └── layout.toml # Character layout
Character-specific files override global settings.
Editing Configuration
You can edit files directly, or use the in-client menu:
- Press
F1to open the main menu - Navigate to Config submenu
- Select the file to edit
Changes to layout are saved automatically. Other config changes require restart.
Resetting to Defaults
Delete a configuration file to reset it to defaults on next launch:
rm ~/.vellum-fe/layout.toml
Or delete the entire directory for a full reset:
rm -rf ~/.vellum-fe
config.toml
General client settings including connection, UI behavior, and sound.
Connection
[connection]
host = "127.0.0.1"
port = 8001
character = "YourName"
# For direct connection (optional - can use CLI instead)
account = "your_account"
password = "your_password" # Stored in plain text!
game = "prime" # prime, platinum, shattered, test
Tip: For security, pass credentials via CLI:
--account X --password Y
User Interface
[ui]
buffer_size = 1000 # Lines kept per window
border_style = "single" # single, double, rounded, thick, none
color_mode = "direct" # direct (24-bit), indexed (256-color)
# Text selection
selection_enabled = true
selection_auto_copy = true # Copy on mouse-up
# Commands
command_echo = true # Show sent commands in main window
min_command_length = 3 # Min length to save in history
# Drag modifier for moving windows
drag_modifier_key = "ctrl" # ctrl, alt, or shift
Color Modes
| Mode | Description |
|---|---|
direct | 24-bit true color. Use with modern terminals (kitty, alacritty, Windows Terminal) |
indexed | 256-color with standard palette. Fallback for legacy terminals |
slot | 256-color with custom palette. For terminals supporting OSC4 |
Focus Navigation
Control which windows are focusable with Tab:
[ui.focus]
types = ["text", "tabbedtext"] # Widget types that can receive focus
exclude = ["bounty", "society"] # Specific windows to skip
order = [] # Custom focus order (empty = layout order)
Target List
Configure the targets widget display:
[target_list]
status_position = "end" # "end" or "start"
truncation_mode = "noun" # "full" or "noun"
excluded_nouns = ["arm", "coal"]
[target_list.status_abbrev]
stunned = "stu"
frozen = "frz"
dead = "ded"
Highlights
Global toggles for the highlight system:
[highlights]
sounds_enabled = true # Play sounds on match
replace_enabled = true # Apply text replacements
redirect_enabled = true # Route lines to other windows
coloring_enabled = true # Apply color highlighting
Sound
[sound]
enabled = true
volume = 0.7 # 0.0 to 1.0
cooldown_ms = 500 # Min time between sounds
startup_music = true
Text-to-Speech
[tts]
enabled = false
rate = 1.0 # 0.5 (slow) to 2.0 (fast)
volume = 1.0
speak_thoughts = true
speak_speech = true
speak_main = false # Usually too noisy
Stream Routing
Control how unsubscribed text streams are handled:
[streams]
# Streams to silently discard
drop_unsubscribed = [
"speech", "whisper", "talk",
"targetcount", "playercount"
]
fallback = "main" # Route unknown streams here
room_in_main = true # Show room text in main (DR only)
Logging
Capture raw XML for debugging:
[logging]
enabled = false
# dir = "logs"
# timestamps = true
Event Patterns
Regex patterns for countdown timers:
[event_patterns.stun_rounds]
pattern = '^\s*You are stunned for ([0-9]+) rounds?'
event_type = "stun"
action = "set"
duration_capture = 1
duration_multiplier = 5.0
enabled = true
layout.toml
Defines window positions, sizes, and properties.
Basic Structure
terminal_width = 120
terminal_height = 40
[[windows]]
name = "main"
widget_type = "text"
row = 0
col = 0
rows = 37
cols = 120
Window Properties
Required
| Property | Type | Description |
|---|---|---|
name | string | Unique identifier |
widget_type | string | Widget type (see Widgets) |
row | integer | Top row position (0 = top) |
col | integer | Left column position (0 = left) |
rows | integer | Height in rows |
cols | integer | Width in columns |
Optional
| Property | Type | Default | Description |
|---|---|---|---|
visible | bool | true | Show window |
show_border | bool | true | Draw border |
border_style | string | "single" | single, double, rounded, thick |
border_color | string | "#808080" | Border color |
border_sides | string | "all" | Which sides: all, none, top, bottom, left, right, or combinations |
title | string | - | Custom title |
show_title | bool | true | Show title in border |
buffer_size | integer | 1000 | Lines to keep (text windows) |
background_color | string | - | Background color |
text_color | string | - | Default text color |
transparent_background | bool | false | See-through background |
Size Constraints
[[windows]]
name = "compass"
widget_type = "compass"
min_rows = 3
max_rows = 5
min_cols = 7
max_cols = 15
Widget-Specific Properties
Text Windows
[[windows]]
name = "main"
widget_type = "text"
streams = ["main"] # Streams to display
buffer_size = 10000
compact = false # Remove blank lines
Tabbed Text
[[windows]]
name = "channels"
widget_type = "tabbedtext"
buffer_size = 5000
[[windows.tabs]]
name = "Speech"
streams = ["speech"]
show_timestamps = true
[[windows.tabs]]
name = "Thoughts"
streams = ["thoughts"]
Progress Bars
[[windows]]
name = "health"
widget_type = "progress"
stat = "health" # health, mana, stamina, spirit, encumbrance
bar_color = "#00FF00"
show_percentage = true
Countdowns
[[windows]]
name = "roundtime"
widget_type = "countdown"
id = "roundtime" # roundtime, casttime, stuntime
Room Window
[[windows]]
name = "room"
widget_type = "room"
show_desc = true
show_objs = true
show_players = true
show_exits = true
show_name = true
Example Layout
terminal_width = 160
terminal_height = 50
# Main game text - left side
[[windows]]
name = "main"
widget_type = "text"
streams = ["main"]
row = 0
col = 0
rows = 45
cols = 100
buffer_size = 10000
# Channels - right side
[[windows]]
name = "channels"
widget_type = "tabbedtext"
row = 0
col = 100
rows = 30
cols = 60
buffer_size = 2000
[[windows.tabs]]
name = "Speech"
streams = ["speech"]
[[windows.tabs]]
name = "Thoughts"
streams = ["thoughts"]
# Status bars
[[windows]]
name = "health"
widget_type = "progress"
stat = "health"
row = 30
col = 100
rows = 1
cols = 60
# Command input - bottom
[[windows]]
name = "command_input"
widget_type = "command_input"
row = 47
col = 0
rows = 3
cols = 160
Hidden Windows
Set visible = false to define windows that can be shown later via the menu:
[[windows]]
name = "society"
widget_type = "text"
streams = ["society"]
visible = false
# ... position and size still required
Show via: Menu → Windows → Add Window → Text Windows → Society
keybinds.toml
Keyboard shortcuts for client actions and game commands.
Basic Format
[keybinds]
"ctrl+s" = "save_layout"
"f1" = "menu"
"ctrl+c" = "copy"
"numpad1" = { command = "go southwest" }
Key Names
Modifiers
Combine with +: ctrl+shift+a, alt+f1
| Modifier | Name |
|---|---|
| Control | ctrl |
| Alt | alt |
| Shift | shift |
Special Keys
| Key | Name |
|---|---|
| Function keys | f1 through f12 |
| Arrow keys | up, down, left, right |
| Navigation | home, end, pageup, pagedown |
| Editing | insert, delete, backspace |
| Other | enter, tab, escape, space |
| Numpad | numpad0-numpad9, numpad_add, numpad_subtract, etc. |
Action Types
Client Actions
"f1" = "menu" # Open main menu
"ctrl+c" = "copy" # Copy selection
"pageup" = "scroll_up" # Scroll focused window
"pagedown" = "scroll_down"
"ctrl+home" = "scroll_top"
"ctrl+end" = "scroll_bottom"
"ctrl+s" = "save_layout"
"ctrl+tab" = "focus_next" # Cycle window focus
"escape" = "cancel" # Close menu/cancel
Game Commands
"numpad1" = { command = "go southwest" }
"numpad5" = { command = "look" }
"f2" = { command = "stance defensive" }
Macros (Multiple Commands)
"ctrl+h" = { macro = "hide\npause 2\nstalk" }
Common Keybinds
[keybinds]
# Navigation
"numpad1" = { command = "go southwest" }
"numpad2" = { command = "go south" }
"numpad3" = { command = "go southeast" }
"numpad4" = { command = "go west" }
"numpad5" = { command = "look" }
"numpad6" = { command = "go east" }
"numpad7" = { command = "go northwest" }
"numpad8" = { command = "go north" }
"numpad9" = { command = "go northeast" }
"numpad_add" = { command = "go out" }
"numpad_subtract" = { command = "go up" }
"numpad_multiply" = { command = "go down" }
# Client
"f1" = "menu"
"ctrl+c" = "copy"
"ctrl+s" = "save_layout"
"pageup" = "scroll_up"
"pagedown" = "scroll_down"
"escape" = "cancel"
# Search
"ctrl+f" = "search"
"ctrl+pageup" = "prev_search_match"
"ctrl+pagedown" = "next_search_match"
Available Actions
| Action | Description |
|---|---|
menu | Open main menu |
copy | Copy selected text |
scroll_up / scroll_down | Scroll focused window |
scroll_top / scroll_bottom | Jump to top/bottom |
focus_next / focus_prev | Cycle window focus |
save_layout | Save current layout |
cancel | Close menu or cancel operation |
search | Open search in focused window |
prev_search_match / next_search_match | Cycle search results |
highlights.toml
Text highlighting rules for coloring, sounds, and redirects.
Basic Format
[[highlights]]
name = "my_highlight"
pattern = "pattern to match"
foreground = "#FF0000"
Pattern Matching
Literal Match (Fast)
[[highlights]]
name = "death_cry"
pattern = "death cry" # Exact text match
foreground = "#FF0000"
Regex Match
[[highlights]]
name = "creature_attack"
pattern = "^A .+ (swings|claws|lunges)"
is_regex = true
foreground = "#FFA500"
Styling Options
[[highlights]]
name = "whisper"
pattern = "whispers,"
foreground = "#9370DB" # Text color
background = "#1a1a2e" # Background color
bold = true
italic = true
underline = true
Colors
Use hex colors (#RRGGBB) or named colors:
- Basic:
red,green,blue,yellow,cyan,magenta,white,black - Extended:
gray,orange,purple,pink,brown
Sound Alerts
[[highlights]]
name = "dead"
pattern = "appears dead"
foreground = "#00FF00"
sound = "ding.wav" # File in ~/.vellum-fe/sounds/
sound_volume = 0.8 # 0.0 to 1.0
Text Replacement
[[highlights]]
name = "shorten_deaths"
pattern = "The death cry of"
replace = "†"
foreground = "#FF0000"
Stream Redirect
Route matching lines to another window:
[[highlights]]
name = "loot_to_window"
pattern = "^You gather"
redirect = "loot" # Window name
Full Example
# Creature deaths
[[highlights]]
name = "creature_dead"
pattern = "appears dead"
foreground = "#00FF00"
bold = true
sound = "kill.wav"
# Player speech
[[highlights]]
name = "says"
pattern = ' (says|asks|exclaims),'
is_regex = true
foreground = "#87CEEB"
# Whispers (with background)
[[highlights]]
name = "whisper"
pattern = "whispers,"
foreground = "#DDA0DD"
background = "#2a1a2a"
italic = true
# Stun warning
[[highlights]]
name = "stunned"
pattern = "You are stunned"
foreground = "#FF4500"
bold = true
sound = "alert.wav"
# Treasure (redirect to loot window)
[[highlights]]
name = "loot"
pattern = "^(You gather|You search)"
is_regex = true
foreground = "#FFD700"
redirect = "loot"
Priority
Highlights are applied in order. Later patterns can override earlier ones.
Disabling
Disable without deleting via config.toml:
[highlights]
sounds_enabled = false # Disable all sounds
coloring_enabled = false # Disable all coloring
colors.toml
Custom color palette definitions.
Basic Format
[colors]
my_red = "#FF0000"
soft_blue = "#5588AA"
dark_bg = "#1a1a1a"
Using Custom Colors
Reference in other config files:
# In highlights.toml
[[highlights]]
name = "danger"
pattern = "attacks you"
foreground = "my_red" # Uses color from colors.toml
# In layout.toml
[[windows]]
name = "combat"
border_color = "soft_blue"
background_color = "dark_bg"
Preset Colors
VellumFE recognizes these named colors without definition:
| Name | Hex |
|---|---|
black | #000000 |
red | #FF0000 |
green | #00FF00 |
yellow | #FFFF00 |
blue | #0000FF |
magenta | #FF00FF |
cyan | #00FFFF |
white | #FFFFFF |
gray / grey | #808080 |
orange | #FFA500 |
purple | #800080 |
pink | #FFC0CB |
Example Palette
[colors]
# UI colors
border_normal = "#404040"
border_focused = "#5588AA"
border_alert = "#FF4040"
# Text colors
text_normal = "#CCCCCC"
text_dim = "#666666"
text_bright = "#FFFFFF"
# Creature states
dead = "#00FF00"
stunned = "#FFFF00"
frozen = "#00FFFF"
# Communication
speech = "#87CEEB"
whisper = "#DDA0DD"
thoughts = "#9370DB"
# Combat
damage_minor = "#FFFF00"
damage_major = "#FFA500"
damage_critical = "#FF0000"
Color Formats
All colors must be specified as hex:
# Supported formats
color1 = "#RGB" # 3-digit (expanded to 6)
color2 = "#RRGGBB" # 6-digit (most common)
# Not supported
color3 = "rgb(255, 0, 0)" # CSS format - won't work
color4 = "255, 0, 0" # Raw values - won't work
Widgets
Widgets are the visual building blocks of your layout. Each widget type displays specific game information.
Widget Types
| Type | Purpose |
|---|---|
| text | Scrollable game text |
| tabbedtext | Multiple streams in tabs |
| progress | Health, mana, stamina bars |
| countdown | Roundtime, cast time timers |
| compass | Available exits |
| hand | Items in hands |
| indicator | Status conditions |
| dashboard | Multi-indicator panel |
| room | Room name, description, exits |
| injury_doll | Body part injuries |
| active_effects | Buffs and debuffs |
| targets | Creatures in room |
| players | Players in room |
| items | Items on ground |
| inventory | Carried items |
| spells | Known spells |
| container | Container contents |
Common Properties
All widgets share these properties:
[[windows]]
name = "my_widget" # Unique identifier
widget_type = "text" # Widget type
row = 0 # Top position
col = 0 # Left position
rows = 10 # Height
cols = 40 # Width
visible = true # Show/hide
show_border = true
border_style = "single" # single, double, rounded, thick
border_color = "#808080"
title = "Custom Title"
Adding Widgets
- Via Menu: F1 → Windows → Add Window → [Category] → [Widget]
- Via Command:
.addwindow widgetname - Via Config: Edit layout.toml directly
Categories
Widgets are organized into categories in the Add Window menu:
| Category | Widgets |
|---|---|
| Text Windows | text, tabbedtext |
| Status | progress, countdown, hand, indicator, dashboard |
| Navigation | compass, room |
| Entity | targets, players, items |
| Lists | inventory, spells, container |
| Other | injury_doll, active_effects |
Text Windows
Scrollable text display for game output.
Basic Usage
[[windows]]
name = "main"
widget_type = "text"
streams = ["main"]
row = 0
col = 0
rows = 30
cols = 80
buffer_size = 10000
Properties
| Property | Type | Default | Description |
|---|---|---|---|
streams | array | [] | Stream IDs to display |
buffer_size | integer | 1000 | Lines to keep in memory |
compact | bool | false | Remove blank lines |
show_timestamps | bool | false | Prefix lines with time |
timestamp_position | string | "end" | "start" or "end" |
Common Streams
| Stream | Content |
|---|---|
main | Primary game output |
speech | Player dialogue |
thoughts | ESP/telepathy |
combat | Combat messages |
death | Death messages |
familiar | Familiar messages |
group | Group information |
logons | Login/logout |
society | Society messages |
bounty | Bounty information |
Examples
Main Window
[[windows]]
name = "main"
widget_type = "text"
streams = ["main"]
buffer_size = 10000
Speech Window
[[windows]]
name = "speech"
widget_type = "text"
streams = ["speech"]
buffer_size = 2000
show_timestamps = true
timestamp_position = "start"
Combat Log (Compact)
[[windows]]
name = "combat"
widget_type = "text"
streams = ["combat"]
buffer_size = 500
compact = true
Scrolling
Page Up/Page Down- Scroll when focused- Mouse wheel - Scroll under cursor
Home/End- Jump to top/bottom- Auto-scrolls when new text arrives (unless scrolled back)
Tabbed Text Windows
Multiple text streams organized into switchable tabs.
Basic Usage
[[windows]]
name = "channels"
widget_type = "tabbedtext"
row = 0
col = 80
rows = 20
cols = 40
buffer_size = 2000
[[windows.tabs]]
name = "Speech"
streams = ["speech"]
[[windows.tabs]]
name = "Thoughts"
streams = ["thoughts"]
[[windows.tabs]]
name = "Combat"
streams = ["combat"]
Properties
| Property | Type | Default | Description |
|---|---|---|---|
buffer_size | integer | 5000 | Lines per tab |
Tab Properties
| Property | Type | Default | Description |
|---|---|---|---|
name | string | required | Tab label |
streams | array | required | Stream IDs for this tab |
show_timestamps | bool | false | Show timestamps |
timestamp_position | string | "end" | "start" or "end" |
ignore_activity | bool | false | Don’t highlight on new content |
Tab Switching
- Click tab name to switch
- Activity indicator shows which tabs have new content
Example: Communication Hub
[[windows]]
name = "comms"
widget_type = "tabbedtext"
row = 0
col = 100
rows = 25
cols = 60
buffer_size = 3000
[[windows.tabs]]
name = "Speech"
streams = ["speech"]
show_timestamps = true
[[windows.tabs]]
name = "Thoughts"
streams = ["thoughts"]
show_timestamps = true
[[windows.tabs]]
name = "Whispers"
streams = ["whisper"]
show_timestamps = true
[[windows.tabs]]
name = "Group"
streams = ["group"]
ignore_activity = true
Example: Game Activity
[[windows]]
name = "activity"
widget_type = "tabbedtext"
buffer_size = 1000
[[windows.tabs]]
name = "Combat"
streams = ["combat"]
[[windows.tabs]]
name = "Deaths"
streams = ["death"]
[[windows.tabs]]
name = "Arrivals"
streams = ["logons"]
ignore_activity = true
Progress Bars
Display character vitals as visual bars.
Basic Usage
[[windows]]
name = "health"
widget_type = "progress"
stat = "health"
row = 0
col = 0
rows = 1
cols = 20
Properties
| Property | Type | Default | Description |
|---|---|---|---|
stat | string | required | Stat to display |
bar_color | string | auto | Bar fill color |
show_percentage | bool | true | Show % value |
show_label | bool | true | Show stat name |
Available Stats
| Stat | Description |
|---|---|
health | Hit points |
mana | Mana points |
stamina | Stamina points |
spirit | Spirit points |
encumbrance | Carry weight |
mind | Mental state (DR) |
concentration | Concentration (DR) |
Examples
Minimal Health Bar
[[windows]]
name = "health"
widget_type = "progress"
stat = "health"
rows = 1
cols = 15
show_label = false
Colored Mana Bar
[[windows]]
name = "mana"
widget_type = "progress"
stat = "mana"
bar_color = "#4169E1"
rows = 1
cols = 20
Stacked Vitals
[[windows]]
name = "health"
widget_type = "progress"
stat = "health"
row = 0
col = 0
rows = 1
cols = 25
bar_color = "#FF4040"
[[windows]]
name = "mana"
widget_type = "progress"
stat = "mana"
row = 1
col = 0
rows = 1
cols = 25
bar_color = "#4169E1"
[[windows]]
name = "stamina"
widget_type = "progress"
stat = "stamina"
row = 2
col = 0
rows = 1
cols = 25
bar_color = "#32CD32"
Color Behavior
Without bar_color, bars change color based on value:
- Green (high) → Yellow (medium) → Red (low)
Countdowns
Display roundtime, cast time, and stun timers.
Basic Usage
[[windows]]
name = "roundtime"
widget_type = "countdown"
id = "roundtime"
row = 0
col = 0
rows = 1
cols = 15
Properties
| Property | Type | Default | Description |
|---|---|---|---|
id | string | required | Timer type |
label | string | auto | Custom label |
bar_color | string | auto | Bar color |
Timer Types
| ID | Description |
|---|---|
roundtime | Action roundtime (RT) |
casttime | Spell cast time (CT) |
stuntime | Stun duration |
Examples
Roundtime Bar
[[windows]]
name = "rt"
widget_type = "countdown"
id = "roundtime"
rows = 1
cols = 20
bar_color = "#FFD700"
Cast Time
[[windows]]
name = "ct"
widget_type = "countdown"
id = "casttime"
rows = 1
cols = 15
bar_color = "#9370DB"
Stun Timer
[[windows]]
name = "stun"
widget_type = "countdown"
id = "stuntime"
rows = 1
cols = 15
bar_color = "#FF4500"
Display
- Shows remaining seconds with visual bar
- Bar depletes as time passes
- Empty/hidden when not active
Compass
Displays available room exits with directional arrows.
Basic Usage
[[windows]]
name = "compass"
widget_type = "compass"
row = 0
col = 0
rows = 3
cols = 7
Properties
| Property | Type | Default | Description |
|---|---|---|---|
style | string | "arrows" | Display style |
Size Requirements
- Minimum: 3 rows × 7 columns
- Recommended: 3×7 or 5×9
Display
N
W ◆ E
S
- Available exits shown with arrows
- Unavailable directions dimmed
- Supports all 10 directions: N, S, E, W, NE, NW, SE, SW, Up, Down, Out
Example
[[windows]]
name = "compass"
widget_type = "compass"
row = 0
col = 0
rows = 3
cols = 7
show_border = true
border_style = "rounded"
Hands
Display items held in left and right hands.
Basic Usage
[[windows]]
name = "right_hand"
widget_type = "hand"
hand = "right"
row = 0
col = 0
rows = 1
cols = 25
Properties
| Property | Type | Default | Description |
|---|---|---|---|
hand | string | required | "left" or "right" |
Examples
Right Hand
[[windows]]
name = "right"
widget_type = "hand"
hand = "right"
rows = 1
cols = 30
title = "R:"
Left Hand
[[windows]]
name = "left"
widget_type = "hand"
hand = "left"
rows = 1
cols = 30
title = "L:"
Side by Side
[[windows]]
name = "right_hand"
widget_type = "hand"
hand = "right"
row = 0
col = 0
rows = 1
cols = 25
show_border = false
title = "R:"
[[windows]]
name = "left_hand"
widget_type = "hand"
hand = "left"
row = 0
col = 25
rows = 1
cols = 25
show_border = false
title = "L:"
Interaction
- Click item name to interact
- Right-click for context menu
- Shows “Empty” when nothing held
Status Indicators
Display character status conditions (kneeling, hidden, webbed, etc).
Basic Usage
[[windows]]
name = "status"
widget_type = "indicator"
id = "kneeling"
row = 0
col = 0
rows = 1
cols = 3
Properties
| Property | Type | Default | Description |
|---|---|---|---|
id | string | required | Status to track |
active_color | string | auto | Color when active |
inactive_color | string | "gray" | Color when inactive |
Available Statuses
| ID | Description |
|---|---|
kneeling | Kneeling position |
sitting | Sitting position |
prone | Lying down |
stunned | Stunned |
webbed | Webbed |
hidden | Hidden |
invisible | Invisible |
dead | Dead |
bleeding | Bleeding |
poisoned | Poisoned |
diseased | Diseased |
Examples
Single Indicator
[[windows]]
name = "hidden_indicator"
widget_type = "indicator"
id = "hidden"
rows = 1
cols = 3
active_color = "#00FF00"
Status Row
[[windows]]
name = "kneel"
widget_type = "indicator"
id = "kneeling"
row = 0
col = 0
rows = 1
cols = 3
[[windows]]
name = "hide"
widget_type = "indicator"
id = "hidden"
row = 0
col = 3
rows = 1
cols = 3
[[windows]]
name = "stun"
widget_type = "indicator"
id = "stunned"
row = 0
col = 6
rows = 1
cols = 3
Display
- Shows abbreviated status code (3 chars)
- Active: colored, Inactive: dimmed
- Example:
KNE(kneeling),HID(hidden)
Dashboard
Configurable grid of status indicators in a single widget.
Basic Usage
[[windows]]
name = "dashboard"
widget_type = "dashboard"
row = 0
col = 0
rows = 2
cols = 12
Properties
| Property | Type | Default | Description |
|---|---|---|---|
indicators | array | all | Which indicators to show |
columns | integer | auto | Grid columns |
Display
Shows multiple status indicators in a compact grid:
┌──────────┐
│KNE SIT HID│
│STU WEB BLE│
└──────────┘
- Active indicators are highlighted
- Inactive indicators are dimmed
Custom Indicators
[[windows]]
name = "dashboard"
widget_type = "dashboard"
indicators = ["kneeling", "hidden", "stunned", "webbed"]
columns = 2
Available Indicators
kneeling,sitting,pronestunned,webbed,hiddeninvisible,deadbleeding,poisoned,diseased
Example: Combat Dashboard
[[windows]]
name = "combat_status"
widget_type = "dashboard"
row = 0
col = 0
rows = 2
cols = 15
indicators = ["stunned", "webbed", "prone", "bleeding"]
columns = 2
show_border = true
title = "Status"
Room Window
Displays current room information: name, description, objects, players, and exits.
Basic Usage
[[windows]]
name = "room"
widget_type = "room"
row = 0
col = 0
rows = 10
cols = 50
Properties
| Property | Type | Default | Description |
|---|---|---|---|
show_name | bool | true | Show room name |
show_desc | bool | true | Show description |
show_objs | bool | true | Show objects/creatures |
show_players | bool | true | Show other players |
show_exits | bool | true | Show obvious exits |
Examples
Full Room Display
[[windows]]
name = "room"
widget_type = "room"
rows = 12
cols = 60
show_name = true
show_desc = true
show_objs = true
show_players = true
show_exits = true
Compact (Name + Exits Only)
[[windows]]
name = "room"
widget_type = "room"
rows = 3
cols = 40
show_name = true
show_desc = false
show_objs = false
show_players = false
show_exits = true
Description Only
[[windows]]
name = "room"
widget_type = "room"
rows = 8
cols = 50
show_name = true
show_desc = true
show_objs = false
show_players = false
show_exits = false
Display
┌─ Town Square ─────────────────────────┐
│ The center of town bustles with │
│ activity. A large fountain dominates │
│ the square. │
│ │
│ You also see a town guard. │
│ Also here: Adventurer, Merchant │
│ Obvious exits: north, east, south │
└───────────────────────────────────────┘
Interaction
- Click creature/player names to interact
- Right-click for context menu
Injury Display
Shows body part injuries as a visual “paper doll”.
Basic Usage
[[windows]]
name = "injuries"
widget_type = "injury_doll"
row = 0
col = 0
rows = 10
cols = 15
Display
[Head]
[L.Arm][Chest][R.Arm]
[L.Leg][R.Leg]
- Each body part changes color based on injury severity
- Green (healthy) → Yellow (minor) → Orange (moderate) → Red (severe)
Size Requirements
- Minimum: 8 rows × 12 columns
- Recommended: 10×15
Example
[[windows]]
name = "injuries"
widget_type = "injury_doll"
row = 0
col = 0
rows = 10
cols = 15
show_border = true
border_style = "rounded"
title = "Injuries"
Body Parts Tracked
- Head, Neck
- Chest, Abdomen, Back
- Left/Right Arm
- Left/Right Hand
- Left/Right Leg
- Left/Right Eye
Active Effects
Displays active spells, buffs, debuffs, and cooldowns.
Basic Usage
[[windows]]
name = "effects"
widget_type = "active_effects"
row = 0
col = 0
rows = 10
cols = 30
Properties
| Property | Type | Default | Description |
|---|---|---|---|
category | string | "all" | Filter by type |
Categories
| Category | Content |
|---|---|
all | Everything |
spell | Active spells |
buff | Beneficial effects |
debuff | Harmful effects |
cooldown | Ability cooldowns |
Display
Shows effect name with remaining duration:
┌─ Active Effects ──────┐
│ Spirit Shield 12:34 │
│ Haste 3:45 │
│ Bless 8:20 │
└───────────────────────┘
Example
[[windows]]
name = "buffs"
widget_type = "active_effects"
category = "spell"
rows = 8
cols = 25
show_border = true
title = "Spells"
Targets
Lists creatures in the current room with status indicators.
Basic Usage
[[windows]]
name = "targets"
widget_type = "targets"
row = 0
col = 0
rows = 10
cols = 35
Display
┌─ Targets [03] ────────────┐
│ > a mud hog [stunned] │
│ a mud hog │
│ a large rat [dead] │
└───────────────────────────┘
>marks your current target- Status shown in brackets
- Count in title
Configuration
Configure via config.toml:
[target_list]
status_position = "end" # "end" or "start"
truncation_mode = "noun" # "full" or "noun"
excluded_nouns = ["arm", "coal"]
[target_list.status_abbrev]
stunned = "stu"
frozen = "frz"
dead = "ded"
Interaction
- Click creature to target
- Right-click for context menu
- Drag to inventory to loot
Example
[[windows]]
name = "targets"
widget_type = "targets"
row = 0
col = 100
rows = 12
cols = 30
show_border = true
border_color = "#AA4444"
title = "Enemies"
Players
Lists other players in the current room.
Basic Usage
[[windows]]
name = "players"
widget_type = "players"
row = 0
col = 0
rows = 8
cols = 25
Display
┌─ Players [02] ──────┐
│ Adventurer │
│ Merchant (sitting) │
└─────────────────────┘
- Shows player names
- Status in parentheses (sitting, kneeling, etc.)
- Count in title
Interaction
- Click player name to interact
- Right-click for context menu
Example
[[windows]]
name = "players"
widget_type = "players"
row = 0
col = 100
rows = 8
cols = 25
show_border = true
title = "Also Here"
Items
Lists non-creature objects on the ground (dropped items, loot, furniture).
Basic Usage
[[windows]]
name = "items"
widget_type = "items"
row = 0
col = 0
rows = 10
cols = 30
Display
┌─ Items [04] ──────────────┐
│ a silver ring │
│ some gold coins │
│ a wooden chest │
│ a torn scroll │
└───────────────────────────┘
- Shows item names from room
- Count in title
- Updates when room changes or items are dropped/picked up
Interaction
- Click item to interact (look, get)
- Right-click for context menu
- Drag to inventory to pick up
Example
[[windows]]
name = "loot"
widget_type = "items"
row = 20
col = 100
rows = 8
cols = 30
show_border = true
title = "Ground"
Note
Items widget shows objects from the room description that are NOT creatures. Creatures appear in the Targets widget instead.
Inventory
Displays items carried on your character.
Basic Usage
[[windows]]
name = "inventory"
widget_type = "inventory"
row = 0
col = 0
rows = 15
cols = 35
Display
Shows items from the inv stream:
┌─ Inventory ────────────────┐
│ a leather backpack │
│ a silver ring │
│ some gold coins │
│ a steel sword │
└────────────────────────────┘
Interaction
- Click item to interact
- Right-click for context menu
- Drag items to rearrange or drop
Example
[[windows]]
name = "inventory"
widget_type = "inventory"
row = 0
col = 100
rows = 20
cols = 40
show_border = true
title = "Carried Items"
Updating
Inventory updates when you:
- Type
inventorycommand - Pick up or drop items
- Open/close containers
Spells
Displays known spells from the spell list.
Basic Usage
[[windows]]
name = "spells"
widget_type = "spells"
row = 0
col = 0
rows = 20
cols = 35
Display
Shows spells from the Spells stream:
┌─ Spells ───────────────────┐
│ Spirit Warding I (101) │
│ Spirit Barrier (102) │
│ Spirit Defense (103) │
└────────────────────────────┘
Interaction
- Click spell to prepare/cast
- Right-click for context menu
Example
[[windows]]
name = "spells"
widget_type = "spells"
row = 0
col = 120
rows = 25
cols = 35
show_border = true
title = "Known Spells"
Note
Spell list is populated at login. Use spell command in-game to refresh.
Containers
Displays contents of open containers (bags, backpacks, chests).
Basic Usage
Container windows are created dynamically when you look in a container.
Enabling Containers
Enable container windows via command:
.containers
Or via menu: F1 → Config → Toggle Containers
Behavior
When enabled:
- Look in a container (
look in backpack) - A window appears showing contents
- Window closes when you close/leave the container
Display
┌─ leather backpack ─────────┐
│ a silver ring │
│ some gold coins │
│ a healing herb │
└────────────────────────────┘
Interaction
- Click items to interact
- Right-click for context menu
- Drag items to inventory or other containers
Manual Container Window
Create a persistent container window:
[[windows]]
name = "my_bag"
widget_type = "container"
container_title = "backpack"
row = 0
col = 100
rows = 10
cols = 30
The container_title must match the container name in-game.
Customization
Create your perfect interface with custom layouts, highlights, keybinds, and sounds.
Topics
- Creating Layouts - Design custom window arrangements
- Highlight Patterns - Color and style game text
- Keybind Actions - Custom keyboard shortcuts
- Sound Alerts - Audio notifications for game events
Quick Start
Custom Layout
- Press F1 → Windows → Add Window
- Position and resize windows
- Press Ctrl+S to save
Add Highlights
Edit ~/.vellum-fe/highlights.toml:
[[highlights]]
name = "death"
pattern = "appears dead"
foreground = "#00FF00"
bold = true
sound = "kill.wav"
Custom Keybinds
Edit ~/.vellum-fe/keybinds.toml:
[keybinds]
"f2" = { command = "stance offensive" }
"f3" = { command = "stance defensive" }
Sound Alerts
- Place
.wavfiles in~/.vellum-fe/sounds/ - Reference in highlights:
[[highlights]]
name = "whisper"
pattern = "whispers to you"
sound = "whisper.wav"
Creating Layouts
Design custom window arrangements for different playstyles.
Using the Window Editor
- Press F1 → Windows → Edit Window → [window name]
- Modify position, size, and properties
- Save changes (applied immediately)
Or via command: .edit windowname
Adding Windows
Via Menu
F1 → Windows → Add Window → [Category] → [Widget]
Via Command
.addwindow targets
.addwindow text mywindow
Via Config
Edit ~/.vellum-fe/layout.toml:
[[windows]]
name = "mywindow"
widget_type = "text"
streams = ["main"]
row = 0
col = 0
rows = 20
cols = 60
Positioning
Grid Coordinates
row = 0 # Top edge (0 = top)
col = 0 # Left edge (0 = left)
rows = 20 # Height
cols = 60 # Width
Overlapping
Windows can overlap. Later windows in the file render on top.
Saving
- Ctrl+S - Save current layout
- F1 → Config → Save Layout - Same thing
- Changes to window positions via drag are saved automatically
Example Layouts
Hunting Layout
terminal_width = 160
terminal_height = 50
# Main game text
[[windows]]
name = "main"
widget_type = "text"
streams = ["main"]
row = 0
col = 0
rows = 40
cols = 100
# Targets on right
[[windows]]
name = "targets"
widget_type = "targets"
row = 0
col = 100
rows = 15
cols = 30
# Items below targets
[[windows]]
name = "items"
widget_type = "items"
row = 15
col = 100
rows = 10
cols = 30
# Vitals
[[windows]]
name = "health"
widget_type = "progress"
stat = "health"
row = 25
col = 100
rows = 1
cols = 30
# Roundtime
[[windows]]
name = "rt"
widget_type = "countdown"
id = "roundtime"
row = 26
col = 100
rows = 1
cols = 30
# Command input
[[windows]]
name = "command_input"
widget_type = "command_input"
row = 47
col = 0
rows = 3
cols = 160
Minimal Layout
terminal_width = 80
terminal_height = 24
[[windows]]
name = "main"
widget_type = "text"
streams = ["main"]
row = 0
col = 0
rows = 21
cols = 80
[[windows]]
name = "command_input"
widget_type = "command_input"
row = 21
col = 0
rows = 3
cols = 80
Per-Character Layouts
Save layouts per character:
~/.vellum-fe/characters/CharName/layout.toml
Use --character NAME to load character-specific layout.
Highlight Patterns
Color and style game text based on patterns.
Basic Highlight
[[highlights]]
name = "player_speech"
pattern = " says,"
foreground = "#87CEEB"
Pattern Types
Literal (Default)
Fast exact matching:
pattern = "appears dead"
Regex
Flexible pattern matching:
pattern = "^A .+ attacks"
is_regex = true
Styling Options
[[highlights]]
name = "important"
pattern = "IMPORTANT"
foreground = "#FF0000" # Text color
background = "#330000" # Background color
bold = true
italic = true
underline = true
Sound Alerts
[[highlights]]
name = "whisper_alert"
pattern = "whispers to you"
foreground = "#DDA0DD"
sound = "whisper.wav" # In ~/.vellum-fe/sounds/
sound_volume = 0.8 # 0.0 to 1.0
Text Replacement
[[highlights]]
name = "shorten"
pattern = "The death cry of"
replace = "†"
foreground = "#FF0000"
Stream Redirect
Route lines to another window:
[[highlights]]
name = "loot_redirect"
pattern = "^You gather"
is_regex = true
redirect = "loot" # Window name
Common Patterns
# Combat
[[highlights]]
name = "creature_dead"
pattern = "appears dead"
foreground = "#00FF00"
bold = true
sound = "kill.wav"
[[highlights]]
name = "you_hit"
pattern = "^You .+ (swing|slash|thrust)"
is_regex = true
foreground = "#FFFF00"
[[highlights]]
name = "you_miss"
pattern = "^A clean miss"
foreground = "#808080"
# Communication
[[highlights]]
name = "says"
pattern = " says,"
foreground = "#87CEEB"
[[highlights]]
name = "whisper"
pattern = "whispers,"
foreground = "#DDA0DD"
italic = true
[[highlights]]
name = "thoughts"
pattern = "^You hear .+ thinking,"
is_regex = true
foreground = "#9370DB"
# Warnings
[[highlights]]
name = "stunned"
pattern = "You are stunned"
foreground = "#FF4500"
bold = true
sound = "alert.wav"
[[highlights]]
name = "bleeding"
pattern = "Blood runs down"
foreground = "#FF0000"
sound = "danger.wav"
Disabling Highlights
In config.toml:
[highlights]
sounds_enabled = false # Disable sounds
coloring_enabled = false # Disable colors
replace_enabled = false # Disable replacements
Keybind Actions
Customize keyboard shortcuts for commands and actions.
Basic Keybind
[keybinds]
"f2" = { command = "stance offensive" }
Key Format
modifier+key
Modifiers
ctrl- Control keyalt- Alt keyshift- Shift key
Combine: ctrl+shift+a
Key Names
| Keys | Names |
|---|---|
| Letters | a through z |
| Numbers | 0 through 9 |
| Function | f1 through f12 |
| Arrows | up, down, left, right |
| Navigation | home, end, pageup, pagedown |
| Numpad | numpad0-numpad9, numpad_add, etc. |
| Other | enter, tab, escape, space, backspace |
Action Types
Game Commands
"f2" = { command = "stance offensive" }
"numpad5" = { command = "look" }
Macros (Multiple Commands)
"ctrl+h" = { macro = "hide\npause 2\nstalk" }
Client Actions
"f1" = "menu"
"ctrl+c" = "copy"
"pageup" = "scroll_up"
Available Actions
| Action | Description |
|---|---|
menu | Open main menu |
copy | Copy selection |
scroll_up | Scroll focused window up |
scroll_down | Scroll focused window down |
scroll_top | Jump to top |
scroll_bottom | Jump to bottom |
focus_next | Focus next window |
focus_prev | Focus previous window |
save_layout | Save current layout |
cancel | Close menu/cancel |
search | Search in window |
Example Configuration
[keybinds]
# Navigation (numpad)
"numpad1" = { command = "go sw" }
"numpad2" = { command = "go s" }
"numpad3" = { command = "go se" }
"numpad4" = { command = "go w" }
"numpad5" = { command = "look" }
"numpad6" = { command = "go e" }
"numpad7" = { command = "go nw" }
"numpad8" = { command = "go n" }
"numpad9" = { command = "go ne" }
"numpad_add" = { command = "go out" }
"numpad_subtract" = { command = "go up" }
"numpad_multiply" = { command = "go down" }
# Combat stances
"f2" = { command = "stance offensive" }
"f3" = { command = "stance defensive" }
"f4" = { command = "stance guarded" }
# Quick actions
"f5" = { command = "look in my backpack" }
"f6" = { command = "inventory" }
# Macros
"ctrl+h" = { macro = "hide\npause 2\nstalk" }
"ctrl+l" = { macro = "search\npause 1\nloot" }
# Client
"f1" = "menu"
"ctrl+s" = "save_layout"
"ctrl+c" = "copy"
"escape" = "cancel"
Sound Alerts
Audio notifications for game events.
Setup
- Create sounds directory:
~/.vellum-fe/sounds/ - Add
.wavfiles - Reference in highlights
Using Sounds
In highlights.toml:
[[highlights]]
name = "death_alert"
pattern = "appears dead"
foreground = "#00FF00"
sound = "kill.wav"
sound_volume = 0.8
Sound Properties
| Property | Type | Default | Description |
|---|---|---|---|
sound | string | - | Filename in sounds directory |
sound_volume | float | 1.0 | Volume (0.0 to 1.0) |
Global Settings
In config.toml:
[sound]
enabled = true
volume = 0.7 # Master volume
cooldown_ms = 500 # Min time between sounds
startup_music = true # Play music on launch
Disabling Sounds
All Sounds
[sound]
enabled = false
Highlight Sounds Only
[highlights]
sounds_enabled = false
Example Sounds Setup
Directory structure:
~/.vellum-fe/sounds/
├── kill.wav
├── alert.wav
├── whisper.wav
├── danger.wav
└── loot.wav
Highlights:
[[highlights]]
name = "kill"
pattern = "appears dead"
sound = "kill.wav"
[[highlights]]
name = "stunned"
pattern = "You are stunned"
sound = "alert.wav"
sound_volume = 1.0
[[highlights]]
name = "whisper"
pattern = "whispers to you"
sound = "whisper.wav"
sound_volume = 0.5
[[highlights]]
name = "bleeding"
pattern = "Blood runs down"
sound = "danger.wav"
Supported Formats
- WAV (recommended)
- MP3
- OGG
- FLAC
Troubleshooting
No sound playing?
- Check
[sound] enabled = truein config.toml - Check
[highlights] sounds_enabled = true - Verify file exists in sounds directory
- Check file format is supported
- Try increasing volume