github

oma-solorpg · a solo virtual tabletop for Omarchy

Your agent is the game master

You play a tabletop RPG alone, tonight, with no prep. Claude Code or Codex runs the game from behind a book of prose, and you answer it in words. A small engine owns the dice, the rules and every word said at the table, and the agent has to go through it for all of them.

install it tonight watch the trailer 45 s

Plays Ironsworn out of the box, its free rules shipped with credit, and Dragonbane, built from your own copy of the rules.

an omarchy-shell plugin · standard-library Python 3.11 · no API keys · no network · MIT

The Book during a fight in Chieftain's Hall: Ragna's text portrait, a fight tableau with Grukk Red Tusk, and the story log.
the Book · Chieftain's Hall

The trailer

the Book and the Table, in play

The Book

where the story is read and told

A coding agent in a terminal prints its tool calls, permission prompts and JSON between the lines of your story. The Book takes the story out of the terminal. The agent runs headless behind it, its narration streams in as it writes, and what you read is prose.

None of these is a mockup. They're screens from The Red Tusk Hall, the adventure that ships with oma-solorpg: the plugin's own QML, rendered offscreen against real engine state by the test harness in tests/qml. Click one to look closer.

roll it yourself d20 under the skill · Dragon on 1 · Demon on 20

          

Ragna

Adult · Dwarf · Fighter

HP 14/14

WP 11/11

no conditions

Boons0 Banes0

SWORDS

needs 14 or less

 

a face that follows the story drawn by solo/portrait.py

        

Kin and profession

What the story did to them

A head per kin with slots for the eyes, brows, mouth, wounds and age, headgear per profession, a mood per condition. The Book colours each stroke by what it is, and the face blinks now and then.

The desktop joins in

your window borders, your screen, your notifications

On Omarchy the big moments leave the Book. Hyprland's window borders, a screen shader and hyprsunset land with the Book's dice to the millisecond, and each can be switched off under Desktop effects on the Table. Here CSS stands in for them, and the sounds are synthesised on the spot, the way the plugin makes its own with Python's standard library.

1 2 3 4Day 1, 00:15◆
The Book in a fight at the Fiendish Altar.
The Table during the same fight.
solo deskclick one

The dice are code

the agent narrates, the engine decides

Questions nobody rolls for go down a fixed ladder: the adventure's text first, then a skill check, then the oracle, which takes its odds from what the campaign tracks. The agent never picks the answer. Every change is an event in events.jsonl, and the state is rebuilt from it at any time.

how a turn works
  1. youwrite to the GM at the bottom of the Book
  2. agentpicks one intent from what solo scene offers
  3. enginesolo check sneaking: the dice and the rules, in code
  4. agentreads the scene and proposes the consequence
  5. enginesolo commit '{"facts": …}': validated, logged, clocks advance
  6. agentnarrates what was committed

Fights, dying and advancement are rules the engine runs: initiative cards, weapon damage through armor, death rolls at zero HP, and skills marked by Dragons and Demons and rolled up at the end of a session.

solo check sneaking

{
  "summary": "Sneaking: 16 vs 5, failure",
  "push": {
    "cost": "take a condition",
    "choose_from": ["exhausted", "sickly", "dazed", "angry", "scared", "disheartened"]
  },
  …
}

solo commit '{"note": "the horn sounds", "facts": {"hall.alarm": true}}'

{
  "summary": "the horn sounds [for the GM: facts hall.alarm = true]",
  "then": [
    "The ritual below 1/6",
    "Omens of the ritual (3): A low chant rises from somewhere under your feet."
  ],
  …
}

solo ask "Is the gate barred from the inside?"

{ "summary": "asked \"Is the gate barred from the inside?\" (fortune, yes/no, rolled 2): No", … }

Real output from the engine, trimmed where it says …

playing alone, by the book

With Dragonbane's own solo rules built into your pack (they're in Alone in Deepfall Breach, in the core set), the engine runs the game the way the book means it to be played alone.

  • Your hero starts with one more heroic ability. Army of One deals you two initiative cards in a fight; Sole Survivor lets you push a roll for willpower instead of a condition.
  • Questions a GM would answer go to the book's fortune chart: yes or no, how many, how big, how strong, how fine, or how someone reacts. Open questions get words to read.
  • Threats loom on a counter that climbs with every delay, and come for you when it fills.
  • You can search an area and scavenge a nest. Foes the adventure never wrote fight as minions or bosses.
  • At a rest you tend your own wounds. At zero HP you can rally yourself, or try to save your own life.

Without a solo rules book the oracle is the engine's own, a likelihood oracle that brings surprises: random events tied to the people and threads in play, and scenes that turn out altered, as often as a chaos factor says.

The Table: Ragna's sheet, a fight against two demon cultists, the oracle with the fortune chart, and a threat clock.
the Table, mid-fight

Bring your books

