Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Repository files navigation

AetherTable

An open-source AI Game Master you self-host — and can run 100% locally. The model narrates; a real RNG rolls the dice.

Most "AI dungeon master" toys let the model type "you rolled a 17" — which means the model quietly decides your fate. AetherTable doesn't. It runs a real tabletop session with an AI DM — or an AI player at your table — across five real systems, and every die is rolled server-side by an actual RNG; the model only ever asks to roll. Play in the browser or in your terminal, by text or voice, on a frontier model or a local 7B.

Built with Python and React — runs on Google Gemini, or fully offline via Ollama / LM Studio.


Why AetherTable

  • The AI can't cheat the dice. The model never invents a number. When a roll is needed it emits a tag — [[ROLL:1d20+5]] — and the server rolls with a real RNG, then substitutes the result. The die is honest by construction.
  • Five real systems, real math. Dungeons & Dragons 5e · Pathfinder 2e · Call of Cthulhu 7e · Cyberpunk RED · Ordem Paranormal — each with its authentic resolution (roll-under percentile, exploding d10s, keep-highest attribute pools), not a generic "roll a d20."
  • No keys baked in — bring your own. This repo ships with no API key and never stores one. You pick a backend in the web UI and paste your own key; it stays in your browser. Or pick a local model and need no key at all.
  • Runs on your machine. Point it at Ollama or LM Studio and it plays fully offline — no API bill, nothing leaves the box. Prefer the cloud? Gemini and OpenAI-compatible endpoints work too.
  • DM or player. The AI can run the world, or join your party and play one character — declaring actions and waiting on the DM like everyone else.
  • Remembers long sagas. A live window keeps recent turns verbatim; older turns are folded into a rolling summary instead of being forgotten.
  • A full web client. Character creation with per-system attributes and derived stats, a live character sheet, five themes that re-skin the whole app, EN/PT-BR, and voice play.
  • Ships with evals. A tiny harness scores whether a model keeps the dice contract and stays in character — so you can measure a local 7B against a frontier model.

Quickstart — local & free

git clone https://github.com/IPedrax/AetherTable
cd AetherTable

# spin up the local model (free, offline)
ollama serve
ollama pull IPedrax/firefly-v5

docker compose up --build      # then open http://localhost:8080

Prefer to run it without Docker:

pip install -r requirements.txt
uvicorn server:app --reload           # the engine, on :8000

cd web && npm install && npm run dev  # the web client, on :5173

No .env needed for the web client — choose a backend and paste a key (if the backend needs one) on the Engine Settings screen. To play in the terminal instead, see Play.


Keys stay yours

There is no API key in this repository, and the server has none of its own.

  • Pick a backend in the UI. Ollama and LM Studio run on your machine and need no key whatsoever.
  • For a cloud backend, paste your own key. It's kept in your browser's localStorage and sent with each turn, used to build that one provider and then dropped — never written to disk, never logged, never shared between players.
  • Self-hosting for yourself only? Put the key in .env instead (see .env.example) and leave the UI field blank — the server falls back to the environment. This is what play.py and the CLI evals use.

Anything you type still reaches whichever model you chose, so a cloud backend sees your session; a local one doesn't. If you expose the engine beyond localhost, put it behind your own auth — it deliberately ships with none.


Providers

Backend Key needed Notes
Ollama (local) no free, offline — the default
LM Studio (local) no free, offline
Google Gemini (cloud) yes also the only backend that does voice input
OpenAI / any compatible endpoint yes cloud or proxy

Out of the box it points at IPedrax/firefly-v5 — a 6 GB, 128K-context local model that fits on an ordinary GPU and keeps the dice contract. Any other Ollama model works: change the name in Engine Settings, or set OLLAMA_MODEL for the terminal client.

Ollama and LM Studio both speak the OpenAI API, so one small provider class covers every local and cloud backend. Adding another is a ~20-line class in aethertable/providers.py.

In the terminal the same choice is made with LLM_PROVIDER=ollama | lmstudio | gemini | openai in .env.

Running the engine in Docker while Ollama runs on your host? Use http://host.docker.internal:11434/v1 as the endpoint — localhost would point at the container.


