Skip to content
Development
Skill

/dialogue-systems

Build branching dialogue and narrative — a node/choice graph with conditions, variables, and localization hooks — and choose between authoring tools Ink and Yarn Spinner or a custom data-driven runner. Engine-neutral. Use when the user mentions dialogue system, branching

From plugin
awesome-gamedev-agent-skills
45567 skills
Install
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill dialogue-systems --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/dialogue-systems

Context preview

The summary Claude sees to decide when to auto-load this skill.

Build branching dialogue and narrative — a node/choice graph with conditions, variables, and localization hooks — and choose between authoring tools Ink and Yarn Spinner or a custom data-driven runner. Engine-neutral. Use when the user mentions dialogue system, branching

SKILL.md

dialogue-systems.SKILL.md
name: dialogue-systems
description: >
  Build branching dialogue and narrative — a node/choice graph with conditions,
  variables, and localization hooks — and choose between authoring tools Ink and
  Yarn Spinner or a custom data-driven runner. Engine-neutral. Use when the user
  mentions dialogue system, branching dialogue, conversation tree, choices,
  Ink (.ink), Yarn Spinner (.yarn), or NPC dialogue.

Dialogue systems

Model conversations as a **graph**: nodes hold lines, choices branch the flow, conditions gate options, and variables remember what the player did. The first real decision is *build vs. buy* — adopt a proven authoring tool (**Ink** or **Yarn Spinner**) or write a small data-driven runner. This skill owns both Ink and Yarn; the `visual-novel` and `rpg` genres consume it.

When to use

  • Use to design branching conversations, choice menus, or narrative state

(flags, relationship values) that affect later dialogue.

  • Use to decide between Ink, Yarn Spinner, and a custom JSON/resource format.
  • Use to wire a dialogue script into your game loop (advance line, present

choices, run commands, resolve variables).

**When *not* to use:** for engine UI (text boxes, portraits, choice buttons), use `godot-ui-control` or the engine's UI skill. For persisting narrative variables across sessions, use `save-systems`. For data-as-resources in Godot/Unity, see `godot-resources` / `unity-scriptableobjects`.

Core workflow

1. **Choose the authoring approach.**

  • **Ink** — prose-first, writer-friendly, weave/gather flow; great for

dialogue-heavy or CYOA narrative. Integrate via ink runtime / inkle plugins.

  • **Yarn Spinner** — node-based, explicit `<<commands>>`, strong for

game-driven dialogue with lots of engine hooks.

  • **Custom runner** — a JSON/resource graph + a small interpreter when you need

full control or minimal dependencies. Don't build a *language*; build a graph. 2. **Define the node contract.** A node yields one of: a line (speaker + text), a set of choices, a command/side-effect, or an end/jump. The runner advances through nodes and hands lines/choices to the UI. 3. **Separate variables from flow.** Keep a variable store (booleans, numbers, strings) the dialogue reads/writes; gate choices with conditions over it. 4. **Localize from the start.** Author with **line IDs**, not raw strings, so the displayed text comes from a string table keyed by locale. 5. **Drive it from the game loop.** The runner is a state machine: `current` node → emit content → wait for input (continue or choice) → advance. 6. **Verify by walking branches.** Exercise each choice path; confirm conditions, variable writes, and that every branch reaches an end or a valid jump.

Patterns

1. Engine-neutral dialogue graph (data, not code)

{
  "start": "guard_intro",
  "nodes": {
    "guard_intro": {
      "speaker": "Guard", "line": "DLG_GUARD_001",
      "choices": [
        { "text": "DLG_OPT_BRIBE", "to": "bribe", "if": "gold >= 50" },
        { "text": "DLG_OPT_LEAVE", "to": "end" }
      ]
    },
    "bribe": {
      "speaker": "Guard", "line": "DLG_GUARD_BRIBED",
      "set": { "gate_open": true, "gold": "gold - 50" },
      "next": "end"
    },
    "end": { "end": true }
  }
}

`line`/`text` are **string-table IDs** (localization), not literal text. `if` gates a choice; `set` mutates the variable store. The full interpreter that walks this graph is in `references/runner.md`.

2. Runner step (a state machine over the graph)

# The runner holds the current node and a variable store; the UI calls advance().
func present(node):
    if node.has("line"):
        ui.show_line(node.speaker, localize(node.line))
    if node.has("choices"):
        var shown = node.choices.filter(func(c): return eval_cond(c.get("if", "")))
        ui.show_choices(shown)            # only choices whose condition passes

func choose(choice):                       # called when the player clicks a choice
    apply_set(choice.get("set", {}))       # write variables
    goto(choice.to)

func goto(id):
    current = graph.nodes[id]
    apply_set(current.get("set", {}))
    if current.get("end", false): ui.close(); return
    present(current)
    if current.has("next") and not current.has("choices"):
        goto(current.next)                 # auto-advance linear nodes

3. Ink — branching with knots, choices, and variables (inkle)

// Ink: '*' = once-only choice, '+' = sticky. [bracketed] text shows only in the
// choice, not the printed result. '->' diverts; '-> END' stops the flow.
VAR gold = 60

=== guard_intro ===
The guard blocks the gate.
* {gold >= 50} [Offer 50 gold]   "Here, take it."
    ~ gold = gold - 50
    The guard pockets it and steps aside. -> END
* [Leave]   You turn back. -> END

Ink tracks how often each knot was seen, so `{visited_knot}` is a built-in condition. Variables are global (`VAR`) or temporary (`~ temp`).

4. Yarn Spinner — nodes, options, and commands (Yarn 2.x)

title: GuardIntro
---
<<declare $gold = 60>>
Guard: You can't pass.
-> Offer 50 gold <<if $gold >= 50>>
    <<set $gold = $gold - 50>>
    Guard: ...fine. Go on through.
    <<set $gate_open to true>>
-> Leave
    Guard: Good choice.
===

Yarn lines may start with `Speaker:`; options use `->`; `<<set>>`/`<<declare>>` manage `$variables`; `<<if>>` gates an option; `<<jump NodeName>>` moves between nodes. Interpolate values in text with `{$gold}`.

Pitfalls

  • **Hardcoding display strings** instead of line IDs makes localization a

rewrite. Author against a string table from day one.

  • **Inventing a scripting language** for a simple branching tree. If you only

need lines + choices + flags, a JSON/resource graph plus a 50-line runner beats a parser you must maintain. Use Ink/Yarn when writers need real flow control.

  • **Variables coupled to the UI**: store narrative state separately so the same

dialogue wo

Read more
Ships withawesome-gamedev-agent-skills

<img src="docs/assets/banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.

Get the whole plugin
Stats
458
Stars
36
Forks
Active
Maintenance
Python
Language
Apache-2.0
License
1d ago
Last commit
1mo ago
Created

Repo: gamedev-skills/awesome-gamedev-agent-skills