Solo tabletop role-playing: AI roles play many rule sets, code owns the dice
Python
2
86 commits
updated Oct 6, 2026
Click the demo to watch it in full quality.
Rulehall is a browser game for solo tabletop role-playing. You type what your character does, and three AI roles and a rules engine play the rest of the table. When a setting turns it on, a fourth role, the opponent, plays the other side of a battle.
Python code owns the rules. It rolls the dice, checks every change the game master asks for, and keeps and saves the game state. The AI roles never touch the save.
Four rule sets ship with the app:
A scenario is a backdrop, a premise, a scope and an opening scene. The worldsmith writes one from your prompt, or from a document you drop in (Markdown, text or PDF). A character is one sheet per rule set. Some of both come with the game, and you can make your own in the app. Each rule set plays from a pack, which is either its own tables or a full kit with a backdrop, names, traits and adventure seeds. Loner ships with twelve genre packs, and you can write a pack of your own on the New pack page.
Each role runs on one of four providers, and you can mix them. The times below are for one whole turn.
| Provider | What you need | Time per turn | Cost per turn |
|---|---|---|---|
Claude Code (claude) | A Claude subscription | About 20 s (Opus master, Sonnet narrator) | Your subscription |
Codex (codex) | A ChatGPT subscription | 10 to 15 s (Sol master, Luna narrator) | Your subscription |
| OpenRouter | An API key | About 5 s with DeepSeek V4 Flash | $0.005 to $0.01 with DeepSeek V4 Flash |
| Local | A model that supports tool calls, served by Ollama for example | Depends on your hardware | Free |
Scene art is optional and off by default. It uses its own provider key, and a picture costs about $0.03 on OpenRouter.
Rulehall is not affiliated with or endorsed by Anthropic or OpenAI. With claude or codex, it drives their command-line tools with your own account. Whether that kind of use is allowed is up to their terms, which can change, and either of them could restrict or end it at any moment. Check their terms yourself. OpenRouter and local models don't depend on those terms.
Rulehall is under active development. Expect bugs, and expect things to change between versions, saves included.
Setup needs a terminal today: you install uv, run two commands, and connect an AI provider. If you're comfortable with that, you're the audience for now.
Much of the code is written with AI coding agents. CLAUDE.md and AGENTS.md hold the rules they follow, and the tests and checks in CI guard every change.
You need uv and one AI provider from the table above. The default settings use claude, installed and logged in. To use another provider, change it on the Settings page (see below). Rulehall runs on Linux and Windows. It should run on macOS too, but nobody has tried it there yet.
Install the project.
uv sync
Start the app.
uv run rulehall
Open the address the command prints.
Everything else, the AI commands included, lives on the Settings page. Each setting is a key in .env, and saving applies it at once, except for the server address and port, which wait until the server next starts.
A role doesn't have to use a command. Under Roles, set its provider to openrouter or local and name a model that supports tool calls: deepseek/deepseek-v4-flash-0731 on OpenRouter, for example, or a tool-capable model that Ollama serves at the local default, http://localhost:11434/v1. Each provider's base URL and key live under Providers. Over a completion API, the narrator and the worldsmith answer in one request each, and the master plays its tools inside the app's own process.
What you make is kept next to the app:
user/characters/<id>/<engine>.json: one sheet per rule set.user/scenarios/<id>/world.json: the opening the worldsmith wrote.packs/<engine>/<id>.json: the packs you wrote in the app. Edit the file to change a pack. The shipped packs are read-only.The shipped scenarios/ and characters/ are read-only too, and if one of yours has the same id, the shipped one wins.
Saves carry no version. When a change alters the stored shape, older saves go stale: the launcher skips them with a warning, and it never migrates or deletes them.
The Pokemon rule set runs its battles in Pokemon Showdown, a Node program, so it needs a bit of extra setup.
Install Node 22.
Install the simulator, its battle view and the sprites.
npm --prefix src/rulehall/engines/pokemon/showdown run setup
The setup downloads about 220 MB and takes a few minutes. The sprites cover every species in the dex, and once the setup is done the game needs no network. The dex export (npm --prefix src/rulehall/engines/pokemon/showdown run export-dex) and the pack export (npm --prefix src/rulehall/engines/pokemon/showdown run export-packs) do need the network, and they're only for maintainers.
Rulehall is a free fan project, not affiliated with Nintendo, Creatures Inc., Game Freak or The Pokemon Company. The sprites, music and Pokedex entries belong to them. docs/POKEMON.md lists what comes from where.
By default the app only listens on its own computer. Tailscale is a simple way to reach it from your other devices, at home or away. You'll need a free Tailscale account.
Install Tailscale on the computer that runs the app, then log in. On Linux:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Add this line to .env, then restart the app.
SERVER__HOST=0.0.0.0
Find the computer's Tailscale name, on the first line of:
tailscale status
Install the Tailscale app on the other device and log in with the same account.
On that device, open http://<name>:8080. If the name doesn't work, use the 100.x.x.x address from step 3.
The app has no login. Any device that can reach the port can play and change every setting, keys and provider addresses included. The page never shows a stored key, but please don't open the port to the internet.
Every push to master publishes ghcr.io/mmerah/rulehall, tagged latest and sha-<commit>, and each release adds its version, like 0.1.0. The image holds Python, Node, the Pokemon Showdown simulator, and the claude and codex commands. It holds no Pokemon art or sound: on its first start, the container fetches them (about 220 MB, a few minutes) into /data in the background. The other rule sets work at once, and Pokemon battles open once the log says Pokemon art and sound: ready. After that, the game needs no network. The image also installs Anthropic's Claude Code (proprietary, under Anthropic's terms) and OpenAI Codex (Apache-2.0); Rulehall's MIT licence does not cover them.
docker run -d -p 8080:8080 \
-v rulehall-data:/data -v rulehall-home:/home/rulehall \
-e CLAUDE_CODE_OAUTH_TOKEN=<token> \
ghcr.io/mmerah/rulehall
/data holds .env, saves/, packs/, user/ and vendor/ (the Pokemon art and sound)./home/rulehall holds the logins of the AI commands.claude setup-token on a computer that has a browser.PROVIDERS__OPENROUTER__API_KEY, or enter the key on the Settings page.FETCH_POKEMON_ASSETS=false to skip the fetch. Pokemon battles then stay off. If the fetch fails, restart the container: it resumes where it stopped.GET /status answers {"busy": <bool>, "idle_seconds": <float>}. busy is true while a turn is playing or a scenario or pack is being written.The code is MIT, © 2026 Mounir Merah. Read LICENSE. The rule sets below keep their own licenses.
The sample portraits under scenarios/ and characters/ are AI-generated. src/rulehall/ui/sounds/roll.wav was made for Rulehall and is MIT.
Loner 4e: Core Rules © 2026 Roberto Bisceglie. Licensed under CC BY-SA 4.0 — attribution in the Loner notes.
Tunnel Goons is © Nate Treme, released under a Creative Commons 4.0 International License — attribution in the Tunnel Goons notes.
24XX rules (v1.4) are CC BY Jason Tocci — attribution in the 24XX notes.
Solo tabletop role-playing: AI roles play many rule sets, code owns the dice
Python
2
86 commits
updated Oct 6, 2026
Click the demo to watch it in full quality.
Rulehall is a browser game for solo tabletop role-playing. You type what your character does, and three AI roles and a rules engine play the rest of the table. When a setting turns it on, a fourth role, the opponent, plays the other side of a battle.
Python code owns the rules. It rolls the dice, checks every change the game master asks for, and keeps and saves the game state. The AI roles never touch the save.
Four rule sets ship with the app:
A scenario is a backdrop, a premise, a scope and an opening scene. The worldsmith writes one from your prompt, or from a document you drop in (Markdown, text or PDF). A character is one sheet per rule set. Some of both come with the game, and you can make your own in the app. Each rule set plays from a pack, which is either its own tables or a full kit with a backdrop, names, traits and adventure seeds. Loner ships with twelve genre packs, and you can write a pack of your own on the New pack page.
Each role runs on one of four providers, and you can mix them. The times below are for one whole turn.
| Provider | What you need | Time per turn | Cost per turn |
|---|---|---|---|
Claude Code (claude) | A Claude subscription | About 20 s (Opus master, Sonnet narrator) | Your subscription |
Codex (codex) | A ChatGPT subscription | 10 to 15 s (Sol master, Luna narrator) | Your subscription |
| OpenRouter | An API key | About 5 s with DeepSeek V4 Flash | $0.005 to $0.01 with DeepSeek V4 Flash |
| Local | A model that supports tool calls, served by Ollama for example | Depends on your hardware | Free |
Scene art is optional and off by default. It uses its own provider key, and a picture costs about $0.03 on OpenRouter.
Rulehall is not affiliated with or endorsed by Anthropic or OpenAI. With claude or codex, it drives their command-line tools with your own account. Whether that kind of use is allowed is up to their terms, which can change, and either of them could restrict or end it at any moment. Check their terms yourself. OpenRouter and local models don't depend on those terms.
Rulehall is under active development. Expect bugs, and expect things to change between versions, saves included.
Setup needs a terminal today: you install uv, run two commands, and connect an AI provider. If you're comfortable with that, you're the audience for now.
Much of the code is written with AI coding agents. CLAUDE.md and AGENTS.md hold the rules they follow, and the tests and checks in CI guard every change.
You need uv and one AI provider from the table above. The default settings use claude, installed and logged in. To use another provider, change it on the Settings page (see below). Rulehall runs on Linux and Windows. It should run on macOS too, but nobody has tried it there yet.
Install the project.
uv sync
Start the app.
uv run rulehall
Open the address the command prints.
Everything else, the AI commands included, lives on the Settings page. Each setting is a key in .env, and saving applies it at once, except for the server address and port, which wait until the server next starts.
A role doesn't have to use a command. Under Roles, set its provider to openrouter or local and name a model that supports tool calls: deepseek/deepseek-v4-flash-0731 on OpenRouter, for example, or a tool-capable model that Ollama serves at the local default, http://localhost:11434/v1. Each provider's base URL and key live under Providers. Over a completion API, the narrator and the worldsmith answer in one request each, and the master plays its tools inside the app's own process.
What you make is kept next to the app:
user/characters/<id>/<engine>.json: one sheet per rule set.user/scenarios/<id>/world.json: the opening the worldsmith wrote.packs/<engine>/<id>.json: the packs you wrote in the app. Edit the file to change a pack. The shipped packs are read-only.The shipped scenarios/ and characters/ are read-only too, and if one of yours has the same id, the shipped one wins.
Saves carry no version. When a change alters the stored shape, older saves go stale: the launcher skips them with a warning, and it never migrates or deletes them.
The Pokemon rule set runs its battles in Pokemon Showdown, a Node program, so it needs a bit of extra setup.
Install Node 22.
Install the simulator, its battle view and the sprites.
npm --prefix src/rulehall/engines/pokemon/showdown run setup
The setup downloads about 220 MB and takes a few minutes. The sprites cover every species in the dex, and once the setup is done the game needs no network. The dex export (npm --prefix src/rulehall/engines/pokemon/showdown run export-dex) and the pack export (npm --prefix src/rulehall/engines/pokemon/showdown run export-packs) do need the network, and they're only for maintainers.
Rulehall is a free fan project, not affiliated with Nintendo, Creatures Inc., Game Freak or The Pokemon Company. The sprites, music and Pokedex entries belong to them. docs/POKEMON.md lists what comes from where.
By default the app only listens on its own computer. Tailscale is a simple way to reach it from your other devices, at home or away. You'll need a free Tailscale account.
Install Tailscale on the computer that runs the app, then log in. On Linux:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Add this line to .env, then restart the app.
SERVER__HOST=0.0.0.0
Find the computer's Tailscale name, on the first line of:
tailscale status
Install the Tailscale app on the other device and log in with the same account.
On that device, open http://<name>:8080. If the name doesn't work, use the 100.x.x.x address from step 3.
The app has no login. Any device that can reach the port can play and change every setting, keys and provider addresses included. The page never shows a stored key, but please don't open the port to the internet.
Every push to master publishes ghcr.io/mmerah/rulehall, tagged latest and sha-<commit>, and each release adds its version, like 0.1.0. The image holds Python, Node, the Pokemon Showdown simulator, and the claude and codex commands. It holds no Pokemon art or sound: on its first start, the container fetches them (about 220 MB, a few minutes) into /data in the background. The other rule sets work at once, and Pokemon battles open once the log says Pokemon art and sound: ready. After that, the game needs no network. The image also installs Anthropic's Claude Code (proprietary, under Anthropic's terms) and OpenAI Codex (Apache-2.0); Rulehall's MIT licence does not cover them.
docker run -d -p 8080:8080 \
-v rulehall-data:/data -v rulehall-home:/home/rulehall \
-e CLAUDE_CODE_OAUTH_TOKEN=<token> \
ghcr.io/mmerah/rulehall
/data holds .env, saves/, packs/, user/ and vendor/ (the Pokemon art and sound)./home/rulehall holds the logins of the AI commands.claude setup-token on a computer that has a browser.PROVIDERS__OPENROUTER__API_KEY, or enter the key on the Settings page.FETCH_POKEMON_ASSETS=false to skip the fetch. Pokemon battles then stay off. If the fetch fails, restart the container: it resumes where it stopped.GET /status answers {"busy": <bool>, "idle_seconds": <float>}. busy is true while a turn is playing or a scenario or pack is being written.The code is MIT, © 2026 Mounir Merah. Read LICENSE. The rule sets below keep their own licenses.
The sample portraits under scenarios/ and characters/ are AI-generated. src/rulehall/ui/sounds/roll.wav was made for Rulehall and is MIT.
Loner 4e: Core Rules © 2026 Roberto Bisceglie. Licensed under CC BY-SA 4.0 — attribution in the Loner notes.
Tunnel Goons is © Nate Treme, released under a Creative Commons 4.0 International License — attribution in the Tunnel Goons notes.
24XX rules (v1.4) are CC BY Jason Tocci — attribution in the 24XX notes.