lefteros_by SomniusX
EL ↗Say hello

LEFTEROS / PERSONAL ARCHIVE

ShadowRealms AI — a local AI Storyteller for World of Darkness

31 May 2026 / Lefteris Iliadis / SomniusX

ShadowRealms AI's new logo: the sigil with the drop of blood and the moon

This is the biggest public project I run as Somnius: a web app for World of Darkness chronicles with an AI Storyteller, which you host yourself. The app runs in Docker and the language models on your own computer, through LM Studio and Ollama, so your stories stay with you. Every chronicle is played either with the classic rules (Classic, oWoD Revised) or with V5, and both the interface and the Storyteller speak English and Greek.

The repository opened on 28 August 2025. On 4 October 2026 versions 0.9.0 to 0.10.0 came out together, the biggest update since the project began, along with a two-minute trailer in English and in Greek. On 15 and 16 October versions 0.11.0 to 0.14.1 followed, about V5 characters made by the book, and a new trailer two and a half minutes long. Later on the 16th came 0.15.0, with ghoul sheets for V5 and Classic, and overnight to the 17th 0.16.0 to 0.22.1, which give the chat a voice: you hear it read aloud and you can speak your lines. Later on the 17th came 0.23.0 to 0.28.0, with cloud voices (opt-in) and the chronicle so far: the local model writes every chronicle’s chat up as minutes, night by night. On 18 and 19 October came 0.29.0 to 0.31.0: the AI Storyteller now remembers the chronicle so far, and a fallen character gets its death written by the local model, from an admin page that kills, revives and keeps the deaths log. The app is open source, under the MIT licence.

A V5 chronicle in play: dice cards, a Rouse check, the AI Storyteller's reply and the character panel

“Athens by Night” (V5) in play: two dice cards, a Rouse check, the Storyteller’s reply, and on the right the character with their Hunger.

Beta testing

I'm looking for a few people to test the platform, not to run a real chronicle: sign up, Classic and V5 characters in the forge, a chronicle with rooms, dice, a chat with the AI Storyteller, voice from a phone, switching between Greek and English, the chronicle so far. It runs on a test copy on my own machine, with a local model, so replies can be slow and the server will be down at times. Whatever is written in the test chronicles is visible to me, as the admin.

For access send me a message (on Discord or through the contact page) and I'll give you the address and an invite code privately. Report what you find with the beta form on GitHub: it needs a free account, and issues are public, so no personal data and no server address.

The trailer

The new trailer, two and a half minutes long, shows what came after the first one: the Storyteller setting a chronicle’s character creation rules, Guided mode suggesting a clan from a few questions, the new forge with every power and its page in the book, a bestial failure with /ai explain on it, a botch in Classic, and the character sheet as a PDF.

Everything in it is real: recorded on a demo copy of the app, with real AI Storyteller replies (Llama-Krikri, running locally), real dice rolls from the server and an original score. For the bestial failure and the botch I just kept rolling until they landed. The videos play straight from GitHub, in 1080p at 60 fps; each is about 570 MB, so they need a good connection. For the best experience, watch them fullscreen.

In English

In Greek

If it doesn’t play in your browser, download the video: English · Greek · the trailer’s page on GitHub. The first trailer, from 0.10.0, is still on GitHub.

Voice (0.16 to 0.22)

From the evening of 16 October to the morning of the 17th, seven releases gave the chat a voice. All of it runs on the app’s own server, in an optional speech container. More in the post about the voice.

A Storyteller reply being read aloud: the message highlighted and the current sentence in the speaking bar