The web client

cd web && npm run dev
  • Engine Settings — pick a backend, model, and endpoint; paste a key only if the backend needs one.
  • Campaign setup — the AI runs the world as DM, or joins your party as a player while you DM.
  • Character creation — each system brings its own attributes, classes/ancestries, skills, and derived stats (D&D hit points, Cyberpunk RED Humanity, Ordem PV/PE/Sanity, CoC Sanity and damage bonus). Let the AI roll one up for you, then edit it.
  • The table — narration on parchment with resolved rolls inline, a live character sheet, push-to-talk voice (Gemini), and spoken replies when unmuted.
  • Five themes, one per system, applied app-wide — and EN / PT-BR, toggled with Alt+B.

The engine underneath is REST + WebSocket with no accounts, no quotas, no database — session history lives in memory for the life of the connection. Send {"type":"message","content":"I open the door","rpgSystem":"coc","settings":{…}} to /ws and stream back narration (and audio, if unmuted).


Play

No browser required — the terminal client is the zero-setup demo:

python play.py                     # AI Dungeon Master, D&D 5e
python play.py --system cyberpunk  # dnd5e | pathfinder | coc | enigma | cyberpunk
python play.py --role player       # flip it: the AI joins your party, you DM

It reads LLM_PROVIDER and the matching key from .env.


How the dice stay honest

The prompt forbids inventing numbers; to roll, the model must emit a tag like [[ROLL:1d20+5]]. The server intercepts it, rolls with a real RNG in aethertable/dice.py, and replaces the tag with [1d20+5 -> 17]. Because the contract is plain text, it works on any model — no provider-specific function-calling to maintain.

One parser covers every supported mechanic:

Expression Meaning System
1d20+5 flat modifier D&D / Pathfinder
1d100 roll-under percentile Call of Cthulhu
1d10!+7 exploding die Cyberpunk RED
3d20kh1 keep highest of a pool Ordem Paranormal

Evals

python -m aethertable.evals selftest   # offline scorer self-check, no network
python -m aethertable.evals            # live run against your configured provider

The live run reports dice-tag compliance and stayed-in-character rates — a quick way to see how playable a given local model actually is.


Architecture

aethertable/
  providers.py    swappable LLM backends (Gemini, OpenAI-compatible: Ollama/LM Studio/OpenAI)
  game_master.py  the narrative brain — provider-agnostic
  prompts.py      DM/Player instructions + the 5 game systems
  dice.py         deterministic dice (pure, self-tested)
  memory.py       rolling-window + summary memory (pure, self-tested)
  evals.py        behavioral evals for the dice + character contracts
play.py           terminal client (zero-setup demo)
server.py         FastAPI WebSocket + REST engine — no key of its own
web/              React + Vite client
  src/settings.ts       bring-your-own-key store (localStorage)
  src/data/            per-system character models, skills, derived stats
  src/components/      landing · settings · setup · character creator · sheet · table
  src/i18n.tsx         EN / PT-BR

Self-tests, no network:

python -m aethertable.dice        # -> dice OK
python -m aethertable.memory      # -> memory OK
python -m aethertable.providers   # -> providers OK  (credential precedence)

Roadmap — good first issues

  • React reference web UI
  • Local voice input via Whisper (STT for Ollama/LM Studio)
  • More systems: Blades in the Dark, Mothership, FATE
  • Token streaming over the WebSocket
  • Optional SQLite persistence adapter for the server
  • Save / export a campaign transcript from the browser

Contributions welcome — pick one, open a PR.


License

MIT © 2026 Pedro Medeiros


Built by Pedro Medeiros — science-fiction author & AI engineer.
ipedrax.com.br · The Harvest of Minds
---

Built by Pedro Medeiros. I build production LLM applications for companies too: multi-provider backends, the infrastructure under them, and the billing on top. Available for contract work, remote from Brazil on US hours. [email protected]

About

Open-source, self-hostable AI Game Master — the model narrates, a real RNG rolls the dice. Multi-provider (Gemini/Ollama/LM Studio/OpenAI), 5 tabletop systems, voice-optional.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages