Use Open character in the shared header to inspect a character from any view. Inside a profile, Character to inspect switches characters while keeping the current section and skill filters. Compare with shows aligned Overview, Stats, Skills or History values for two explicit character/realm identities. Stats comparison offers base, normal and enhanced values with bonuses; unknown values remain distinct from zero. Select No comparison for the full profile, including live status, effects, training and other detailed observations.
Views and profile/comparison links now survive refresh and browser Back/Forward. View filters are remembered within the browser tab. Progress drilldowns retain the selected period, including custom dates. The roster keeps exact weekly/stored balances visible and puts the complete cycle/resource summary in an expandable section. All five navigation destinations remain visible on phones.
See the UX audit, redesign proposal and
validation results and screenshots. New isolated checks:
.venv/bin/python examples/ux_browser_check.py and
.venv/bin/python examples/ux_resilience_check.py (Playwright Chromium required).
Restart the Gempy web process for the new asset routes, then reload the browser.
Live shows two character cards per row on wide desktops and one per row on smaller screens. Each card has Character and Vitals columns, which stack on phones. Open client and Disconnect icons sit beside the name and realm; clicking the level opens the profile. The desktop sidebar can collapse to an icon strip using its top arrow; the browser remembers your choice. Current location and Lich room ID appear below the character name, above their level. Weekly and Stored resource counts appear beneath each character's status, and XP bonuses sit beneath Vitals in both layouts. Fresh critical health/spirit states stand out; reporting timestamps stay in tooltips, and experience metrics are available in the character profile. Refresh the browser to load these UI changes.
Rotation is a weekly hunting view for configured main characters and enchanting wizards. Wizard completion requires current-cycle Lumnis spent and weekly essence earnings at the reported cap (or the configured weekly target). Exact earned and stored balances, Pacific AM/PM renewal dates, upcoming deadlines and account occupancy are visible. Filter by account or completion, or group by account. Main character Lumnis summaries are separate; their section folds away on phones.
Configure membership and account roles in weekly_rotation (see config-sample.yaml).
The view uses stored game observations and never imports old note balances as live
progress. Missing reports and passed renewals require an update. For cycle attribution,
it conservatively checks observations against the calendar week preceding the reported
next renewal in Eastern time, with a minute of rounding tolerance. Offline completion
remains visible only while its observations belong to that cycle. A new launch is
disabled in this view when another character on that account is already running.
Character names in Characters now open a persistent profile, including while offline. Profiles use four tabs: Overview, Stats, Skills, and History. Overview keeps exact weekly and stored resource balances alongside Lumnis and donations; live status and experience/training remain available in expandable sections. Stats separates base, normal and enhanced values and bonuses. Prime and Test retain separate profiles. Unreported fields show a dash; each profile section includes its observation time. Profile data is included in the existing SQLite backup.
Live and roster summaries show exact profession resource numbers, for example
Essence · Weekly: 32,450 · Total: 118,750. The detailed profile separates
Earned this cycle (weekly) from Total stored, and shows caps read from the
game's RESOURCE response. Weekly earnings are not the spendable balance.
Temple donations prepaid for future cycles appear separately from the observed
Lumnis phase. Passing a reported refresh time does not automatically reset counters
or mark a new cycle active; Gempy waits for a game observation.
Live cards use the installed Saga client's Lumnis and Tutelage artwork. Lumnis
shows its multiplier over the colored icon while active; expired bonuses use
grayscale artwork. Tutelage is colored when eligible and has a steady gold glow
while active. Hover or focus either icon for status, prepaid cycles, and remaining
Tutelage days; clicking opens the character profile. A countdown in whole days and
hours appears beside the icons. Asset provenance is recorded in static/images/saga/SOURCE.txt.
Install the updated scripts/gempy_reporter.lic in Lich's scripts/custom/
(or download it from Settings) and restart the reporter on each running character
with ;kill gempy_reporter then ;gempy_reporter. Existing character-specific
URL/token settings are retained. The reporter quietly requests INFO FULL,
SKILL, LUMNIS INFO, RESOURCE and EXPERIENCE in a bounded startup sequence,
then rotates them at its configured command interval. It also observes manually
requested reports. Stats and skills refresh less often than vitals. Old reporters
remain compatible but cannot populate the new stats and skills sections.
After installing backend changes, restart the Gempy web process and reload the browser. Restarting Gempy leaves game and frontend sessions connected.
Additional checks: ruby test_reporter_profiles.rb and
.venv/bin/python examples/profile_browser_check.py (requires Playwright Chromium).
The web workspace has Live, Progress, Characters, and Settings views. Live combines session/client controls with reported character vitals, location, injuries, effects and experience. Progress retains XP history for offline characters, with today/week/month/year totals and custom date ranges. Settings manages reporter tokens, Saga history imports, SQLite backups, timezone/day rollover and display defaults. See MIGRATION.md for reporter installation, pilot and KoboldMonitor cutover.
Use Add a character to enter a character name already saved in Lich and choose
an existing account label or create a new one. Account labels organize the roster;
Lich uses its saved login for authentication. Additions are saved to config.yaml
and are available immediately, including after restarting Gempy. Edit moves or
corrects a roster entry; Rename changes an account label. These labels organize
the roster, while Lich continues to own saved game credentials.
The terminal launcher remains available with ./run.sh. For a Linux web daemon,
configure your existing Lich saved logins and set paths.vellum_bin to the
installed Vellum executable. The web interface has its own client selector. No desktop environment is required.
Set the single Gempy administrator password interactively, then start the server:
./run.sh --set-password
./run.sh --webOpen http://127.0.0.1:8080 and sign in. Gempy stores a salted password hash
in private application state under ${XDG_STATE_HOME:-$HOME/.local/state}/gempy;
it does not store the password itself. Login sessions expire, login attempts are
throttled, and state-changing requests require a CSRF token. Use Log out on
shared browsers. This login is separate from your Lich saved game logins. After
changing the password with --set-password, restart the daemon to apply it and
revoke existing Gempy login sessions.
The Characters tab lists configured accounts and lets you choose Prime or Test before launching. A launch reuses a matching running Lich session. The Live view also discovers local sessions started outside Gempy and shows Attached, Headless, or Unknown client status. Open/Attach client opens Despana in a new tab; allow pop-ups for Gempy if your browser blocks it. Status refreshes every three seconds by default, configurable in Settings. Attachment is checked passively and is not a measure of open browser tabs.
Disconnect asks for confirmation and requests an orderly Lich exit. Allow up to 70 seconds for cleanup. If orderly exit fails, a separately confirmed Force Disconnect can terminate the revalidated process. Successful disconnect also removes managed frontend processes. Closing a browser tab, logging out of Gempy, or stopping/restarting the daemon leaves game and Vellum sessions running; the next daemon start rediscovers them.
For LAN or Tailscale access, bind Gempy to all interfaces:
./run.sh --web --host 0.0.0.0 --port 8080Visit http://<server-LAN-or-Tailscale-hostname>:8080. Despana links use the
hostname you used to access Gempy and Vellum's actual web port. Gempy and Vellum
use separate ports: both must be reachable from your browser, including through
any host firewall. Vellum keeps its pairing authentication; treat pairing URLs
as secrets. Gempy returns them only after login and excludes them from logs.
This mode is intended for a trusted LAN or Tailscale network with one administrator, not deployment directly on the public internet. Plain HTTP does not encrypt LAN traffic. Use Tailscale for access over untrusted networks. Run one daemon worker so operation locks and port allocation remain coordinated.
Use examples/gempy.service to run the dashboard as a
systemd user service. Replace both checkout paths before installation. The unit
runs run.sh, which selects the project Python environment and the local
Ruby 4.0.3 runtime. Set the password only for a new installation; when migrating
an existing dashboard, keep its configuration, credentials, and state directory.
mkdir -p ~/.config/systemd/user
cp examples/gempy.service ~/.config/systemd/user/gempy.service
# Edit ~/.config/systemd/user/gempy.service before starting it.
systemctl --user daemon-reload
systemctl --user enable gempy.service
loginctl enable-linger "$USER"
# Stop only the old standalone dashboard PID before starting the service.
systemctl --user start gempy.serviceLingering keeps the user manager running after logout and starts it when WSL
boots. If enabling lingering requires administrator privileges, run
sudo loginctl enable-linger "$USER". WSL must have systemd enabled in
/etc/wsl.conf. The service runs independently of the launching terminal while
the WSL distribution is running.
The unit uses Restart=on-failure, a five-second restart delay, and
KillMode=process. Preserve KillMode=process: stopping or restarting the
dashboard must leave Lich and Vellum processes running. Do not use a broad
process-kill command when replacing a standalone dashboard. If it used
GEMPY_STATE_DIR or XDG_STATE_HOME, configure the same state location in the
unit before starting it.
For the /home/nick/gs4/gempy WSL installation, the installed unit is
/home/nick/.config/systemd/user/gempy.service, with the existing bind address
0.0.0.0:8080 and state at /home/nick/.local/state/gempy. Its environment
includes DISPLAY=:0, the WSLg Wayland and PulseAudio sockets, and
WSL_INTEROP=/run/WSL/1_interop, verified from a systemd user unit. This avoids
depending on the original terminal's interop socket. Recheck these WSL-specific
paths if moving the unit to another distribution.
To reproduce this installation, use these values in the unit's [Service]
section in addition to the settings in the example:
WorkingDirectory=/home/nick/gs4/gempy
ExecStart=/home/nick/gs4/gempy/run.sh --web --host 0.0.0.0 --port 8080
Environment=GEMPY_STATE_DIR=/home/nick/.local/state/gempy
Environment=DISPLAY=:0
Environment=WAYLAND_DISPLAY=/mnt/wslg/runtime-dir/wayland-0
Environment=PULSE_SERVER=unix:/mnt/wslg/PulseServer
Environment=WSL_INTEROP=/run/WSL/1_interop
Environment=WSL_DISTRO_NAME=Ubuntu-26.04Replace the example's WorkingDirectory and ExecStart lines with these
values, then add the environment entries. After editing an installed unit, run
systemctl --user daemon-reload before restarting it.
Verified on 2026-10-18: the service was enabled and active, Linger=yes, and
the dashboard returned HTTP 200 on port 8080. A dashboard-only service restart
preserved all four running Lich processes, their listening sockets, and all
22 Vellum processes, including clients launched by the service. Ruby 4.0.3,
the SQLite/GTK/OpenSSL gems, Python dependencies, and Windows interoperability
were checked in the service environment. The transition preserved configuration
and credential file hashes and retained the existing telemetry database.
Manage the installed service with:
systemctl --user status gempy.service
journalctl --user -u gempy.service -f
systemctl --user restart gempy.service
systemctl --user stop gempy.service
loginctl show-user nick -p LingerAn explicit stop stays stopped despite Restart=on-failure. Use
systemctl --user disable --now gempy.service to stop it and disable automatic
startup. Gempy itself does not install or enable a service.
Choose Client above the roster; the choice applies to launches and existing
session attachments. Vellum Despana remains the default. Vellum Web / mobile
opens the /play layout using the same authenticated Vellum engine, so switching
browser layouts does not create another game login.
Vellum desktop and Vellum terminal open on the computer running Gempy.
The desktop needs a graphical display. The terminal choice opens a terminal
emulator; configure clients.terminal_command as an argument list if needed
(for example ['xterm', '-e']). A browser on another device does not cause
these windows to open on that device. Connection details provides desktop,
terminal, and SSH tunnel commands for connecting from another computer without
exposing Lich's unauthenticated listener to the network. Replace USER@SERVER
in the tunnel command with your SSH login. Vellum mobile apps can also pair
with the existing web session; use Vellum's pairing workflow.
Saga (experimental) opens a new window in the installed Saga, including when
other Saga windows are already running. Set paths.saga_bin to its executable
or Linux AppImage. On Windows/WSL, Gempy also discovers
C:\Program Files\Saga\Saga.exe.
Gempy displays the selected character, realm, host, and port. In the new Saga window, select Via Lich, expand Advanced: attach to a running Lich, choose GemStone IV, enter the displayed host and port, and select Attach to Lich. No account sign-in is needed: the port selects the existing character session, including its Prime or Test realm. Each Saga launch uses this step; existing windows stay open. The terminal launcher also displays these details and waits for Enter before returning to its roster.
Saga 0.10.4 forwards new-window requests to a shared process but does not forward the external Lich host and port. Gempy uses Saga's per-window attach form to avoid connecting a new window to the first character's port. A launch is shown as awaiting manual attachment, rather than reported as connected.
Gempy clears inherited automatic-login targets and passes the normal-window
environment to Windows through WSLENV.
Windows Saga must be able to reach WSL at 127.0.0.1; the tested installation
uses the existing WSL localhost networking. On older Lich versions accepting a
single client, close the attached frontend before opening another one.
Native client windows remain under your control. Closing a native client leaves Lich running; Disconnect ends the game session. Gempy does not force-close Windows Saga or a terminal emulator. A missing display/client or startup timeout returns an error; if a window opened despite a timeout, check it before retrying.
The terminal launcher can select frontend: vellum_gui, vellum_tui,
vellum_web, or saga in config.yaml. Vellum TUI uses the current terminal.
Restart Gempy after changing its configuration or installing these changes.
Run ./run.sh from this directory. The ignored config.yaml selects
frontend: vellum_despana, the shared /home/nick/gs4/Lich5/lich.rbw,
and /home/nick/gs4/vellum-fe. Python requirements are installed in .venv.
Prime is the default; press t to switch to Test, then Enter to launch.
The menu stays available for additional characters while Vellum runs in the
background. Startup failures are recorded in gempy.log; frontend output
containing authenticated browser URLs is never copied into that log.
Each character has gempy-<Character>-prime and gempy-<Character>-test
profiles in ~/.vellum-fe/launcher.toml. They use Lich mode,
web_client = "despana", web_port = 0 for automatic allocation, and
all-interface web binding (0.0.0.0) for LAN access. Gempy allocates an available loopback web port and passes
it explicitly to Vellum, so installed builds that open port-zero browser
URLs still open the correct session. Existing per-character Vellum settings
are reused.
Vellum opens the authenticated browser URL itself. Gempy starts Lich,
waits passively for its detachable listener, and supplies the actual port
when launching the matching saved profile. Existing Lich sessions are reused
only when their character and realm match.
The shared configurations were backed up beside the originals as
entry.yaml.gempy-20260930-backup and
launcher.toml.gempy-20260930-backup. Saved passwords remain in Lich.
Ruby runtime: Ruby 4.0.3 is installed at ~/.local/ruby-4.0.3 with
Lich's runtime gems, GTK, and curses. User executables in ~/.local/bin
select this version. ./run.sh also selects this runtime when present;
the system Ruby remains available as /usr/bin/ruby.
For existing Profanity configurations, omit frontend or set it to
profanity and retain paths.profanity_bin and any profanity_template.
Install test dependencies with .venv/bin/python -m pip install -r requirements-dev.txt,
then run launcher, service, and web checks with .venv/bin/python -m unittest -q.
This script provides a terminal-based interface for launching characters in GemstonIV using Lich and the Profanity Front End. It allows you to select characters from your accounts and handles the login process then launches Profanity. It also displays the online status of characters currently logged in on the same computer.
Before you begin, ensure you have the following installed on your system:
- Python 3.10 or higher
- Ruby interpreter
- Lich 5 (Lich5) installed and configured
- Profanity Frontend for the terminal default, or Vellum for Despana/web clients
- Git (optional, for cloning the repository)
Ensure that the ruby command is available in your system's PATH.
Clone the repository or download the script files into a directory of your choice:
git clone https://github.com/ndoucette/gempy.git
cd gempyThe script uses a YAML configuration file named config.yaml. You'll need to create and customize this file based on your setup.
-
Create the
config.yamlFile:You can create the file manually or copy the sample provided:
cp config-sample.yaml config.yaml
-
Edit the
config.yamlFile:Open
config.yamlin your preferred text editor and configure the following sections:- Paths to Lich and Profanity
- Accounts and Characters
Example
config.yaml:# config.yaml # Paths to the Lich and Profanity binaries paths: lich_bin: '/path/to/your/lich.rbw' profanity_bin: '/path/to/your/profanity.rb' # Character accounts and their characters accounts: AccountName1: - CharacterName1 - CharacterName2 AccountName2: - CharacterName3 - CharacterName4
Install the required Python packages using pip and the provided requirements.txt file:
pip install -r requirements.txtIf you're using Python 3 and pip refers to Python 2, use:
pip3 install -r requirements.txtDependencies:
- PyYAML: For parsing the YAML configuration file.
- FastAPI and Uvicorn: For the web daemon and authenticated APIs.
- websocket-client: For authenticated local Vellum connections.
In the config.yaml file, specify the full paths to your lich.rbw and profanity.rb binaries:
paths:
lich_bin: '/full/path/to/your/lich.rbw'
profanity_bin: '/full/path/to/your/profanity.rb'Notes:
- Ensure that the paths are absolute (full paths), not relative.
- Verify that the files exist at the specified locations.
- The paths should point to the executable Ruby scripts (
.rbwand.rbfiles).
Define your accounts and associated character names under the accounts section:
accounts:
AccountName1:
- CharacterName1
- CharacterName2
AccountName2:
- CharacterName3
- CharacterName4Important:
- Character names are case-sensitive. Ensure they match exactly as required for login.
- You can add as many accounts and characters as you need.
- Account names are used as headers in the terminal interface.
To launch the script, navigate to the directory containing launcher.py and run:
./launcher.pyIf the script is not executable, you can make it executable:
chmod +x launcher.pyAlternatively, run the script using Python:
python launcher.pyOnce the script is running, you'll see a terminal-based interface displaying your accounts and characters.
| Key | Action |
|---|---|
| Arrow keys | Move between accounts and characters |
Enter |
Log the selected character in |
t |
Toggle between the prime and test servers |
r |
Refresh online status |
Esc |
Quit |
The right-hand side of the bottom status bar always shows which server you're
about to log into — green for prime, magenta for test. Press t to toggle; the
[Online] markers refresh to show who is logged in on that server, since a character can
be on prime and test at the same time and each gets its own Profanity port.
Test logins pass --gemstone --test to Lich, which resolves to game code GST.
Lich falls back to your existing prime (GS3) saved entry for that character, so
you do not need to add separate saved logins for the test server.
To start the launcher on the test server by default, set default_realm: test in
config.yaml.
- Terminal Size: Ensure your terminal window is large enough to display the interface. If it's too small, you'll be prompted to resize.
- Case Sensitivity: Character names in the configuration file are case-sensitive. Enter them exactly as required.
- Dependencies: All required dependencies must be installed. Use the provided
requirements.txtfile. - Environment Variables:
- The script sets
TERMtoscreen-256color. - If
DISPLAYis not set, it defaults to:0.
- The script sets
- "Unsupported Operating System" Error:
- Ensure you're running the script on a supported system (Linux, macOS, or WSL).
- "Configuration File Not Found" Error:
- Verify that
config.yamlexists in the same directory aslauncher.py.
- Verify that
- "LICH_BIN path does not exist" Error:
- Check that the path to
lich.rbwis correct and the file exists.
- Check that the path to
- "PROFANITY_BIN path does not exist" Error:
- Check that the path to
profanity.rbis correct and the file exists.
- Check that the path to
- Terminal Rendering Issues:
- If the interface doesn't display correctly, try running the script in a different terminal emulator.
- Permission Denied Errors:
- Ensure that
launcher.pyis executable. - Verify permissions on the Lich and Profanity binaries.
- Ensure that
- Ruby Not Found:
- Ensure that Ruby is installed and the
rubycommand is available in your PATH.
- Ensure that Ruby is installed and the
This script is provided under the MIT License. You are free to use, modify, and distribute it as per the terms of the license.
Enjoy your gaming experience! If you encounter any issues or have suggestions for improvements, feel free to contribute or open an issue.