I'm always excited to take on new projects and collaborate with innovative minds.

Email

joshuerubio@gmail.com

Social

View on GitHub

Teller Framework - AI Story Bible

A directory of markdown files that lets any AI with file access write consistent, canon-accurate fiction across sessions, projects and models. No memory, no plugins, no special setup.

Role

Design & Development

Stack

Markdown, YAML, Claude Code

Type

Writing automation

Status

Actively used
Teller Framework
1. Overview

The structure of the files tells the AI what to load. Teller is a story bible built from plain markdown. Each concept lives in its own file, called a node, and declares which other files must be loaded with it. Any AI that can read files can then work on a long story with precision, without relying on memory.

It is the evolution of my Teller UX/UI case study: the same problem, context-aware AI for fiction writers, solved this time as an engine instead of an interface. I built it for my own long-form universe, which today spans two books and more than 115 tracked chapters.

⚠️ The Problem

A long story outgrows any context window, and chat memory drifts. Characters change their voice between sessions, a rule of the world is quietly contradicted, and every new session starts by pasting the same background again.

  • Loading everything is noisy and expensive, and more context also means more chances to contradict it
  • Loading too little breaks continuity across chapters
  • Relying on the model to remember fails across sessions and across models
2. Why Not the Alternatives
ApproachWhat goes wrong
Paste the whole bibleNoise, cost and contradictions grow with the story.
Rely on chat memoryDrift between sessions and models; nothing is auditable.
Plugins or a vector storeExtra infrastructure, fuzzy retrieval and files nobody can read or diff.
Teller: files that declare their dependenciesExact, portable, human-readable and versioned in git.
✓ The Idea

A node knows its own dependencies. When the AI opens a character, that node already declares which system, world and voice files come along, so nothing important is forgotten and nothing else is loaded.

01
REQUEST
What the writer asks
02
BUNDLE
Task preset
03
NODES
Load only what is needed
04
CLOSE
Update the canon
3. Core Concepts
ConceptWhat it is
NodeOne concept per markdown file, with YAML frontmatter: id, type, project, module, tags, relations, load-with and updated.
ModuleA category folder inside a project: characters, world, system, plot, relations, voice, themes, bestiary and chapters.
BundleA task preset that says which nodes an AI task loads: write, plan, edit, continuity check, update nodes, develop and dashboard.
load-withThe frontmatter field where a node declares its own dependencies. The key to precision.
state.mdPer-project file that tracks the current position, the last chapter written and the plan for the next one.
Chapters indexOne row per chapter with its number, title, point of view, key characters and a one-line summary.
Example node with load-with
A node declaring its dependencies
Teller data model
Data model: nodes, modules, bundles and project state
4. Architecture

Three layers keep the framework separate from the story it serves.

  • Agent instructions: A short root file that acts as a router, the agent specification, and five slash commands. It is the only thing the AI reads automatically.

  • Framework: Bundles, node templates and the path conventions. It contains no story data.

  • Project data: One folder per project with its state, index and module folders. Planning notes and spin-off pitches live outside the projects, so they are never loaded while writing.

How a request flows through Teller
How a request flows through the framework
Repository structure
Framework and project data side by side
5. Keeping the Context Small

The whole design is a set of rules about what not to load.

  • Session start: Only each project's state file is read, never the full bible.

  • Writing default: A chapter is written with the state file and the voice guide, and nothing else loads automatically.

  • Demand-driven nodes: A node loads only if the writer names it, the scene requires it and the agent asks, or the writer asks mid-scene.

  • Depth capped: Dependencies are followed one level deep. Excess context is treated as noise.

  • Per-task bundles: Planning at chapter level loads arcs, state and conflicts only, and editing loads only the relevant book's voice section.

A request resolving through bundle and load-with
Resolving a request: bundle, named nodes, then one level of load-with (file counts are illustrative)
6. The Session Lifecycle

A session opens in Claude Code at the repository root. The agent reads the project states and greets the writer, unprompted, with a table of projects, the available actions and the next step. The writer then writes, plans, edits or runs a continuity check, and every finished chapter ends with a prompt to close the session.

Closing a session

The close command runs nine steps and asks for confirmation before every write: it stops if there are unresolved continuity flags, proposes the new state and the new chapter-index row, updates the story structure only if arcs moved, offers a canon update, detects the end of a book, and finally proposes a commit message before committing and pushing. Nothing is applied without approval.

Session lifecycle
From opening a session to the gated close
Commands reference
Actions and commands, and what each one loads and touches
7. Features in Depth

What follows is how each feature feels in a real session. The conversations replay as you scroll, and they are illustrative: the commands, prompts and output formats are the real ones, while the story content is placeholder and not taken from my manuscripts.

Continuity checking: flags, never rewrites

The bundle loads the arcs, the relationships, the rules of the world and the characters present in the scene, then compares the chapter against them. It only raises flags, and the session cannot close while one is unresolved.

claude · teller · continuity-check
you ›   verifica continuidad del cap 12
agent › Loading arcs, conflicts, system rules and the 3 characters in the scene...
⚑     "Ada lit the lamp with her bare hand" contradicts [characters/ada: canonical gestures]
     reason: she never touches a flame directly