Listening in a room: the message being read is highlighted, and the bar shows the sentence being said.

  • Listen (0.16, 0.17): an ear in the room header reads the chat aloud, with the phone’s voices or the server’s (Piper for English, Pocket TTS for Greek). A character speaks with a voice of its gender (female, male or neutral, set on its character sheet), the Storyteller with the chronicle’s narrator voice, in American or British English or Greek. The chronicle’s creator sets what is read by default; every player can turn things off, and set speed and volume.
  • Speak (0.18): the mic in the message box records up to three minutes, with a large timer and a ring that pulses and changes colour as time passes. You listen back with a slider and speeds, pick the language you spoke with a flag, transcribe it with Whisper, fix the text, and send it in character, as a quote or out of character. Voice messages carry a mic everyone sees, and the recording plays from the chat for the chronicle’s lifetime.
  • In your language (0.19): read and hear the chat in your own language, with the original one tap away; speak Greek and send English. The translator is Llama-Krikri, with the chronicle’s names kept out of the translation.
  • Transcript check (0.21): Laya-words, my model from RecMeets, marks the probably misheard words and Llama-Krikri fixes only those, slang and swearing included.
  • Read along (0.22): sentence by sentence, so a long reply starts in about three seconds; the message highlighted and followed; “Read this” and “Read from here” on a long press; the dice read as a sentence in your language. And in 0.22.1, English voices say Greek names the Greek way.

The chronicle so far (0.23 to 0.28)

On 17 October, six releases gave every chronicle its minutes. The local model writes the chat up as a story, the way minutes are written from a meeting’s recording. More in the post about the chronicle so far.

  • The chronicle so far (0.24): a panel in Chronicle settings writes the chat one room and one night at a time, in Greek with Llama-Krikri, in English with the LM Studio model: in short, the story so far, the open threads, and every night with a title, paragraphs and what happened, each event pointing back to its messages. It is written from what the players could read; the Storyteller has a part of their own with what they didn’t see. Only the nights that changed are written again, with live progress and Cancel.
  • Minutes on paper (0.25, 0.26): export as Markdown or PDF, for the whole chronicle, the last N nights or a date range; in the character sheet’s look or a horror look (stained paper, a blood-red frame with thorns, splatters and drips), in colour or black and white for print, A4 or Letter. Greek text can be selected and searched in the PDF.
  • The Storyteller edits and translates (0.25): the whole story edited in one Markdown box, with the written text kept apart; translation into the other language by the chat’s translator, with the names protected. And “Session ended here” (0.26) from a message’s menu, which cuts the nights there.
  • Previously on… (0.27): whoever opens a room after twelve hours away gets a card with the nights they missed and the story in short, built only from the players’ view and with no model call, with “Jump to the start” of each night and “Read it” aloud.
  • For the admin (0.28): settings per chronicle (night gap, writer model, table talk), an optional nightly run, writer health, and archives: a deleted chronicle leaves its minutes and transcript behind, for admins and for its Storyteller for 30 days.
  • Cloud voices (0.23): Google Gemini voices, free or paid tier, turned on by the admin and chosen by each chronicle for itself; off by default, and if Gemini doesn’t answer, the local voice speaks.

The Storyteller remembers (0.29 to 0.31)

On 18 and 19 October, three releases put the minutes to use. More in the post about the Storyteller’s memory.

  • The Storyteller remembers (0.29): every AI Storyteller reply gets a short block from the chronicle so far (the story in short, the open threads, the last three nights of the room, one line per other room, the Storyteller-only paragraphs), at most a quarter of the prompt and never more than 1,500 tokens, with no model call and no waiting. It is the Storyteller’s private memory, never quoted to players; on for every chronicle, with a switch in Chronicle settings, and /ai context shows it to admins only.
  • A death in writing (0.30): when an admin kills a character, the chronicle writer writes two to four sentences of the death in the chronicle’s language, from the story so far and the character’s last nights, player view only; on any failure or timeout the fixed sentence is used, in Greek too. Also: the composer’s slash commands come from the server, in English and Greek, and a chronicle created through the API without a language takes its creator’s app language.
  • The kill page (0.31): Admin → Characters lists every player character, alive or fallen; Kill picks the death (soft, sacrifice, horrible), shows the text and whether the AI wrote it; Revive undoes it and the kill stays in the deaths log, which also goes to the moderation log. The fallen show the death text on the owner’s profile card and on the sheet. The death prompt forbids invented names, clans, places and lore, and mixed scripts in Greek fall back to the fixed sentence. And on phones the whole sheet scrolls, with only the name bar staying on top.
  • SPEC.md: a system specification in the repository, at 0.31.0: what the system is and must do, roles, data, scope.

