Skip to content

Macros Reference

Macros are template variables written as {{macro_name}} that get replaced with dynamic content when your preset is assembled into a prompt. This is the complete reference of the built-in macros available in Lumiverse.


How to Use Macros

Place macros anywhere in preset blocks, chat-facing prompt fields, and other prompt content that goes through macro evaluation:

You are {{char}}, a character described as: {{description}}
You are speaking with {{user}}.
{{persona}}

During prompt assembly, each macro is replaced with its current value.

Arguments

Some macros accept arguments, separated by :: (double colon) or spaces:

{{random::1::100}}          — random number between 1 and 100
{{pick::cat::dog::bird}}    — randomly selects one item
{{roll::2d6}}               — rolls two six-sided dice

Space-delimited arguments are also supported — each word becomes a separate argument:

{{upper hello}}             — same as {{upper::hello}}
{{setvar key value}}        — same as {{setvar::key::value}}
{{abs -5}}                  — same as {{abs::-5}}

When to use :: vs spaces

Use spaces for quick single-word arguments: {{upper hello}}, {{floor 3.7}}. Use :: when an argument contains spaces: {{replace::hello world::goodbye world::text}}. You can mix both: {{setvar key::long value with spaces}}.

Variable Shorthand

Access variables directly with . (local), $ (global), or @ (chat-persisted) prefixes:

{{.myVar}}                  — same as {{getvar::myVar}}
{{$theme}}                  — same as {{getgvar::theme}}
{{@hp}}                     — same as {{getchatvar::hp}}
{{.score = 100}}            — same as {{setvar::score::100}}
{{@hp = 100}}               — same as {{setchatvar::hp::100}}
{{.hp -= 25}}               — subtract 25 from hp
{{.counter++}}              — increment by 1
{{@turn++}}                 — increment a persisted counter
{{.counter--}}              — decrement by 1

Variable shorthands work inside conditions too:

{{if .myVar}}has a value{{/if}}
{{if .score == 100}}perfect!{{/if}}
{{if !.gameOver}}still playing{{/if}}
{{if $theme == dark}}dark mode{{/if}}
{{if @hp > 0}}still alive{{/if}}

Scoped Macros

A few macros wrap content between opening and closing tags:

{{if::{{isGroupChat}}}}
This is a group conversation with {{group}}.
{{else}}
This is a private conversation.
{{/if}}

Prefixes & Scoped Tags

Lumiverse parses SillyTavern-style macro prefixes. The currently user-relevant ones are:

Prefix Syntax Effect
! {{!macro}} Parsed for immediate/compatibility-prefixed macros
? {{?macro}} Parsed for delayed/compatibility-prefixed macros
~ {{~macro}} Parsed for reevaluate-style compatibility
> {{>macro}} Parsed for filter-style compatibility
# {{#trim}}...{{/trim}} Preserve whitespace for macros that support it (trim is the main built-in example)

Closing scoped macros use /, like {{/if}}, {{/trim}}, or {{/numbered}}.


Core Macros

Utility macros for text manipulation and flow control.