⚑     "The tide rose at noon" contradicts [world/tides: rules]
     reason: tides only rise at dusk
agent › 2 flags. Nothing was rewritten. /session-close stays blocked until both are resolved.
Canon updates as a reviewed diff

Closing a session walks through gated steps, and each write needs a yes. The canon is updated as a list of proposed changes that the writer approves or rejects one by one.

claude · teller · /session-close
you ›   /session-close 12
agent › Any open continuity flags?
you ›   resolved
agent › Proposed state.md update: last written -> cap 12, next -> cap 13. Apply?
you ›   yes
✓     state.md updated
agent › Proposed canon changes (update-nodes):
     1. characters/ada > Personality > now distrusts the harbour master (cap 12)
     2. world/lighthouse > Canon details > the east lamp is broken (cap 12)
you ›   approve 1, reject 2
✓     1 applied, 1 skipped. Nothing else was touched.
Editing without side effects

Editing an old chapter is deliberately isolated. It never touches the project state and never suggests closing the session, so a late fix cannot corrupt the active progress.

claude · teller · edit
you ›   edita el cap 4
agent › Chapter 4 belongs to Book 1 (found through chapters/index.md).
     loading: Book 1 voice, the characters in the scene, the manuscript
✓     edit applied to the manuscript
agent › The chapter summary changed. Update its row in chapters/index.md?
you ›   yes
✓     index row updated
     state.md untouched. No /session-close suggested for a past edit.
Planning at the right granularity

There are no separate commands for planning levels. The bundle reads the phrasing and decides whether it is looking at a chapter, a batch, an arc, a book or a single event.

claude · teller · plan
you ›   planifiquemos el cap 13
agent › Level: chapter -> beat sheet
you ›   planifiquemos el arco 2
agent › Level: arc -> dramatic question and three acts
you ›   planifiquemos el libro 2
agent › Level: book -> structural skeleton only
you ›   que sigue?
agent › Ambiguous. Default: the next 3 chapters from state.md, as a flow table.
Multiple books, one universe

A new book versions only the voice, the themes and the plot. The world, the system and the characters stay shared, and existing content is wrapped, never overwritten. A spin-off goes further and declares its parent, so shared characters and world load only when a scene requires them.

claude · teller · /new-book 2
you ›   /new-book 2
agent › Six steps, each one confirmed before writing. First: voice, rhythm and themes for Book 2?
✓     voice/style.md: "## Book 2" added, Book 1 preserved
✓     themes/writing-rules.md: same treatment
✓     plot/arcs-book2.md created
✓     state.md: active-libro set to 2
     shared with Book 1: world, system, characters
Voice as data

Voice lives in files: a versioned style guide per book and a voice node per point-of-view character, plus a list of patterns to eliminate. Writing loads almost nothing by default and pulls a node in only when the scene needs it.

claude · teller · write
you ›   escribe el cap 13
agent › Loading state.md and voice/style.md.
     nothing else loads automatically
agent › The scene is from Ada's point of view. Load voice/pov-ada?
you ›   yes
agent › Ada's node declares load-with: world/lighthouse, system/rules. Following one level deep.
✓     drafting in Ada's voice. Canon gaps are flagged, never invented.
8. Decision Records
Plain files instead of a database or plugin

Files are portable, diffable in git (every session ends in a commit) and readable by both people and any AI. The trade-off is that there is no query engine, so integrity depends on conventions and on the agent following them.

Dependencies declared by the node, not the caller

Bundles stay short and dependencies are not forgotten, because the file that needs a dependency is the one that names it. Retrieval is exact rather than semantic, and capped at one level.

Human in the loop

Agents read freely, propose changes as structured diffs and never apply them without approval. There are no parallel writes and no shared memory between agents.

Model-agnostic in principle, Claude Code in practice

Any AI with file access can navigate the structure, while the shipped orchestration (the auto-read instructions and the slash commands) targets Claude Code.

9. How It Evolved

Most of the design came from friction, and the commit history shows it: the always-loaded instruction file was slimmed down to a minimal router, node loading moved from preloading to on-demand, multi-project support arrived as a refactor with the parent-project pattern, and a structural map of book, arc and chapter was added when the index and the arcs drifted apart. Seventy-five commits in about seven weeks, part of them produced through parallel Claude Code worktrees.

170+

files tracked

2

projects

10

bundle files

5

slash commands

115+

chapters tracked

Key Takeaways
  • Structure beats memory: Making the dependencies explicit worked better than hoping the model would remember them.
  • What not to load is the real design: Every rule that keeps context small also removed a source of contradictions.
  • Confirmation gates build trust: Because nothing is applied without approval, the canon can be trusted after months of sessions.
  • Conventions need care: Without a query engine, documentation can drift from behaviour, as my own notes show, so keeping the docs in sync is part of the work.

Next steps: Measure the effect on consistency more rigorously, for example by counting the canon flags caught per chapter, and reconcile the remaining documentation drift.