What changed since 0.10

0.15.0 “Blood servants” (16 October 2026): ghouls get their own sheet, made from your vampire’s sheet with “Add a ghoul retainer”. A ghoul belongs to the same player, follows its domitor and has no chronicle of its own; the domitor’s Storyteller can read it, and the AI Storyteller sees up to two of a playing character’s ghouls. More in the post about 0.15.

  • V5 ghouls: a retainer on the corebook’s mortal templates (Weak •, Average ••, Gifted •••, or Deadly; pp. 185, 194) or a player ghoul by the Players Guide (pp. 140–142), with one level 1 power of a Discipline its domitor has, the ghoul-only Merits and Flaws, and a Blood Bond. No blood pool: in V5 a ghoul has no vitae to spend, no Hunger and no Blood Potency (core p. 234). The server checks it like a vampire.
  • Classic Revised ghouls, by Ghouls: Fatal Addiction: Attributes 6/4/3, Abilities 11/7/4, 21 freebies, Potence 1 and one more Discipline, a Blood Pool of up to 10 spent 1 per turn, the Domitor Background, and a PDF laid out like the old ghoul sheet.
  • The sheet PDF has a print version with no form fields, which looks the same in every viewer, the fillable one keeps Turkish and other accented letters, and long backgrounds and notes continue on extra pages.

A Classic ghoul’s sheet: Potence, the Domitor Background, the Blood Pool, Blood Bond and Overdosing

A Classic ghoul’s sheet in the PDF, with its Blood Pool.

On 15 and 16 October 2026 came versions 0.11.0 to 0.14.1 (0.11.0 on the 15th, the rest on the 16th). Almost all of it is Forge v2: V5 characters made by the book. More in the post about 0.14.

0.11.0 “By the book”:

  • A V5 rules catalog. All 16 clans (the corebook’s seven, the Players Guide’s seven with the Hecata, plus Caitiff and thin-bloods), every Discipline power, Blood Sorcery ritual, Oblivion ceremony and thin-blood alchemy formula, and the 18 predator types, each with its book and page and a short description in English and Greek. A script built it from the official books, facts only, with no book text; the descriptions are in our own words.
  • The V5 forge follows the corebook’s order, with powers and rituals picked from lists and the real choices of each predator type. At the Disciplines step you see what a predator type gives before you pick it, and its Flaws now count as extra: every character also takes 2 Flaw dots of its own, as the corebook says (p. 136). There’s also optional starting experience for neonates and ancillae.
  • Export to PDF: a fillable two-page character sheet for V5 or Classic Revised, in black and white for ordinary printers, Greek included.
  • /ai explain: reply to a dice card, and the Storyteller explains how that roll was counted, step by step, with the corebook page. Hidden rolls stay hidden.
  • Character creation rules per chronicle: which clans, predator types and ages the forge offers, and house rules shown at the top of the forge.
  • The rule books are imported by a script, not read by an AI, into separate collections for each edition, so a Vampire chronicle never gets Werewolf rules. Dice leniency is set per edition too.

0.12.0 “Merits and guides”:

  • Guided mode: instead of the full forge, a player can answer scenario questions, one per screen, and get a suggested clan and predator type, with the Attributes and Skills filled in. Everything stays editable. The questions are a first set for now.
  • Advantages from the catalog: Backgrounds, Merits, Flaws and loresheets are picked from lists, with the ratings the books print.
  • The server checks V5 characters too, and refuses a sheet that breaks the rules, saying what’s wrong in English or Greek. The Storyteller can still approve a sheet outside the rules.
  • The PDF gets a Reference page with the clan, the powers, the rituals and the advantages the character has, each with its book and page.