Macro Aliases Description
{{space}} Inserts a literal space character
{{newline}} {{nl}}, {{n}} Inserts a literal newline
{{noop}} No operation — resolves to nothing
{{trim}}...{{/trim}} Trims whitespace from the enclosed content
{{comment::...}} {{note::...}} Comment — content is discarded, produces no output
{{// comment text}} Inline comment shorthand
{{input}} The raw text of the last user message
{{reverse::text}} Reverses the given text
{{outlet::name}} Resolves the content exported by an active world-info entry outlet
{{banned}} Placeholder for banned token lists

Conditional Logic

{{if::condition}}
  Content when true
{{else}}
  Content when false
{{/if}}

The condition can be any value — it's truthy unless it's empty, "0", "false", "null", or "undefined".

Only the selected branch is resolved. Side-effect macros in the unselected branch do not run.

Negation — prefix with ! to invert:

{{if::!0}}yes{{/if}}                — "yes" (0 is falsy, negated → truthy)
{{if::!{{hasvar::key}}}}missing{{/if}}

Comparisons — use ==, !=, >, <, >=, <= inside the condition:

{{if::{{messageCount}} > 10}}long chat{{/if}}
{{if::{{.score}} == 100}}perfect!{{/if}}

Variable shorthand.var, $var, and @var resolve automatically in conditions:

{{if .myVar}}has a value{{/if}}
{{if .x > .y}}x is bigger{{/if}}
{{if !.gameOver}}still playing{{/if}}
{{if @hp > 0}}still alive{{/if}}

Identity & Names

Macros for character and user identity.

Macro Aliases Returns
{{user}} Your persona name (or username if no persona)
{{char}} {{charName}} The current character's name
{{group}} Comma-separated list of all group member names
{{groupNotMuted}} {{group_not_muted}} Names of non-muted group members
{{notChar}} {{not_char}} The non-character party (usually the user)
{{charGroupFocused}} {{charFocused}}, {{char_group_focused}} The targeted character in a group chat
{{isGroupChat}} {{is_group_chat}} "yes" or "no" — usable as a condition
{{groupOthers}} {{group_others}} Group members excluding the focused character
{{groupMemberCount}} {{group_member_count}} Number of characters in the group
{{groupLastSpeaker}} {{group_last_speaker}} Last character who spoke

Character Data

Macros that pull from the character card fields. These respect alternate field selections.

Macro Aliases Returns
{{description}} {{charDescription}} Character's description
{{personality}} {{charPersonality}} Character's personality
{{scenario}} {{charScenario}} Character's scenario
{{persona}} {{userPersona}} Your persona's description (includes enabled add-ons)
{{sub}} {{subjectivePronoun}}, {{personaSubjectivePronoun}} Your persona's subjective pronoun
{{obj}} {{objectivePronoun}}, {{personaObjectivePronoun}} Your persona's objective pronoun
{{poss}} {{possessivePronoun}}, {{personaPossessivePronoun}} Your persona's possessive pronoun
{{mesExamples}} {{mes_examples}}, {{exampleMessages}} Character's example dialogue
{{mesExamplesRaw}} Raw example dialogue (unprocessed)
{{system}} {{charPrompt}}, {{charSystem}} Character's system prompt
{{charPostHistoryInstructions}} {{charInstruction}}, {{jailbreak}}, {{charJailbreak}} Post-history instructions
{{charDepthPrompt}} {{depth_prompt}} Character's depth prompt (from extensions)
{{charCreatorNotes}} {{creatorNotes}} Creator's notes (informational)
{{charVersion}} Character card version
{{charCreator}} Character creator's name
{{firstMessage}} {{firstMes}}, {{first_message}} Character's first/greeting message
{{original}} Character description (original card text)

Chat & Conversation

Macros for the current chat state.

Macro Aliases Returns
{{lastMessage}} {{last_message}} Content of the most recent message
{{lastMessageId}} {{last_message_id}} Index of the last message
{{lastUserMessage}} {{last_user_message}} Content of the last message from you
{{lastCharMessage}} {{last_char_message}}, {{lastBotMessage}} Content of the last character message
{{lastMessageName}} Name of whoever sent the last message
{{messageCount}} {{message_count}}, {{messagecount}} Total message count in the chat
{{chatId}} {{chat_id}} The current chat's unique ID
{{firstIncludedMessageId}} Index of the first message included in the prompt
{{firstDisplayedMessageId}} Index of the first displayed message
{{lastSwipeId}} Index of the last swipe on the final message
{{currentSwipeId}} Index of the active swipe

Time & Date

Macros for current time information.

Macro Aliases Returns Args
{{time}} Current time (HH:MM) Optional: UTC offset (e.g., {{time::UTC+2}})
{{date}} Current date (Month Day, Year)
{{weekday}} Day of the week
{{isotime}} ISO 8601 date and time
{{isodate}} ISO date (YYYY-MM-DD)
{{datetimeformat::...}} Custom formatted date/time Intl.DateTimeFormat options as key=value
{{idleDuration}} {{idle_duration}} Human-readable time since last message
{{timeDiff::date1::date2}} {{time_diff}} Human-readable difference between two dates Two ISO date strings (second defaults to now)

Examples:

It is currently {{time}} on {{weekday}}, {{date}}.
The user has been idle for {{idleDuration}}.

Random & Entropy

Macros for randomness and dice rolling.

Macro Returns Args
{{random::min::max}} Random integer between min and max Two numbers separated by ::, or a list of items
{{pick::item1::item2::...}} One randomly chosen item List of options separated by ::
{{roll::NdS}} Dice roll total Dice notation (e.g., 2d6, 1d20, 3d8)

Examples:

{{char}} rolls a {{roll::1d20}} on their perception check.
The weather today is {{pick::sunny::cloudy::rainy::stormy}}.
A random number: {{random::1::100}}

String Manipulation

Transform, measure, and extract from text.

Macro Aliases Returns Args
{{len::text}} {{length}} Character count Text (or scoped: {{len}}text{{/len}})
{{upper::text}} {{uppercase}}, {{toUpper}} Uppercased text Text (or scoped)
{{lower::text}} {{lowercase}}, {{toLower}} Lowercased text Text (or scoped)
{{capitalize::text}} {{titlecase}} First letter capitalized Text (or scoped)
{{replace::find::with::text}} Text with replacements Find, replacement, source (or scoped body)
{{substr::text::start::end}} {{substring}} Substring Source, start index, optional end index
{{split::text::delimiter::index}} Nth item from split Source, delimiter, 0-based index (negative from end)
{{join::sep::a::b::...}} Joined string Separator, then items
{{repeat::N::text}} Repeated text Count (max 1000), text (or scoped)
{{wrap::prefix::suffix::text}} Wrapped text (empty if text is empty) Prefix, suffix, text (or scoped)
{{regex::pattern::replacement::text}} Regex-replaced text Pattern, replacement, text (or scoped), optional flags
{{tokenCount::text}} {{token_count}}, {{tokens}} Approximate token count Text (or scoped)
{{truncate::text::maxTokens}} Truncated text (word-boundary, adds ...) Text, max tokens

Examples:

{{upper::{{char}}}}                     — "BOB"
{{len::{{description}}}}                — "234" (character count)
{{replace::they::she::{{persona}}}}     — pronoun swap
{{split::{{charTags}}::,::0}}           — first tag
{{join::, ::{{char}}::{{user}}}}        — "Bob, Alice"
{{repeat::3}}---{{newline}}{{/repeat}}  — three separator lines
{{wrap::(**::**)::{{.note}}}}           — "(**important**)" or "" if empty
{{regex::\b(he|him)\b::she/her::{{description}}}}

Math

Arithmetic without intermediate variable gymnastics.

Macro Aliases Returns Args
{{calc::expression}} {{math}}, {{evaluate}} Result of + - * / % () Expression string
{{min::a::b::...}} Smallest number Two or more numbers
{{max::a::b::...}} Largest number Two or more numbers
{{clamp::value::min::max}} Value clamped to range Value, floor, ceiling
{{abs::value}} Absolute value Number
{{floor::value}} Rounded down Number
{{ceil::value}} Rounded up Number
{{round::value::decimals}} Rounded to N decimal places Number, optional decimal count (default 0)
{{mod::a::b}} Remainder of a / b Dividend, divisor

Examples:

{{calc::{{messageCount}} * 2 + 1}}      — arithmetic with macros
{{calc::({{.hp}} / {{.maxHp}}) * 100}}   — health percentage
{{clamp::{{.score}}::0::100}}            — keep score in bounds
{{max::{{.str}}::{{.dex}}}}              — highest stat
{{round::3.14159::2}}                    — "3.14"

Safe evaluator

{{calc}} uses a sandboxed arithmetic parser — no eval(). Supports +, -, *, /, %, parentheses, unary minus, and decimal numbers. Division by zero returns 0.


Logic & Comparisons

Composable boolean logic and multi-branch conditionals.

Branching

Macro Aliases Returns Args
{{switch::value::c1::r1::c2::r2::default}} Matching result, or default Value, then case/result pairs, optional default
{{default::value::fallback}} {{fallback}}, {{coalesce}} First truthy value Primary value, fallback

Boolean Operators

Macro Returns Args
{{and::a::b::...}} "true" if all args truthy, else "" Two or more values
{{or::a::b::...}} "true" if any arg truthy, else "" Two or more values
{{not::value}} "true" if value is falsy, else "" One value

Comparison Operators

Macro Returns
{{eq::a::b}} "true" if equal (numeric-aware)
{{ne::a::b}} "true" if not equal
{{gt::a::b}} "true" if a > b
{{lt::a::b}} "true" if a < b
{{gte::a::b}} "true" if a >= b
{{lte::a::b}} "true" if a <= b

Examples:

{{switch::{{.mood}}::happy::😊::sad::😢::neutral}}

{{default::{{.title}}::Stranger}}

{{if::{{and::{{isGroupChat}}::{{lumiaCouncilModeActive}}}}}}
  Group council is active.
{{/if}}

{{if::{{gt::{{messageCount}}::50}}}}
  This is a long conversation.
{{/if}}

switch vs nested if

Instead of chaining {{if}}...{{else}}{{if}}... for multiple cases, use {{switch}}. It's cleaner and easier to read.


Formatting

Quick list formatting.

Macro Aliases Returns Args
{{bullets::item1::item2::...}} - item1\n- item2\n... Items via args, or newline-split body if scoped
{{numbered::item1::item2::...}} {{ol}}, {{enumerate}} 1. item1\n2. item2\n... Items via args, or newline-split body if scoped

Examples:

{{bullets::{{char}}::{{user}}::{{group}}}}
{{numbered}}
Establish the scene
Describe the character's action
Include internal thoughts
{{/numbered}}

Chat Utilities

Access individual messages, track state, and query character metadata.

Macro Aliases Returns Args
{{messageAt::index}} {{message_at}}, {{msgAt}} Message content at index 0-based index (negative counts from end)
{{messagesBy::name::count}} {{messages_by}}, {{msgBy}} Last N messages from a speaker Speaker name, optional count (default 3)
{{chatAge}} {{chat_age}} Human-readable time since chat creation
{{counter::name}} Incremented value (1, 2, 3...) Counter name (stored as local variable)
{{toggle::name}} Flipped boolean ("true""false") Toggle name (stored as local variable)
{{charTags}} {{char_tags}}, {{characterTags}} Comma-separated list of the character's tags
{{charTag::tag}} {{char_tag}}, {{hasTag}}, {{has_tag}} "true" / "false" — whether character has this tag Tag name (case-insensitive)

Examples:

{{messageAt::0}}                  — the first message (greeting)
{{messageAt::-1}}                 — the most recent message
{{messagesBy::{{char}}::3}}       — last 3 things the character said

{{counter::scene_count}}          — auto-incrementing scene counter
{{toggle::narrator_mode}}         — flip between narrator on/off

{{if::{{charTag::fantasy}}}}
Include world-building details.
{{/if}}

This chat started {{chatAge}} ago.

Regex Script References

Call installed regex scripts by their Script ID — a stable, user-defined identifier you set on any regex script.

Script IDs are auto-normalized: lowercase, spaces/hyphens become underscores, punctuation stripped. "My Cool-Script!" becomes my_cool_script.

Macro Aliases Returns Args
{{regexInstalled::scriptId}} {{regex_installed}}, {{hasRegex}}, {{has_regex}} "true" / "false" — whether the script exists and is enabled Script ID only
{{regexInstalled::scriptId::text}} Text with the regex applied (unchanged if script missing) Script ID + text (or scoped body)

Examples:

{{!-- Check if a script is installed --}}
{{if::{{regexInstalled::censor}}}}
  Content filtering is active.
{{/if}}

{{!-- Apply a regex script inline --}}
{{regexInstalled::fix_pronouns::{{description}}}}

{{!-- Scoped form --}}
{{regexInstalled::format_dialogue}}
  "Hello," she said. "How are you?"
{{/regexInstalled}}

Setting a Script ID

Open any regex script in the Regex Scripts panel and fill in the Script ID field. This is the identifier you use in {{regexInstalled}}. Keep it short and descriptive — e.g., censor, fix_pronouns, format_dialogue.


Variables

Read and write values in three scopes — local (transient per-evaluation), chat (persisted per-chat), or global (cross-chat).

Local Variables (Transient)

Local variables live for the duration of a single evaluation pass. They are useful for intermediate calculations, loop counters, and temporary values within a preset block. They are not saved between generations.

Macro Description Args
{{getvar::key}} Get a variable's value Variable name
{{setvar::key::value}} Set a variable (returns nothing) Name and value
{{addvar::key::value}} Add a number to a variable Name and number
{{incvar::key}} Increment by 1 (returns new value) Variable name
{{decvar::key}} Decrement by 1 (returns new value) Variable name
{{hasvar::key}} Check if variable exists ("true" / "false") Variable name
{{deletevar::key}} Delete a variable Variable name

Aliases: {{varexists}} for {{hasvar}}, {{flushvar}} for {{deletevar}}

Shorthand: . prefix — {{.myVar}}, {{.score = 100}}, {{.counter++}}

Chat-Persisted Variables

Chat-persisted variables are automatically saved to the chat after each generation. They survive across messages, regenerations, and page reloads — making them ideal for tracking story state like health, quest progress, relationship points, or turn counters.

Macro Description Args
{{getchatvar::key}} Get a persisted variable's value Variable name
{{setchatvar::key::value}} Set a persisted variable (returns nothing) Name and value
{{addchatvar::key::value}} Add a number to a persisted variable (returns new value) Name and number
{{incchatvar::key}} Increment by 1 (returns new value) Variable name
{{decchatvar::key}} Decrement by 1 (returns new value) Variable name
{{haschatvar::key}} Check if exists ("true" / "false") Variable name
{{deletechatvar::key}} Delete a persisted variable Variable name

Alias: {{flushchatvar}} for {{deletechatvar}}

Shorthand: @ prefix — {{@hp}}, {{@hp = 100}}, {{@turn++}}, {{@hp -= 25}}

When to use @ vs .

Use @ (chat-persisted) for anything that should survive between messages — HP, quest stages, relationship scores, turn counters, discovered secrets.

Use . (local) for scratch values within a single evaluation — loop counters, intermediate calculations, temporary formatting state.

Example — RPG state tracking:

{{@turn++}}
{{@hp -= {{roll::1d6}}}}

{{if::{{gt::{{@hp}}::0}}}}
Turn {{@turn}}: {{char}} takes damage. HP: {{@hp}}/{{@maxHp}}
{{else}}
Turn {{@turn}}: {{char}} has fallen!
{{/if}}

Example — Relationship tracker:

{{setchatvar::affection::50}}

{{if::{{gt::{{@affection}}::80}}}}
{{char}} looks at you warmly.
{{else}}
{{char}} gives you a polite nod.
{{/if}}

setchatvar also supports scoped syntax — the enclosed content becomes the value:

{{setchatvar::last_scene}}The group arrived at the ancient temple...{{/setchatvar}}

Global Variables (Cross-Chat)

Global variables persist across all chats for the current user. Useful for preferences, themes, or cross-character state.

Macro Description Args
{{getgvar::key}} Get a global variable Variable name
{{setgvar::key::value}} Set a global variable Name and value
{{addgvar::key::value}} Add a number to a global variable Name and number
{{incgvar::key}} Increment by 1 (returns new value) Variable name
{{decgvar::key}} Decrement by 1 (returns new value) Variable name
{{hasgvar::key}} Check if exists ("true" / "false") Variable name
{{deletegvar::key}} Delete a global variable Variable name

Aliases: {{getglobalvar}}, {{setglobalvar}}, {{addglobalvar}}, {{incglobalvar}}, {{decglobalvar}}, {{hasglobalvar}}, {{gvarexists}}, {{flushgvar}}, {{flushglobalvar}}, {{deleteglobalvar}}

Shorthand: $ prefix — {{$theme}}, {{$theme = dark}}

Variable Scope Summary

Scope Prefix Persists? Storage Use Case
Local . No — one evaluation only In-memory Temp calculations, loop counters
Chat @ Yes — across generations chat.metadata HP, quests, turns, story state
Global $ Yes — across all chats User settings Preferences, cross-character state

Example — Combined usage:

{{.roll = {{roll::1d20}}}}
{{@hp -= {{.roll}}}}
Rolled {{.roll}} damage. {{char}}'s HP: {{@hp}}/{{@maxHp}}

Here .roll is a temporary local variable (used for the current evaluation only), while @hp and @maxHp are chat-persisted and carry over to the next generation.

Prompt Variables (Preset Inputs)

Prompt variables are preset-defined inputs that are seeded into local scope before block evaluation. That means {{var::tone}}, {{getvar::tone}}, and {{.tone}} can all resolve to the same runtime value.

Macro Aliases Description Args
{{var::name}} {{promptVar}}, {{presetVar}} Read the runtime prompt-variable value, then the user override, then the creator default Variable name
{{hasPromptVar::name}} {{hasPresetVar}}, {{hasVar}} Check whether a prompt variable is resolvable Variable name
{{varDefault::name}} {{promptVarDefault}}, {{presetVarDefault}} Read the creator-declared default only Variable name

Examples:

Tone: {{default::{{var::tone}}::neutral}}

{{if::{{hasPromptVar::violence}}}}
Violence level: {{var::violence}}
{{/if}}

Runtime & State

Information about the current system state.

Macro Aliases Returns
{{model}} Current LLM model name
{{isMobile}} {{is_mobile}} Whether the client is mobile
{{maxPrompt}} {{maxPromptTokens}}, {{max_prompt}} Maximum prompt token count
{{maxContext}} {{maxContextTokens}}, {{max_context}} Maximum context window tokens
{{maxResponse}} {{maxResponseTokens}}, {{max_response}} Maximum response tokens
{{lastGenerationType}} {{last_generation_type}} Last generation type (normal, continue, regenerate, etc.)
{{hasExtension::name}} {{has_extension}} "true" / "false" — whether a named extension is active
{{userColorMode}} {{user_color_mode}}, {{colorMode}}, {{color_mode}} User's color scheme (dark, light, or system)

Reasoning / Chain-of-Thought

For models that support extended thinking (DeepSeek, Claude, o1).

Macro Description Args
{{reasoningPrefix}} Opening tag for reasoning blocks Optional: {{reasoningPrefix::raw}} to strip surrounding newlines
{{reasoningSuffix}} Closing tag for reasoning blocks Optional: {{reasoningSuffix::raw}} to strip surrounding newlines

Example:

{{reasoningPrefix}}
Think step by step about what {{char}} would do next.
{{reasoningSuffix}}

Memory

Long-term memory and retrieval macros from Lumiverse's memory systems.

Long-Term Memory

Macro Aliases Returns Args
{{memories}} {{longTermMemory}}, {{chatMemory}}, {{ltm}} Formatted memory chunks with header Optional: {{memories::count}} to override chunk count
{{memoriesActive}} "yes" / "no" — whether memories were retrieved (condition-compatible)
{{memoriesCount}} Number of memory chunks retrieved
{{memoriesRaw}} Raw memory chunks without header formatting Optional: {{memoriesRaw::count}} to override chunk count

Databank Retrieval

Macro Aliases Returns Args
{{databank}} {{databankMemory}}, {{documents}}, {{knowledgeBank}} Formatted databank chunks with source headers Optional: {{databank::count}} to override chunk count
{{databankActive}} "yes" / "no" — whether databank retrieval returned chunks
{{databankCount}} Number of databank chunks retrieved
{{databankRaw}} Raw databank chunks without the outer header Optional: {{databankRaw::count}} to override chunk count

Memory Cortex

Macro Returns Args
{{entities}} Formatted entity snapshots with facts and relationships Optional: {{entities::count}} to limit the number of entities
{{entityFacts::name}} Facts for one named entity Entity name
{{relationships}} Active relationship edges in the current scene
{{arc}} Current narrative arc summary
{{memorySalience}} Highest-salience retrieved memory
{{cortexActive}} "yes" / "no" — whether Memory Cortex returned results
{{entityCount}} Number of active entities in context
{{characterColors}} Character speech / thought / narration color instructions

Lumia & Council

Macros for the council deliberation system and Lumia personas. These resolve to content only when the relevant systems are enabled.

Lumia Identity

Macro Description Args
{{randomLumia}} A random Lumia from all packs (cached per generation) Optional: {{randomLumia::name}}, ::phys, ::pers, or ::behav
{{lumiaDef}} Selected Lumia definition — adapts for Council (multi-member) and Chimera (fusion) modes Optional: {{lumiaDef::len}} to get count
{{lumiaBehavior}} All selected behavioral traits Optional: {{lumiaBehavior::len}} to get count
{{lumiaPersonality}} All selected personality traits Optional: {{lumiaPersonality::len}} to get count
{{lumiaQuirks}} Behavioral quirks with mode-adaptive header
{{lumiaSelf::N}} Self-address pronouns: 1=my/our, 2=mine/ours, 3=me/us, 4=I/we Required: 1, 2, 3, or 4

Alias: {{lumiaCouncilQuirks}} for {{lumiaQuirks}}

Council Status (Condition-Compatible)

Macro Returns
{{lumiaCouncilModeActive}} "yes" / "no" — whether council mode is on
{{lumiaCouncilToolsActive}} "yes" / "no" — whether council tools ran this generation

Council Content

Macro Description Args
{{lumiaCouncilInst}} Council interaction dynamics prompt with member names
{{lumiaCouncilDeliberation}} Full tool results and deliberation instructions
{{loomCouncilResult::var}} A specific named tool result variable Required: variable name
{{lumiaCouncilToolsList}} Tool names with member attribution
{{lumiaStateSynthesis}} Council Sound-Off / State Synthesis prompt
{{lumiaMessageCount}} Chat message count (alias for messageCount)

OOC (Out-of-Character)

Macro Description
{{lumiaOOC}} OOC commentary prompt — adapts for normal, council, and IRC modes
{{lumiaOOCErotic}} Mirror & Synapse erotic OOC prompt
{{lumiaOOCEroticBleed}} Narrative Rupture mid-narrative OOC prompt
{{lumiaOOCTrigger}} OOC trigger countdown or activation message

Loom

Macros for the Loom narrative system.

Loom Content

Macro Description Args
{{loomStyle}} Selected Loom narrative style content Optional: {{loomStyle::len}} to get count
{{loomUtils}} Selected Loom utility prompts Optional: {{loomUtils::len}} to get count
{{loomRetrofits}} Selected Loom retrofit prompts Optional: {{loomRetrofits::len}} to get count
{{loomSummary}} Stored chat summary from Loom summarization
{{loomSummaryPrompt}} Summarization directive prompt (5-section structure)

Loom Conversation Aliases

Macro Same As
{{loomLastUserMessage}} {{lastUserMessage}}
{{loomLastMessageName}} {{lastMessageName}}
{{loomLastCharMessage}} {{lastCharMessage}}

Sovereign Hand

Macro Description
{{loomSovHandActive}} "yes" / "no" — condition-compatible
{{loomSovHand}} Full Sovereign Hand co-pilot prompt
{{loomContinuePrompt}} Continuation instructions when Sovereign Hand is active

Condition-Compatible Macros

These macros return "yes" / "no" or "true" / "false" and are designed for use with {{if}}:

Macro True When
{{isGroupChat}} Chat has multiple characters
{{lumiaCouncilModeActive}} Council mode is enabled
{{lumiaCouncilToolsActive}} Council tools ran this generation
{{loomSovHandActive}} Sovereign Hand mode is on
{{memoriesActive}} Memories were retrieved
{{databankActive}} Databank retrieval returned chunks
{{cortexActive}} Memory Cortex returned results
{{hasvar::key}} Local variable exists
{{haschatvar::key}} Chat-persisted variable exists
{{hasgvar::key}} Global variable exists
{{hasPromptVar::name}} A prompt variable is available
{{charTag::tag}} Character has the specified tag
{{regexInstalled::id}} Regex script with that ID is installed and enabled
{{and::a::b}} All arguments are truthy
{{or::a::b}} Any argument is truthy
{{not::value}} Value is falsy
{{eq::a::b}} / {{gt}} / {{lt}} / etc. Comparison is true

Usage:

{{if::{{lumiaCouncilModeActive}}}}
Council deliberation results:
{{lumiaCouncilDeliberation}}
{{/if}}

{{if::{{and::{{charTag::fantasy}}::{{gt::{{messageCount}}::5}}}}}}
The adventure is well underway.
{{/if}}

Tips for Preset Creators

Use Dry Run religiously

After adding macros to your blocks, always Dry Run to verify they resolve correctly. You'll see the fully assembled prompt with every macro expanded.

Avoid redundancy

If you use structural markers (like the char_description block), the {{description}} macro is already handled. Don't insert both — the same content appears twice.

Conditional blocks save tokens

Wrap council-specific content in {{if::{{lumiaCouncilModeActive}}}} so it only appears when council is active. Same for group chat content with {{if::{{isGroupChat}}}}. This keeps prompts lean.

Variables for state tracking

Use @ variables to track story state that persists across messages — {{@hp = 100}}, {{@turn++}}, {{@quest_stage = 2}}. These are automatically saved after each generation. Use . variables for temporary calculations within a single evaluation. Global variables ({{$var}}) persist across all chats.

{{default}} replaces common if/else patterns

Instead of {{if::{{hasvar::title}}}}{{.title}}{{else}}Stranger{{/if}}, just write {{default::{{.title}}::Stranger}}. Cleaner and shorter.

{{switch}} for multi-branch logic

Instead of nested if/else chains, use {{switch::{{.mood}}::happy::cheerful tone::sad::somber tone::neutral tone}}.

{{wrap}} for conditional formatting

{{wrap}} only outputs if the content is non-empty — {{wrap::(**::**)::{{.note}}}} produces nothing when the note is unset, avoiding stray delimiters.

{{calc}} for dynamic math

{{calc::({{.hp}} / {{.maxHp}}) * 100}} gives you a health percentage without juggling setvar/addvar chains.

Random adds variety

Sprinkle {{pick}} into your presets for natural variation: "Write in a {{pick::vivid::poetic::visceral::atmospheric}} style." Each generation picks a different word.

Coming from SillyTavern?

Lumiverse supports SillyTavern-style syntax: {{.var}} shorthand, space-delimited arguments, {{if .var}} conditions, and ! negation. Your existing presets should work with minimal changes. See the Execution Order guide for any differences.

Mind the evaluation order

Macros resolve primarily in one depth-first AST walk, with nested macro output expanded inline and a small outer retry loop for edge cases. State still flows left-to-right: a later setter will not retroactively change an earlier read in the same block. See the Execution Order guide for the complete breakdown.