Introduction

plotknot is a minimal, extensible narrative scripting tool for game developers. It provides a clean, Markdown-like language for writing branching stories, dialogue trees, and interactive narratives — then compiles them to engine-ready data files.

Why plotknot?

Existing narrative tools (Yarn Spinner, Ink, Loreline) each make strong choices about syntax, runtime coupling, and extensibility. plotknot takes a different approach:

  • Minimal core. The base language covers 80% of narrative scripting needs: sections, choices, variables, conditions, and game interop. No feature bloat.
  • Extensible at runtime. Need character portraits? Variation modes? Custom functions? The Lua runtime provides on_call, register_function, and on_line_type hooks for game integration.
  • Engine-agnostic. The compiler produces data, not code. The runtime is a thin library you drop into your engine. Today: Defold (Lua). Tomorrow: Godot, Unity, or anything else.
  • Human-readable output. Compiled files are plain Lua tables you can read, diff, and debug.

How it works

.plotknot source  →  Compiler (Nim)  →  .lua data file  →  Runtime (Lua)  →  Your game
  1. You write narrative content in .plotknot files
  2. The compiler lexes, parses, validates, and generates output
  3. The runtime loads the data and drives the story at game time
  4. Your game code calls the runtime API to advance dialogue and respond to choices

Philosophy

  • Data over code. Compiled output is a data description of your story, not executable logic. The runtime interprets it.
  • The runtime is the extension point. The compiler produces data; the runtime provides hooks for custom functions, call handlers, and line types.
  • No hidden state. Variables, visited sections, and story position are explicit and inspectable.

Feature overview

Feature Description
Sections Organize narrative into named nodes with headings
Choices Branching with optional conditions
Variables Set and use variables with expressions
Conditions if/else blocks for dynamic content
Game interop Call game functions, receive results
Localization Tag lines with localization keys
Extensibility Runtime hooks: on_call, register_function, on_line_type
LSP Language server for editor integration
CLI Compile, validate, and watch commands

Next steps