rules and adventures, read from PDFs you own

oma-solorpg ships Dragonbane's words and none of its rules. make dragonbane reads the books it knows from your PDFs, by their bookmarks and layout, with no agent. For a book it doesn't know, your agent reads it a chapter at a time and writes a pack the engine can run, every number citing the page it came from. The book never goes through a chat upload, however big it is, and nothing built from it lands in the repository.

what make rules does
  1. solo extract turns the PDF into pages and chapters of text, with the running heads taken out and the printed page numbers read off the footers.
  2. Any page that holds a roll table is also saved as a picture, because text extraction scrambles columns and the agent can look at the page instead. A page with no text on it is flagged as a scan.
  3. solo inventory starts a checklist: an item for every section and table, every page cited.
  4. Your agent works through it with the solo-rules-import skill: attributes, creation tables, weapons and armor, fear and mishap tables, a bestiary, the price lists, a rules page per topic.
  5. solo audit fails on anything unaccounted for, either way, and on any table result, die, monster stat or price that isn't on the page it cites.

make rules BOOK=… SOLO_BOOK=… runs the mechanical steps and then opens your agent with the skill and a prompt. The pack lands in ~/Games/solo/systems, laid over the names the repository ships.

solo extract "Dragon Tests.pdf"

wrote ~/Games/solo/sources/dragon-tests

6 pages, 756 characters (about 189 tokens), 4 chapters from the outline, 1 table

The PDF has no page labels: the printed page numbers were read off the footers (manifest.json, labels).

solo inventory ~/Games/solo/systems/dragon-tests --extract ~/Games/solo/sources/dragon-tests

wrote 5 files in ~/Games/solo/systems/dragon-tests: inventory.toml, inventory/01-front.toml, inventory/02-equipment.toml, inventory/03-travel.toml, inventory/04-monsters.toml

Every page with text is cited by a todo item. Refine each chapter file, map every item, and run solo audit until it's clean.

solo import table ~/Games/solo/sources/dragon-tests/pages/0005.txt --out ~/Games/solo/systems/dragon-tests/tables/weather.toml

wrote ~/Games/solo/systems/dragon-tests/tables/weather.toml

# the agent maps the rest, a chapter at a time

solo audit --system dragon-tests

# Audit of dragon-tests against Dragon Tests

5 items: 4 mapped, 1 skipped.
The pack holds 9 things an item must claim.

Everything is accounted for.

## The book's pages
5 of 5 pages with text are cited (Dragon Tests.pdf, 6 pages).

## Mechanics only in rules pages (1)
The GM reads these; the engine doesn't run them.
- journeys: Journeys (p. 4)

Real output, on the six-page rulebook the test suite makes up for itself (tests/test_rules_import.py).

tables/p0005.pngcaptured by solo extract
A captured PDF page: a weather table rolled on D6, with a running head and page number.
name = "Weather"
formula = "1d6"
results = [
  { range = [1, 2], text = "Clear skies" },
  { range = [3, 4], text = "Rain, a bane on BUSHCRAFT" },
  { range = [5, 5], text = "Storm, no travel" },
  { range = [6, 6], text = "Fog, a bane on AWARENESS" },
]

The page as a picture for the agent to read, and the table solo import table made of it, dice worked out.

adventures, too
make adventure ID=my-adventure PDF=~/Books/dragonbane-adventures.pdf
make adventure ID=my-adventure FOUNDRY=~/Exports/my-adventure
make check-adventure ID=my-adventure

From a PDF, or from a Foundry VTT export (journals, actors and roll tables). The solo-import skill adds what the text only implies: factions, clocks, gates, branches, people with profiles and voices. It also says how to turn a published adventure's table rules into solo ones: a real-time limit becomes game time, pre-made replacement heroes wait for your death, a tournament's score is kept.

solo outline shows the whole adventure on one page for review (spoilers), and solo validate points out scenes nobody can reach. The adventure then shows up on the New adventure screen.

From the author's shelf

two of Free League's own adventures, compiled from the author's copies and played through the engine

the Dragonbane quickstart's tournament adventure

The Sinking Tower

Every twenty years a drowned sorcerer's tower rises from the sea for two hours, a green light burning at its top. Seven floors of puzzles and monsters, and a tide that won't wait.

scenes
10
people & monsters
10
attack tables
6
rules pages
6
heroes
3

Play-tested with a real GM, scored 1 to 5 by a third agent on rules, adventure, state, secrecy, narration and agency. Archmaster Aodhan's full run went 33 turns across two dropped sessions with every clock, fact and condition intact: 5 5 5 5 4 4. With the solo rules, Ragna took two turns a round and killed the eel, the first run anyone lived through.

The title card: The Statue Gallery, The Sinking Tower.
The Book in The Cellar: Archmaster Aodhan fights a monster eel.
The codex with the monster eel and the one-eyed man, his secrets blanked.
A d20 landing on 1 for a Swimming roll: DRAGON.