0.13.0 “Saved for later”: Advantage dots left unspent at creation are kept on the sheet and spent later, with the Storyteller’s approval. A chronicle can let the AI Storyteller approve the spends that pass the rule check; that is a fixed check, not the language model, and a person can reverse it.

0.14.0 “The library” and 0.14.1 “House rulings”: the Storyteller picks which books a chronicle allows, and the forge offers only what they contain. The catalog grows with the supplements: 24 books, with 157 loresheets, 210 Discipline powers, 109 rituals, 29 ceremonies, 48 formulae and 279 Merits, Backgrounds and Flaws. Plus three house rulings, where the book is silent or says otherwise: the Caitiff’s Suspect counts toward the 2 Flaw dots, a player can take more than one loresheet at creation, and a player can take an Enemy or Dark Secret of their own beside the one the predator type gives.

What changed since 0.8

0.9.0 “Into the Night” rebuilds most of the app:

  • Two rules editions. Each chronicle picks Classic or V5 when it’s created and keeps it. A V5 dice engine (Hunger dice, pairs of 10s, messy criticals, bestial and total failures, Willpower rerolls, Rouse checks), and a separate character forge and sheet for each edition.
  • A new app: real URLs for every page, one navigation, and a Discord-style chat with live updates, dice cards and slash commands.
  • Greek everywhere: more than 1,080 strings in English and Greek, and the Storyteller answers in the player’s language (in Greek with Llama-Krikri).
  • A gothic redesign: 97 original SVG glyphs and sigils, fog, candle glow, blood on botches, animated dice, and an atmosphere setting for anyone who wants it calmer.
  • AI: local models first, multilingual long-term memory that finally works, and the Laya classifier for out-of-character chat.
  • Security: rate limits, lockouts, token revocation, a password policy, a login audit and a strict Content-Security-Policy.

0.9.1 to 0.9.4 fill the gaps: pick the edition first and then the game line, Willpower rerolls cost Willpower, a Logins & lockouts tab for admins, tokens that refresh themselves, log lines that can’t be forged, and at the table:

  • Dice pools from the sheet: when the Storyteller asks for a roll, the server works out the pool from your sheet (specialties, Hunger, impairment) and the chat shows a chip that fills in the dice dialog.
  • Copy, reply with a quote and delete on messages, and older history as you scroll up.

0.10.0 “New foundations” replaces the foundations: the interface now builds with Vite instead of Create React App, in about a second, with a smaller bundle and zero findings in the production npm audit (down from 69). In came react-router 7, motion 14, i18next 26 and Jest 30, and the unused packages went. All 204 lint warnings were fixed, and CI now fails on any new one. On the back end: Python 3.12 and ChromaDB pinned to 1.5.9.

How it plays

A V5 roll tumbling, settling as a win and posting to the chatThe rules. In Classic the dice follow Revised: difficulty 2 to 10, 1s cancel successes, a botch only when nothing succeeded, specialties re-roll 10s, and Willpower adds one success that can’t be cancelled. V5 has Hunger dice, messy criticals, bestial failures, Willpower rerolls and Rouse checks. The Storyteller’s prompt and the rule-book search follow the chronicle’s edition.

At the table. The chat feels like Discord: grouped messages, unread counts, in-character and out-of-character rooms. Rolls are made and posted by the server, so a dice card in the chat is always a real roll. /roll, /me and /chat for everyone and /ai for admins, and one “Speaking as” control for your character, yourself out of character or, for staff, the Storyteller’s voice.

Voice. Turn on the ear in a room and the chat is read aloud: each character in a voice of its gender, the Storyteller in the chronicle’s narrator voice, the dice as one sentence. Tap the mic to speak instead of typing; you check the text before it goes, and everyone can play the recording.

The chronicle so far. The Storyteller presses Update and the local model writes the chat up as a story, night by night, with every event pointing to its messages; they edit it, translate it and export it as a PDF, in the character sheet’s look or a horror look. A player who comes back after half a day gets a “Previously on…” with what they missed, and only what they could have seen. And the AI Storyteller reads the same minutes before every reply, so it remembers what happened three nights ago.

