The problem
World-building tools dump text. They do not keep a queryable world, or let you talk to the people in it. I needed lore that is stored, retrieved, and used in conversation: locally, replayably, without a web stack.
What I built
I built LoreBuilder as a Python CLI that treats lore as a small product. You add a fact, it is embedded and searchable. Character names are pulled from the text. Then you talk to one of them, and the reply is grounded in the world you just wrote.
Launch is python app.py. Work happens at a
>> prompt.
Three decisions
1. Split the world from the conversation.
Lore lives in Chroma (semantic). Chat lives in SQLite (per-character sessions). Adding lore is a write. Generating lore is a draft; storing it is an explicit commit. That is a product, not an LLM wrapper.
2. Characters come from the text, not a roster.
On the tape, add_lore introduces Captain Voss.
list_characters then shows Voss and
Mary: names extracted from stored lore, including entries
that were already in the world (Mary, Ardelune, the council of
scholars). The cast stays in sync with the writing.
3. A command registry, not a growing REPL.
Commands are listed in categories (Lore / Characters / System). Help
is generated from the registry. I kept one handler per file and left
deprecated modules unregistered. The demo on tape is slightly ahead
of the public repo (chat_to / chat_with /
reset_chat vs the published chat_as).
Proof
From the tape — add lore, query it, list characters extracted from the world, then chat with Voss grounded in what you just wrote.
>> add_lore Captain Voss keeps a brass compass that always points to the last place he broke a promise. Lore added with id 172161. >> query_lore compass Relevant Lore Entries: Entry 1: Captain Voss keeps a brass compass that always points to the last place he broke a promise. Entry 2: Mary is on the council of scholars. Entry 3: The city of Ardelune is ruled by a council of scholars. >> list_characters Characters mentioned in world lore (2): - Mary - Voss >> chat_to Voss Why does the compass never point north? Voss>> Ah, the compass—an artifact of my own making, but with a burden far heavier than mere metal and glass. It never points north because it seeks to remind me of the weight of my oaths.
The rest of the reply stays in character and pulls Ardelune and the council of scholars into the same answer. That is retrieval, not a canned line.
The clip ends at a new >> prompt; the last frames
also show exit returning to the shell.
Why I built it this way
I wanted a small Python system with the same standards I use in iOS work: clear module boundaries, persistence, and a CLI a technical person can judge in under two minutes.