Table of Contents

Project configuration

A dialogue.toml file configures how DialogueDown compiles the scripts in your project — the speakers your dialogue uses (and which one is the default), the compilation mode, and how unmodeled Markdown is handled. It sits at your project root, and the ddown CLI finds it automatically, so your scripts stay free of project-wide setup.

Note

DialogueDown is in early development. Configuration currently covers speakers, the compilation mode, and unmodeled-Markdown handling; more knobs (documented in the design notes) will follow.

Table of contents

Where the file lives

Put a dialogue.toml at your project root — the folder your scripts live under:

my-game/
  dialogue.toml
  dialogues/
    act1/
      intro.dialogue.md

The CLI discovers it by walking up from a script's folder to the nearest dialogue.toml, so one file at the root serves every script beneath it — the same way tsconfig.json, .clang-format, and pyproject.toml are found. To point at a config elsewhere, pass --config.

Configuring speakers

Declare each speaker as a [[speakers]] entry:

# dialogue.toml

[[speakers]]
name    = "Narrator"     # required
id      = "narrator"     # optional stable id, referenced in a script as @narrator
default = true           # this speaker voices lines with no speaker (at most one)

[[speakers]]
name = "Alice"
id   = "A"
tags = ["main", "mood=cheerful"]
Key Required Meaning
name yes The speaker's display name; must be non-empty.
id no A stable @id a script can reference instead of the name.
default no true marks the document's default speaker; at most one may set it.
tags no Content tags for the speaker (see Tags).

A configured speaker behaves exactly like one declared in a script: the two unify when they share a name, so Alice: Hi. in a script and the Alice entry above are one speaker.

The default speaker

When a line has no speaker prefix, it belongs to the default speaker. A script can name its own default with the ##default tag; when it does not, the speaker you mark default = true in dialogue.toml fills those lines instead of the built-in anonymous fallback.

Precedence, highest first:

  1. A script's own in-file ##default.
  2. The configured default = true speaker.
  3. The anonymous fallback (no configuration, no in-file default).

Tags

The tags array accepts the same tags a script uses. Each entry is either a plain name or a name=value pair:

tags = ["main", "mood=cheerful"]

For a tag whose name itself contains =, use an inline table:

tags = [{ name = "quest=intro", value = "started" }]

Compilation mode

A top-level mode key chooses how far a compile proceeds after an error:

# dialogue.toml
mode = "best-effort"
Value Behavior
stage-boundary Recover within a stage and report every error it finds, then stop at the stage boundary. The default when the key is unset.
best-effort Recover through every stage and collect everything, for the fullest picture.

The CLI's --mode option overrides the configured mode for a single run, so the order of precedence is --mode > dialogue.toml > the default. For the rationale — and why the fail-fast mode is an embedding contract rather than a settable value — see the Compilation Mode Configuration design note.

Unmodeled Markdown

Your scripts are Markdown, but DialogueDown only models the constructs dialogue uses — headings, paragraphs, lists, links, images, code spans, emphasis, and line breaks. Every other construct is unmodeled, and you choose what becomes of each one:

Handling Meaning
keep The construct's source text becomes dialogue text, exactly as written.
ignore The construct is left out of the dialogue entirely, like a comment.

Keeping a construct keeps its text, not its structure: a kept table becomes the characters you typed, pipes and all — DialogueDown does not read it as a table, because it does not model one.

The defaults ignore authoring aids and keep anything that might be content:

Construct Example Default Why
code-block a fenced ```mermaid block ignore Diagrams and code illustrate; they are not dialogue.
thematic-break --- ignore A visual divider, not words.
table \| Speaker \| Mood \| ignore Organizes reference data; not dialogue.
raw-html <div>, <br> keep Ambiguous — you typed it deliberately.
autolink <https://example.com> keep A URL that is content.
other anything else unmodeled keep Kept rather than silently lost.

Override any of them under [markdown.unmodeled]:

# dialogue.toml

[markdown.unmodeled]
table      = "keep"     # this project writes dialogue in tables
code-block = "ignore"

Only the constructs you name change. Every key you leave out keeps its default, so the section is a short list of exceptions rather than a full replacement. An unknown construct name or handling value is a configuration error, reported with its file, line, and column.

Note

Comments are always ignored, and are not part of this setting.

For the rationale and the full model, see the Unmodeled Markdown Handling design note.

Using it with the CLI

Both commands pick up the configuration automatically:

# Discovers the nearest dialogue.toml walking up from the script's folder.
ddown compile dialogues/act1/intro.dialogue.md
ddown visualize dialogues/act1/intro.dialogue.md

Use --config to name a specific file, overriding discovery:

ddown compile intro.dialogue.md --config config/dialogue.toml
Option Behavior
(none) Discover the nearest dialogue.toml from the script's folder upward.
--config <path> Use exactly this file; a missing path is a usage error.
--mode <mode> Override the configured mode for this run.
Note

For visualize, discovery stays within --root (the served folder), so a report never reads a config outside what you chose to serve. A malformed dialogue.toml is reported with its file, line, and column.

Autocompletion in the report

Because configured speakers are part of the compiled model, the interactive visualize report knows them: the source editor autocompletes your configured speakers — including ones you have declared in dialogue.toml but not yet used in the script — alongside the speakers, @ids, and tags the script itself introduces.