Characters. A character forge per edition: Classic with the Revised budgets (7/5/3, 13/9/5, virtues, 15 freebies), V5 with its spreads, Predator type, disciplines, advantages and flaws. Sheets lock after creation; changes go through downtime requests the Storyteller approves. In V5 the forge follows the corebook’s order and takes its clans, powers and advantages from the rules catalog, or a Guided mode suggests a character for you, and every sheet exports to a fillable PDF. The Storyteller sets which clans, predator types, ages and books each chronicle allows.

A V5 bestial failure with cracks, blood and a skull on the Hunger dieThe atmosphere. 97 original SVG glyphs, fog, candle glow and blood dripping on botches. Each account picks its atmosphere: full, subtle or off. A guided tour of the theme lives at the app’s /showcase address.

The AI Storyteller

Instead of one model there are roles, each with its own model, all set in the admin panel:

Role Model Runs on
Storyteller (English) whatever model LM Studio has loaded LM Studio, graphics card
Storyteller (Greek) llama-krikri-8b-instruct (Llama-Krikri by ILSP) LM Studio
Utility calls llama3.2:3b Ollama
Memory and rules bge-m3 embeddings (multilingual) LM Studio, with ChromaDB
Chat moderation Laya, my own fine-tuned mmBERT processor, ONNX Runtime
Translator llama-krikri-8b-instruct, with a game-term glossary LM Studio
Voices Piper (English) and Pocket TTS (Greek) the speech container
Transcription Whisper large-v3-turbo, checked by Laya-words the speech container, graphics card
Chronicle writer llama-krikri-8b-instruct for Greek, the loaded model for English (or one model per chronicle) LM Studio
Cloud voices (optional) Google Gemini, free or paid tier, per chronicle Google, with the local voices as fallback
Death text the chronicle writer, in the chronicle’s language, with a fixed sentence as fallback LM Studio
  • Llama-Krikri was chosen because it writes clean Greek; in tests, Gemma 4 E2B answered Greek prompts in English.
  • Long-term memory and the rule-book search are RAG on ChromaDB, with bge-m3 understanding English, Greek and the mix of the two.
  • The Laya classifier moderates the out-of-character rooms and reads the intent of each message, in about 230 ms on the processor. It was trained with the same process as RecMeets' Laya, on hand-written and synthetic messages in English, Greek and Greeklish.
  • Optionally, an admin can add Anthropic or OpenAI keys, stored encrypted; they are off by default.

Screens

A message’s menu on a phone, with Read this and Read from here The recorder on a phone, with the timer and the ring Reviewing a recording before transcription

The voice on a phone: a message’s menu, recording, and reviewing before transcription.

Profile, Voice: voices, accent, speed, volume and what is read A chronicle’s voice settings: narrator voices and read-out defaults

A player’s voice settings · a chronicle’s narrator voices and read-out defaults.

Guided mode suggests Hecata and Grim Reaper, with the answers behind it The new forge: powers picked from a list with their description and page, and the predator type preview

From the new trailer: Guided mode suggests a clan and a predator type · the forge with every power and its page.

A chronicle’s character creation rules: allowed books and clans The PDF’s Reference page with the clan, predator type, powers and Advantages

A chronicle’s creation rules, with its books and clans · the Reference page in the sheet PDF.

The chronicle hall with a Classic and a V5 chronicle Playing with the interface and the Storyteller in Greek

The chronicle hall, with a Classic and a V5 chronicle · the same chronicle with the interface and the Storyteller in Greek.

The V5 roll dialog with pool, difficulty, Hunger and a Rouse check A Classic roll with a specialty, its 10s re-rolled into gold dice

The V5 roll dialog · a Classic roll with a specialty and an exceptional success.

The V5 character forge at Attributes and Skills The V5 character sheet with Hunger, Willpower and Humanity trackers

