Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pompom454/tea/llms.txt

Use this file to discover all available pages before exploring further.

TwineScript is Tea’s scripting language — essentially JavaScript with a layer of syntax sugar to make it more approachable for authors who are not JavaScript developers. You write TwineScript inside macros such as <<set>>, <<if>>, <<for>>, and <<print>>, and it gives you full access to variables, expressions, and the complete JavaScript standard library.

Variables

A variable is a named storage location for a value. Tea has two kinds of variables: story variables and temporary variables.
  • Story variables (sigil: $) are part of the story history and persist for the lifetime of a playthrough session. They are saved and restored along with saves.
  • Temporary variables (sigil: _) do not enter the story history and only exist for the current moment/turn. They are ideal for loop counters and intermediate calculations.
Temporary variables were added in v2.3.0.

Variable name rules

PositionAllowed characters
First character (after sigil)A–Z, a–z, $, _
Subsequent charactersA–Z, a–z, 0–9, $, _
/* Valid story variable names */
$cash
$hasKeyCard5
$met_alice
$TIMES_POKED_MR_BEAR

/* Valid temporary variable names */
_i
_something2
_some_loop_value
_COUNT

Using variables

Use the <<set>> macro or setter links to assign values to variables.
<<set $name to "Elara">>
<<set $gold += 50>>
[[Buy sword|Market][$gold to $gold - 30]]
Use naked variable markup for simple values, or a print macro for expressions.
/* Naked markup — works for simple lookups */
Your name is $name and you have $gold gold.

/* Print macros — needed for expressions and method calls */
You have <<= $inventory.length>> items.
<<print $name.toUpperCase()>>
Use <<if>> and <<switch>> to control story flow based on variable values.
<<if $gold gte 30>>
  You can afford the sword.
<<else>>
  You cannot afford the sword.
<</if>>

Other places to store values

In addition to $ and _ variables, Tea provides two non-persistent storage locations:
  • setup — an object provided by Tea for storing non-persistent values that should not enter the history (e.g., lookup tables, configuration data).
  • window — the browser’s global object. Properties on window become auto-globals, but take care not to overwrite any of its many built-in properties.

Supported types

The following types may be safely stored in Tea’s story and temporary variables.

Primitive types

  • Booleantrue and false
  • Number — integers (42, -24), floating-point (3.14, -17.76), and special values (Infinity, NaN)
  • String"I like pie", 'You like pie'
  • null
  • undefined

Object types

  • Array
  • Date
  • Map
  • Set
  • Generic objects ({})
Any supported object type may contain any other supported primitive or object type.
The following constructs are not supported inside story variables:
  • Circular references — keep them in setup or window instead.
  • Property attributes (getters/setters) and symbol properties — use a class to encapsulate them.
  • Functions and static methods — a function’s scope cannot be restored from saves, and function behavior is immutable, making storage wasteful. Instance methods of classes are unaffected because they live on the prototype, not in the variable.
Custom object types (classes) can be made compatible with Tea’s serialization by implementing .clone() and .toJSON() methods. See the Non-generic object types guide for details.

Expressions

An expression is any unit of code that yields a value when evaluated.
// Yields: true
true

// Yields: 1 (on the first turn)
turns()

// Yields: 4
2 + 2

// Yields: "22" (string concatenation)
"2" + "2"
Expressions may have side effects — they modify some state as part of their evaluation:
// Yields: 5; side effect: assigns 5 to $a
$a = 5

// Yields: 25 (assuming $x is 15); no side effect
$x + 10
Common expression categories:
  • Arithmetic — yields a number, e.g., 42 or $x + 10
  • String — yields a string, e.g., "Lulamoon" or $first + " " + $last
  • Logical — yields a boolean, e.g., $health gt 0
  • Assignment — causes a value to be stored, e.g., $a = 5

Operators

Assignment operators

Use these to store values in variables. TwineScript provides the to keyword as a readable alternative to =.
OperatorDescriptionExample
toAssigns the right-hand value to the left-hand variable$apples to 6

Conditional (comparison) operators

OperatorDescriptionExample
isStrictly equal$bullets is 6
isnotStrictly not equal$pie isnot "cherry"
eqEquivalent (coercive) — prefer is$bullets eq 6
neqNot equivalent (coercive) — prefer isnot$pie neq "cherry"
gtGreater than$cash gt 5
gteGreater than or equal to$foundStars gte $neededStars
ltLess than$shoeCount lt ($peopleCount * 2)
lteLess than or equal to$level lte 30
notLogical NOTnot $hungry
andLogical AND$age gte 20 and $age lte 30
orLogical OR$friend is "Sue" or $friend is "Dan"
defTrue if the right side is defineddef $mushrooms
ndefTrue if the right side is not definedndef $bottlecaps
The def and ndef operators have very low precedence. When mixing them with other operators, always wrap them in parentheses to avoid unexpected evaluation order — e.g., (def $style) and ($style is "girly").

Unary operators

Unary operators take a single operand, either before or after them.
// Postfix increment (operand then operator)
$i++

// Prefix increment (operator then operand)
++$x

// Logical NOT — TwineScript style
not $hasKey

// Logical NOT — JavaScript style
!$hasKey

Practical examples

/* Initialize variables at story start (in StoryInit) */
<<set $playerName to "Elara">>
<<set $gold to 100>>
<<set $inventory to []>>
<<set $visited to {}>>

/* Conditional branching */
<<if $gold gte 50 and not $visited.market>>
  <<set $visited.market to true>>
  You enter the market for the first time.
<<elseif $gold lt 10>>
  You can barely afford anything here.
<<else>>
  The market stalls are familiar by now.
<</if>>

/* Loop with a temporary variable */
<<for _i to 0; _i lt $inventory.length; _i++>>
  Item <<= _i + 1>>: <<= $inventory[_i]>>
<</for>>

Build docs developers (and LLMs) love