AI-powered solo play companion. Manages characters, party, session state, and lore. Expands scenes, NPCs, and locations using a local LLM. Integrates with Foundry VTT for maps and tokens, and an Obsidian vault for canon lore.
- Old-School Essentials (OSE) — premium + Carcass Crawler
- Dungeon Crawl Classics (DCC)
- Stars Without Number / Worlds Without Number (SWN/WWN)
- For Gold & Glory (FGG)
- Advanced Roleplay System (ARS)
- OSRIC 3.0 (planned, pending release)
browser (Foundry VTT + sanctum module)
↕ HTTP / WebSocket
backend (FastAPI on tower.local:8000)
├── Ollama (local LLaMA — tower.local:11434)
└── Obsidian vault (markdown on disk)
cd backend
cp .env.example .env # edit paths and model name
pip install .
uvicorn main:app --reload # devOr with Docker:
cp backend/.env.example backend/.env
docker compose up --buildCopy foundry-module/ into your Foundry Data/modules/sanctum/ directory, then enable it in your world's module settings.
Configure the API URL under Game Settings → Module Settings → Sanctum.
Copy vault-template/ to your preferred location and open it in Obsidian. Set VAULT_PATH in backend/.env to point to the live vault.
The AI is a bounded tool, not a GM oracle. It:
- Expands flavor text within the active system's tone and setting
- Answers rules questions with caveats when uncertain
- Writes lore notes flagged
pending_review: trueuntil you approve them
Fate rolls, outcomes, and oracle decisions remain with the player.
GET /health— liveness checkPOST /ai/expand/scene— scene description expansionPOST /ai/expand/npc— NPC portrait + dialogPOST /ai/expand/location— location GM notePOST /ai/query— freeform query with system contextGET /ai/models— list available Ollama modelsGET /lore/notes— list vault notesGET /lore/notes/{path}— read a notePUT /lore/notes/{path}— write a noteGET /lore/search?q=— search vaultPOST /lore/generate— AI-generate a lore notePOST /rules/roll— roll dice (XdY+Z notation)GET /rules/systems— list systemsPOST /rules/query— rules questionPOST /session/start— start sessionGET /session/current— current session stateGET /session/party— party characters
Full interactive docs: http://localhost:8000/docs