The V5 forge with live counters · the character sheet and its trackers.

The Classic forge with the 7/5/3 and 13/9/5 budgets Skills with specialties, disciplines and advantages on the V5 sheet

The Classic forge with the Revised budgets · skills, disciplines and advantages on the sheet.

The glyph grimoire: animated glyphs, search and groups A Revised botch beside a V5 messy critical

The grimoire of 97 glyphs · a Revised botch beside a V5 messy critical.

The sign-in page with the animated sigil and fog The account menu with language and atmosphere

Sign-in with the animated sigil · language and atmosphere from the account menu.

Chronicle settings with its locations The admin panel: models per role

A chronicle’s locations · models per role in the admin panel.

Playing on a phone, with a Storyteller reply The chronicles and rooms drawer on a phone Sign-in on a phone

And on a phone: playing, chronicles and rooms, sign-in.

Tech stack

Docker Python Flask Gunicorn PostgreSQL Redis ChromaDB RAG LM Studio Ollama ONNX Runtime FastAPI faster-whisper Piper TTS Pocket TTS Opus Hugging Face React Vite Tailwind CSS i18next Jest ESLint Nginx JWT GitHub Actions Git GitHub

AI Llama-Krikri 8B and any model in LM Studio, Llama 3.2 3B on Ollama, bge-m3 embeddings, the Laya classifier on ONNX Runtime, optional Anthropic and OpenAI
Voice Piper and Pocket TTS for speech, faster-whisper (large-v3-turbo) for transcription, Laya-words on ONNX for the transcript check, FastAPI, Opus recordings, optional Google Gemini voices
Memory and rules RAG on ChromaDB 1.5.9
Back end Python 3.12, Flask 3.1 on gunicorn, PyMuPDF for the rule-book import, ReportLab for the sheet and chronicle PDFs, PostgreSQL 16, Redis 7, server-sent events, bcrypt and Fernet encryption, JWT
Interface React 18, Vite 8, react-router 7, motion 14, i18next (English and Greek), DOMPurify, d3, Tailwind CSS and my own design system with 97 SVG glyphs
Infrastructure Docker Compose (with an optional voice profile), nginx with a strict CSP, NVIDIA container runtime
Quality and security GitHub Actions (pytest, Jest, ESLint, a database schema check), CodeQL, Dependabot, branch protection, more than 250 back-end and 360 interface tests

Developed on Linux (Omarchy), with an AMD Ryzen 9 5950X and an NVIDIA RTX 4080 SUPER 16 GB. Llama-Krikri needs about 5 GB of graphics memory.

Quick start

You need Linux with Docker and Compose v2, LM Studio with its lms command, and Ollama. An NVIDIA graphics card is strongly recommended.

git clone https://github.com/Somnius/shadowrealms-ai.git
cd shadowrealms-ai
cp env.template .env
cp backend/invites.template.json backend/invites.json
python3 scripts/generate_secret_key.py

Put your own keys and PostgreSQL credentials in .env and your own invite codes in invites.json (registration needs an invite). Then:

lms server start
lms load llama-krikri-8b-instruct -y
lms load text-embedding-bge-m3 -y
ollama pull llama3.2:3b
./docker-up.sh
./scripts/build-frontend.sh

For the voice, also start the speech container: docker compose --profile voice up -d speech (it needs SPEECH_SECRET in .env; see docs/VOICE.md).

Open http://localhost, register with your admin code, create a chronicle and type /ai health in its chat. Every step in detail is on the wiki’s installation page.

Contributing

The project is big on purpose, and it needs contributors: code, RPG mechanics, hands-on testing, translations, or just clear issues with steps to reproduce. Everything runs inside Docker, and every change goes through CI before it lands.

Licence

MIT: LICENSE. White Wolf’s commercial books are not covered by the licence; they stay your own files in the data/ folder, and I don’t host them.

Posts

Sources

Updated on 19 October 2026, with version 0.31.0 and the Storyteller’s memory.