Skip to main content

Engine tools and instructions

·595 words·3 mins
chronicler - This article is part of a series.
Part 5: This Article

Tools
#

To keep things fair and interesting, Claude calls the following Python scripts over MCP. They’re grouped by what they touch.

Campaign / session
#

Lifecycle commands — spinning up campaigns, archiving them, and feeding the dashboard.

  • campaign_mgmt.py — create, list, switch, inspect campaigns; add characters
  • campaign_archive.py — export/import a campaign as a single tarball
  • dm_session.py — headless claude -p driver for the dashboard’s /play surface
  • export_session.py — export a Claude Code session JSONL transcript as markdown
  • audit.py — scan events.json for procedural lapses (missed reactions/morale/surprise)
  • log.py — chronicle notes, calendar/time advancement

Combat & dice
#

Mechanics — initiative, dice, conditions, and the DungML-driven tactical grid.

  • combat.py — initiative, attacks, HP, spell declaration, conditions, effects
  • combat_map.py — DungML renderer, grid state, combatant positioning
  • dice.py — roll, reaction, morale, encounter, saves, skill checks

Characters / party / NPCs
#

Character and party state — vitals, loyalty, factions, and player holdings.

  • party.py — HP, XP, spells, rest, coin
  • hirelings.py — CHA-driven loyalty checks for hirelings/henchmen
  • homebrew_classes.py — loader for global/homebrew/classes/*.json
  • factions.py — factions and world-clock countdowns
  • holdings.py — player-owned houses and mounts

World / locations / maps
#

World simulation — places, weather, travel days, and overland geography.

  • world.py — NPCs, locations, areas (markdown-backed)
  • world_map.py — Structurizr-style overland DSL → GeoJSON views
  • lore.py — search, timelines, quest threads, session primers
  • travel.py — overland day-loop chaining weather, encounters, clock ticks, rations
  • weather.py — seasonal weather tables
  • survival.py — consumable inventory, light sources, encumbrance, rations

Reference lookups
#

Read-only lookup over rulebooks, monster/spell/class data, and setting databases.

  • lookup.py — monster/spell/class lookup, treasure generation
  • rules.py — FTS5 search over PHB/DMG/MM text
  • greyhawk.py — wraps settings/greyhawk/greyhawk.db (pages, FTS, typed entries)
  • build_2e_db.py — build global/2e.db (spells + classes)
  • build_phb_ref.py — build ability_scores + proficiencies tables
  • build_rules_db.py — build the FTS5 rules index

Items / quests / rumors
#

Plot-adjacent data — quest fairness, gossip with truth tiers, and shared item weights.

  • quests.py — quests with scope/stakes and level-fairness warnings
  • rumors.py — gossip table tracking truth tier separately from what NPCs say
  • item_weights.py — shared item-weight resolution (used by dashboard + survival)

Media / misc
#

Audio, imagery, generators, and DM-only secret tracking.

  • images.py — Replicate scene + portrait generation
  • tts.py — OpenAI TTS with per-character voice mapping
  • wordlist.py — fantasy-themed random word generator
  • secrets.py — DM-only hidden facts (dm_note, dm_secrets)

Campaign state is stored as structured JSON on the file-system. Tools change state; the web UI reflects current state.

Instructions
#

Claude tends towards a certain style of adventure — world-spanning stakes and long-term adventure hooks where everything connects. At lower levels, I prefer adventures to be more straightforward. My model instructions specify:

  • Focus on simulating a world, rather than telling a story where every adventure thread is connected.
  • Fairness, avoiding the rule of cool and fudging dice-rolls in favour of the party.
  • Playing characters and monsters in line with their intelligence. Animals don’t devise clever tactics; dragons do.
  • Respecting player statistics. Characters with low charisma shouldn’t have supermodel portraits; characters with low intelligence should use simple speech.
  • Not breaking the fourth wall by sharing information player characters couldn’t know (statistics, dungeon master information…).

Sometimes it’s necessary to ask a question or nudge the engine in a certain direction. In that case, I use the ooc: (out of character) prefix. The prefix tells the engine to treat the line as meta-instruction rather than character speech — for example, ooc: skip the tavern small talk and jump to the road, or ooc: what’s the DC for this lock?. Without it, the model would route the input through whichever character I’m currently playing.

chronicler - This article is part of a series.
Part 5: This Article