D20 Companion
A Flutter desktop application for tabletop RPG game masters, built by two people through LLM-assisted development, almost entirely on a shared $200-a-month subscription. The repository is private. A demo is available on request.
I bring twenty-some years of running tabletop games to the design, and I own feature design, technical architecture, all data work, and the instructional scaffolding that tells agents how to work in the repo. My partner handles UI refinement, removing slop, and generating art for every SRD entity.
Shipped. A compendium covering species, classes, backgrounds, feats, spells, items, monsters, and maps and handouts. Characters. A set of tools: session planner, NPC generator, encounter builder, loot generator, dice roller, DM screen, dungeon generator, escape-route generator, ambience audio, map manager.
In progress. A campaign manager with dashboard, world, characters, and plot views, including a locations hierarchy that carries player-safe versus DM-only visibility, travel routes, power blocs, and lore.
The end point. The app becomes a harness where every user-facing tool is also an agent tool, so an LLM storyteller can create campaigns and run games itself.
The data layer
I converted SRD 5.2.1, hundreds of pages published in English, Spanish, German, French, and Italian, into structured files and then a queryable database across all five languages. About 150 hours over five to six weeks, and four attempts.Attempts two and three failed because an earlier attempt's output was still sitting in the repository. The agents locked onto it as the reference for dozens of hours, despite instructions that contradicted its scope. Stale artifacts are a stronger signal to an agent than the prompt. The fourth attempt worked by converting in small pieces to JSON with automated review after each piece.
The agentic development pipeline
Humans decide what the product should be. Agents decompose, implement, test, document, review, and integrate it through an auditable, local-first pipeline. The rules:
- A broad feature request becomes small, independently reviewable tasks. Each owns one coherent behaviour, contract, interaction, screen, or component.
- Product intent and accepted design decisions are written down, so later agents do not reconstruct them from memory.
- Work runs in dedicated local branches and worktrees. Temporary task branches are never pushed.
- Agents make reasonable technical decisions without asking permission each time. Behaviour changes get meaningful tests, red-green-refactor where it fits.
- Every submission launches exactly one fresh reviewer, and the reviewer is diagnostic only. It inspects the full change, call paths, tests, security, persistence, documentation, and acceptance criteria, then approves or rejects with every material blocker listed. It does not repair the work.Reviews are non-mutating on purpose. A single implementer keeps its context and iterates against feedback, instead of a fresh agent being spawned for every fix and losing the thread. Rejections go back to the implementer.
- Approval happens in a clean review worktree. A wrapper merges, pushes, verifies remote ancestry, records proof, and closes the task.
- For UI and UX there is an additional human gate. Approval is tied to an exact commit, a person tests that exact candidate, and any later change invalidates the approval and restarts review.
- Local first. No cloud CI.
I can set up a version of this for a small team, including the review gates and the written product record. See working with me.
Planned: a model-routing evaluation
An open evaluation harness measuring which models handle which D20 Companion tasks, at what cost and reliability. Automated graders wherever ground truth is programmatic: schema validity, challenge-rating arithmetic, constraint satisfaction, retrieval hit rate. One evaluation targets player-safe versus DM-only leakage: does a model disclose a secret when the only thing stopping it is an instruction? Seeded canaries, fuzzy matching, and an independent entailment check.
Constraint: a single RTX 3090 and zero paid API spend. Deliverable: a routing table recommending a model per task, with the measured trade-off that justifies each row.