the solo campaign in the Dragonbane core set

Alone in Deepfall Breach

A wound in the world, struck by a demon lord's spear, plunges leagues into the earth. An old wolfkin demon hunter watches over it from a ruined chapel, and he has work for you: five missions into the Breach, one after another.

missions
5
waypoints
34
scenes
39
people & monsters
15
rules pages
4

In a real GM run the hero pocketed a smith's whetstone in Outskirt and told the tavern keeper about a sister lost in the Breach. Then the GM's session was dropped. The fresh one found it all again from the record, had the smith tell the store keeper while the hero was away, and, of its own accord, tied the lost sister to a ghost waiting in mission four.

The title card: The Vault of Many Paths, Alone in Deepfall Breach.
The Book at the Fiendish Altar: Ragna fights two demon cultists.
The codex with a demon cultist, Gorum and Ingolfr Stone-Gaze.
Two d20s showing 7 and 20, the 20 lit red: DEMON.

The Sinking Tower and Alone in Deepfall Breach are Fria Ligan AB's. The author owns both books, and compiled these packs from them with the ingestion tools above; the screenshots are the engine playing those packs, rendered by the same harness as the rest of this page, with the GM's lines written for the occasion. The packs hold the books' text and tables, so they stay on the author's machine and are not in the repository. Build your own from the books you own.

A long campaign

the campaign remembers, so the GM doesn't have to

A campaign can run for many sessions, and the GM may start any of them knowing nothing. The agent's session can be lost, compacted or replaced at any time, and the campaign holds the memory for it.

generate a campaign

When no book holds the story you want, pitch one. Give your agent a premise, a tone and a length, and it writes the campaign as a pack: a hub to come back to, missions as paths of waypoints, factions that want things, clocks and threats, people with faces, voices and secrets.

make campaign ID=salt-and-ash TONE=grim MISSIONS=4 \
  PREMISE="a smuggler's coast where the dead keep the lighthouses"

Your system's own tables and the oracle roll the parts, so the dice have a say before you start. Missions after the first are written from what your hero actually did: the consequences they left open, the people who remember them. Then solo validate, solo outline and solo campaign check check it like any imported adventure, every roll used or explained, and it waits on the New adventure screen.

heroes carry on

A hero who lives through an adventure brings their story into the next one: how it ended, what was left open, who will remember them, and what you told the GM about them. A lost sister, an oath.

solo new red-tusk --character ~/Games/solo/campaigns/sinking-tower-ragna

And one who doesn't makes it into the Hall of the Fallen, with your last words.

Tonight, then

three commands, then click the d20

~
git clone https://github.com/cabral/oma-solorpg ~/Code/oma-solorpg && cd ~/Code/oma-solorpg
git checkout --detach 26048dee18cc6d139fb4281b17f16b4a01faf805
make install

The checkout pins a release, so what runs is what you read. make install links solo, the GM skills and the plugin, enables it, and says what is missing, if anything.

Then, with clicks only: the d20 in the bar opens the Table. New adventure, pick The Bell Under the Hill and a hero, Begin. That is Ironsworn, and it needs no book: its free rules come with the plugin. The Book opens beside the Table and the GM writes the opening scene.

  • Omarchy, make and Python 3.11 or newer
  • Claude Code or Codex, the agent Omarchy runs for you. Other agents open in a terminal (solo play --terminal), and the Book still shows the story as it is recorded.
dragonbane, from your books
sudo pacman -S python-pymupdf
make dragonbane BOOKS=~/Books/Dragonbane
make check

Dragonbane plays from your own PDFs. make dragonbane reads a folder of them and builds the core rules, the Book of Magic, the card decks, the solo booklet, The Sinking Tower and the Adventure Book's campaign into private packs in ~/Games/solo, in about twenty seconds and with no agent. make check audits them against the books. Then New adventure has The Red Tusk Hall and your books' adventures.

PyMuPDF reads the PDFs; the README says how to install it outside Omarchy. A book no importer knows goes to your agent: make rules BOOK=….

roadmapROADMAP.md
  • shipped Ironsworn with no book, Dragonbane's importers (make dragonbane), campaigns from a premise (make campaign), and the X-card and hard limits on a GM turn.
  • shipped Spells and willpower, weapons that break, ranged attacks, monster traits, the load, journeys rolled by the engine.
  • next Play tests with a real GM: on the imported books, on The Bell Under the Hill, and a baseline to measure every change to the GM against.
  • next Campaigns on Ironsworn, and the imported adventures' timers as clocks the engine counts.
  • later More agents that stream into the Book, more games on the existing families, the importer on the Table, a character roster.
The Table's New adventure screen listing Alone in Deepfall Breach, The Red Tusk Hall and The Sinking Tower, with a random hero preview.
the Table · New adventure

↑ ↓ to choose · enter · esc