Skip to content

Learning paths

Lute’s docs are organized by subject, but you probably arrived with a role in mind. Pick the path that matches what you are trying to do; each is a short, ordered reading list through pages that already exist. You can always branch off into the sidebar once a page raises a question.

You write the story — dialogue, choices, quests — and want the tool to catch your mistakes before a player does. Start here and stay in prose; the logic layer can wait.

  1. Installation — get the lute command on your PATH.
  2. Write your first scene — build one real scene from an empty file, running lute at every step, then pin it with a *.test.yaml that lute test runs.
  3. Connect scenes into a story — chain your scenes with one made-up occasion, after: and priority:, branch the endings with when:, and play the whole story with lute play; no engine needed.
  4. Build an investigation — a full worked project: facts, a quest, an interrogation hub, two traced endings, and their tests.
  5. Dialogue & cast — the @speaker line, delivery flags, and interpolation.
  6. Branch, match & when — player menus and state-driven callbacks.
  7. Choices & hubs — choice guards, the into= record sugar, and revisit hubs.
  8. Quests & scenes — objectives, after: sequencing, and lifecycle events.
  9. Tracing guide and lute test — preview a scene along a chosen path, and keep every path you care about as a test.
  10. Beats and Playing a story — when the engine picks the next piece of story by moment instead of a fixed episode order; lute init --template beats scaffolds a passing example to start from.

Keep the cheatsheet open while you write. If your editor and the terminal ever disagree about a file, trust the terminal and run lute doctor --project .: it names a stale editor language server or a mismatched toolchain.

You think about state, guards, and reachability. This path leads with the logic and analysis layers — the parts of Lute a compiler engineer will recognize.

  1. Frontmatter & profiles — the capability-selecting header every document opens with.
  2. The state model — the tiered scalar namespaces and definite-assignment rules.
  3. CEL expressions — the restricted expression profile behind every condition and assignment.
  4. Facts and Datalog — the relational fact layer and its total derivation rules.
  5. Timeline & property tracks — concurrent choreography with the one-writer-per-track rule.
  6. The scene graph and after: — the project-wide prerequisite graph.
  7. Reachability — the Reachable / Unreachable / Unknown verdicts and their honesty boundary.
  8. Guaranteed / Possible envelopes — per-node available-state analysis.

You are wiring a game engine to play what Lute compiles. Lute never runs your game — it hands you a versioned JSON IR plus CEL, and you implement the runtime contract. This path is contract-first.

  1. Runtime contract — what Lute emits and what an adapter must implement: the command loop, CEL, facts, quests, and typed bridges.
  2. Capability permissions — where compile-time authoring ceilings stop and host/runtime authorization begins.
  3. Streaming continuation compiler — replace full program snapshots while retaining the numeric cursor, state, facts, and control-flow state.
  4. docs/runtime/ on GitHub — the normative runtime specification: streaming continuations, capability permissions/security, execution model, state lifecycle, CEL & facts, quest lifecycle, timeline semantics, and bridge protocol.
  5. conformance/ on GitHub — the artifact-and-expectation fixtures your adapter should replay to prove it plays Lute correctly.
  6. CLI reference → run — lute run is the reference consumer: it executes a compiled artifact against a mock playthrough, so its transcript is the behavior your adapter must match.
  7. CEL expressions — the exact expression semantics your evaluator has to reproduce.

You extend Lute’s vocabulary — new directives, capability surfaces, typed bridges — without touching the fixed grammar or compiler. This path walks the capability model end to end.

  1. Plugin concepts — how plugins add vocabulary and capability without changing the grammar.
  2. Manifests & resolution — the package layout, export kinds, dependency graph, and capability snapshot.
  3. Profiles & activation — deterministic option layering and the distinction between activation and permission ceilings.
  4. Capability permissions — how trusted projects/hosts restrict already-resolved plugin directives, effects, and bridges.
  5. Typed bridge directives — declaring a typed runtime bridge and the state it writes.
  6. Providers and catalog — snapshot-first provider resolution and capabilitySnapshot.

You are building an authoring pipeline where a model writes Lute and the checker keeps it honest. This path centers the machine-readable surfaces.

  1. AI harness guide — wiring trusted --permission-profile, filtered lute context, lute check --json, --deny, exit codes, and fixits into a loop.
  2. Capability permissions — never let generated source choose its authority; use one host ceiling across context, check, compile, and streaming.
  3. Streaming continuation compiler — stream ordinary checked Lute body units through compile --stream without inventing a model-specific grammar.
  4. CLI reference — the full subcommand surface, --json shapes, and the exit-code contract every step keys off.
  5. Current specification — the consolidated index of what the language actually enforces today.
  6. State schemas — the shared, imported source of truth a generator must target.
  7. Build an investigation — see the check → trace → compile loop the harness automates, on a real project (including what whole-project lute check proves about relational fact guards).