Configuration¶
Tua projects use tua.toml.
Configuration is decoded through a typed Serde schema and a standards-compliant TOML parser. Normal TOML quoting, escapes, multiline arrays, dotted keys, and inline tables are supported. Unknown sections and keys are rejected with a nearby-name suggestion when one is unambiguous, and editor diagnostics select the precise offending key or value range.
The language server attaches to tua.toml files in VS Code and provides
schema-backed key completion, section completion, enum/default value
completion, setting hover documentation, and quick fixes for unknown-key
diagnostics that include a suggestion.
Generated config templates live in config/templates/:
default.toml: the full defaulttua.toml, generated fromconfig/schema.jsonand checked againstDEFAULT_CONFIG_TEXT.minimal.toml: the smallest root-level project template for common new projects.
Default Config¶
source = "src"
out = "build"
main = "main.tua"
target = "love11-luajit"
extension = "tua"
emit_maps = true
type_libraries = []
[emit]
annotation_mode = "off"
[format]
indent_width = 2
line_width = 100
quote_style = "preserve"
final_newline = true
[jit]
enabled = false
variable_type_drift = true
table_shape_drift = true
hot_loop_hints = true
[ecs]
enabled = true
backend = "tua"
[diagnostics]
rules = true
duplicate_keys = false
missing_requires = false
self_assignments = false
doc_annotations = false
undefined_variables = false
unused_locals = false
unused_parameters = false
use_before_definition = false
duplicate_parameters = false
wrong_argument_count = false
bad_requires = false
impossible_boolean_expressions = false
duplicate_if_conditions = false
duplicate_binary_operands = false
float_equality = false
const_assignments = false
parameter_type_mismatches = false
return_type_mismatches = false
assignment_arity = false
local_declaration_arity = false
unused_assignments = false
binary_operator_type_mismatches = false
uncalled_local_functions = false
inline_ignores = true
inline_ignore_scopes = ["tua-ignore-line", "tua-ignore-next-line", "tua-ignore-file"]
inline_ignore_max_per_file = 0
globals = []
Schema Reference¶
This compact reference is generated from the same metadata used for config-key validation and editor-setting drift checks. The detailed sections below explain the behavior and tradeoffs of each option.
| TOML path | Type | Default | VS Code override |
|---|---|---|---|
source |
string | "src" |
- |
out |
string | "build" |
- |
main |
string | "main.tua" |
- |
target |
string | "love11-luajit" |
- |
extension |
string | "tua" |
- |
emit_maps |
boolean | true |
- |
type_libraries |
array | [] |
- |
emit.annotation_mode |
string | "off" |
- |
format.indent_width |
integer | 2 |
tua.format.indentWidth |
format.line_width |
integer | 100 |
tua.format.lineWidth |
format.quote_style |
string | "preserve" |
tua.format.quoteStyle |
format.final_newline |
boolean | true |
tua.format.finalNewline |
jit.enabled |
boolean | false |
tua.jit.enabled |
jit.variable_type_drift |
boolean | true |
- |
jit.table_shape_drift |
boolean | true |
- |
jit.hot_loop_hints |
boolean | true |
- |
ecs.enabled |
boolean | true |
tua.ecs.enabled |
ecs.backend |
string | "tua" |
- |
diagnostics.rules |
boolean | true |
tua.diagnostics.rules |
diagnostics.duplicate_keys |
boolean | false |
tua.diagnostics.duplicateKeys |
diagnostics.missing_requires |
boolean | false |
tua.diagnostics.missingRequires |
diagnostics.self_assignments |
boolean | false |
tua.diagnostics.selfAssignments |
diagnostics.doc_annotations |
boolean | false |
tua.diagnostics.docAnnotations |
diagnostics.undefined_variables |
boolean | false |
tua.diagnostics.undefinedVariables |
diagnostics.unused_locals |
boolean | false |
tua.diagnostics.unusedLocals |
diagnostics.unused_parameters |
boolean | false |
tua.diagnostics.unusedParameters |
diagnostics.use_before_definition |
boolean | false |
tua.diagnostics.useBeforeDefinition |
diagnostics.duplicate_parameters |
boolean | false |
tua.diagnostics.duplicateParameters |
diagnostics.wrong_argument_count |
boolean | false |
tua.diagnostics.wrongArgumentCount |
diagnostics.bad_requires |
boolean | false |
tua.diagnostics.badRequires |
diagnostics.impossible_boolean_expressions |
boolean | false |
tua.diagnostics.impossibleBooleanExpressions |
diagnostics.duplicate_if_conditions |
boolean | false |
tua.diagnostics.duplicateIfConditions |
diagnostics.duplicate_binary_operands |
boolean | false |
tua.diagnostics.duplicateBinaryOperands |
diagnostics.float_equality |
boolean | false |
tua.diagnostics.floatEquality |
diagnostics.const_assignments |
boolean | false |
tua.diagnostics.constAssignments |
diagnostics.parameter_type_mismatches |
boolean | false |
tua.diagnostics.parameterTypeMismatches |
diagnostics.return_type_mismatches |
boolean | false |
tua.diagnostics.returnTypeMismatches |
diagnostics.assignment_arity |
boolean | false |
tua.diagnostics.assignmentArity |
diagnostics.local_declaration_arity |
boolean | false |
tua.diagnostics.localDeclarationArity |
diagnostics.unused_assignments |
boolean | false |
tua.diagnostics.unusedAssignments |
diagnostics.binary_operator_type_mismatches |
boolean | false |
tua.diagnostics.binaryOperatorTypeMismatches |
diagnostics.uncalled_local_functions |
boolean | false |
tua.diagnostics.uncalledLocalFunctions |
diagnostics.inline_ignores |
boolean | true |
tua.diagnostics.inlineIgnores |
diagnostics.inline_ignore_scopes |
string-array | ["tua-ignore-line","tua-ignore-next-line","tua-ignore-file"] |
tua.diagnostics.inlineIgnoreScopes |
diagnostics.inline_ignore_max_per_file |
integer | 0 |
tua.diagnostics.inlineIgnoreMaxPerFile |
diagnostics.globals |
string-array | [] |
tua.diagnostics.globals |
Root Options¶
source- Directory containing Tua source files.
out- Directory where emitted Lua files are written.
main- Source file under
sourcethat also emits to<out>/main.luafor LOVE entrypoint loading. The source file still keeps its normal mirrored output path, somain = "love/boot.tua"emits bothbuild/love/boot.luaandbuild/main.lua. If another source would also mirror to<out>/main.lua,tua buildreports an output collision until one of the sources is renamed ormainis changed. target- Runtime target label. The default is
love11-luajit. extension- Source extension to discover. The default is
tua. emit_maps- When
true,tua buildwrites*.lua.map.jsonTua provenance and standard*.lua.mapv3 sidecars next to each generated.luafile. They support generated-Lua navigation,tua traceback, and source-mapped Lua debugging; they are not loaded by the game at runtime.
Declaration-Only Type Libraries¶
type_libraries indexes third-party LuaCATS declarations without treating
them as source files or runtime dependencies. Replace the default
type_libraries = [] line with one array entry per installed library:
[[type_libraries]]
path = "lib/feel/types"
declaration_prefix = "feel"
runtime_prefix = "lib.feel"
Each entry has three required fields:
pathis a directory, relative to the project root unless absolute. Tua recursively indexes its.luafiles as declarations.declaration_prefixis the module namespace used by---@meta, such asfeelandfeel.love.runtime_prefixis the namespace used by projectrequire(...)calls. The example maps---@meta feeltorequire("lib.feel")and---@meta feel.lovetorequire("lib.feel.love").
Declaration libraries are analysis-only. Tua never copies, emits, executes, or
packages their files, and the editor performs no network fetching. A static
import(...) still resolves a real project module because it represents
runtime/build code; only require(...) receives the declaration overlay.
Changes under configured roots are watched by tua watch. The language server
indexes them during workspace reindexing and refreshes changes reported by the
editor.
The installed library owns its declarations. Updating a vendored or package-managed Feel checkout therefore updates Tua completion without a Tua release and without bundling Feel itself.
Emit¶
annotation_mode- Controls annotation-preserving emission for emitted Lua.
off(default): erase all Tua-only types and keep current minimal output.luacats: emit LuaCATS-compatible comments derived from available type information.
LuaCATS output includes:
---@aliasfor exported type aliases.---@typefor annotated locals.---@paramand---@returnfor function signatures.---@fieldfor stable table/object fields.
Format¶
The built-in formatter is Rust-native and is used by tua fmt plus LSP
textDocument/formatting, textDocument/rangeFormatting, and
textDocument/onTypeFormatting. It removes leading and trailing empty lines
and collapses consecutive empty lines between code sections to one. Empty
lines inside multiline strings and block comments are preserved.
indent_width- Spaces per indentation level.
line_width- Preferred maximum line width for line-aware groups.
quote_style- Currently
preserve, which keeps existing string quote style. final_newline- Writes a final LF newline when formatting.
LuaJIT Guidance¶
LuaJIT guidance is opt-in and diagnostic-only. It encourages stable local and table shapes for LOVE projects that care about desktop LuaJIT behavior, but it does not rewrite code, add runtime checks, or change emitted Lua.
enabled- Enables the LuaJIT guidance pass. The default is
false. variable_type_drift- Retained for LuaJIT-guidance configuration compatibility. Incompatible
inferred-local reassignment in
.tuais now a coreTL1003error regardless of JIT settings, so the JIT pass does not duplicate that diagnostic.anyand unknown dynamic values remain escape hatches. table_shape_drift- Reports clear table-shape drift such as adding late fields to a known table constructor or changing a known field from one concrete type to another.
hot_loop_hints- Reports dynamic table-key writes inside loops when Tua can see the pattern. These are hints for reviewing hot code paths, not proof that a loop is slow.
ECS Domain Support¶
ECS support and the bundled Tua runtime are enabled by default. The section can be omitted:
enabled- Enables the built-in
ecsmodule, first-class ECS analysis, ECS diagnostics, and automatic bundled runtime emission. The default istrue; set it tofalseto opt out. backend- Names the runtime profile. The default
tuaprofile emits the bundledtuaecs.luaruntime only when a source file uses the built-inecsmodule.
When enabled, Tua recognizes:
ecs.world(): EcsWorld;ecs.component(name, schema): EcsComponent;ecs.system(world, components, update): EcsSystem;- world methods such as
world:create(),world:add(...), andworld:query(...).
The initial diagnostics cover clear, static patterns:
- mismatched or missing fields in one-line
world:add(entity, Component, { ... })calls; - unknown components in one-line
ecs.system(world, { ... }, ...)orworld:query({ ... })calls; - empty component query lists.
Dynamic ECS construction remains permissive.
An explicit binding such as local ecs = require("project_ecs") overrides the
built-in runtime for that file. See Entity Component Systems for the
runtime model and guidance on when ECS is appropriate.
State Store Support¶
store({...}) is available without configuration. A source file that uses it
emits a require("tuastore"), and the build copies the bundled runtime only
when required. There is no global store setting: state ownership, persistence,
save formats, and migrations belong to each explicit store and project. See
State Stores for the API and LOVE filesystem adapter pattern.
Object Pool Support¶
objectPool({...}) is available without configuration. A source file that
uses it emits a require("tuaobjectpool"), and the build copies the bundled
LuaJIT-compatible runtime only when required. The compiler models lifecycle
methods and preserves an annotated factory return type through acquire().
There is no pool-wide project setting. Pool size and lifecycle belong at each
call site through initial, prewarm, reset, and dispose. See
Object Pooling for the full API and performance guidance.
Input Support¶
input({...}) is available without configuration. A source file that uses it
emits require("baton").new, and the build copies the bundled MIT-licensed
baton.lua only when required. A project-provided src/baton.lua is copied
instead and is not overwritten.
There is no global input setting. Controls, pairs, joystick selection,
deadzones, and player ownership belong to each input call. See
Input for the full Baton-backed API.
Diagnostics¶
Formatting and linting are independent: [format] controls tua fmt, while
[diagnostics] controls code-quality guidance. tua lint always enables the
standard rules for that command. Those rules are enabled by default for
tua check and editor diagnostics; set rules = false to opt out there.
tua lint --strict adds every Tua-specific optional lint. See
Formatter, Linter, and
Diagnostic Codes.
[diagnostics]
rules = true
duplicate_keys = true
missing_requires = true
self_assignments = true
doc_annotations = true
undefined_variables = true
unused_locals = true
unused_parameters = true
use_before_definition = true
duplicate_parameters = true
wrong_argument_count = true
bad_requires = true
impossible_boolean_expressions = true
duplicate_if_conditions = true
duplicate_binary_operands = true
float_equality = true
const_assignments = true
parameter_type_mismatches = true
return_type_mismatches = true
assignment_arity = true
local_declaration_arity = true
unused_assignments = true
binary_operator_type_mismatches = true
uncalled_local_functions = true
inline_ignores = true
inline_ignore_scopes = ["tua-ignore-line", "tua-ignore-next-line", "tua-ignore-file"]
inline_ignore_max_per_file = 0
globals = ["love", "_G"]
[emit]
annotation_mode = "luacats"
duplicate_keys- Reports runtime-equivalent literal keys in table constructors, explicit indices that collide with list entries, and repeated named fields in table type shapes.
rules- Controls the standard lint rules for
tua checkand language server diagnostics. They are enabled by default.tua lintenables these rules for its own run regardless of the configured value. See Linter for the rule map and target-specific exclusions. missing_requires- Reports
require("module")and staticimport(...)bindings that Tua cannot resolve from the current project layout. self_assignments- Reports assignments such as
player.hp = player.hp. doc_annotations- Reports malformed supported LuaHelper/LuaLS-style doc annotations such as
---@paramwithout a parameter type. undefined_variables- Reports variable reads that are not known locals, parameters, configured globals, Lua builtins, LOVE globals, or known module exports.
unused_locals- Reports local bindings and direct user-global function declarations that are never read.
unused_parameters- Reports function parameters that are never read.
use_before_definition- Reports local reads before the local declaration when Tua can prove the ordering.
duplicate_parameters- Reports repeated parameter names as
TL4043without enabling every standard rule. wrong_argument_count- Reports calls to known functions with the wrong number of arguments.
bad_requires- Reports invalid require/import paths, including
import("../...")parent traversal and malformed import specifiers. impossible_boolean_expressions- Reports boolean/equality expressions that Tua can prove are impossible.
duplicate_if_conditions- Reports structurally repeated conditions in one
if/elseifchain. duplicate_binary_operands- Reports structurally repeated operands in boolean chains and suspicious
expressions such as
value == value. float_equality- Reports direct equality checks between known numeric values.
const_assignments- Reports assignments to values Tua treats as constant.
parameter_type_mismatches- Reports known function argument type mismatches through the lint pipeline.
return_type_mismatches- Reports known function return type mismatches through the lint pipeline.
assignment_arity- Reports assignments whose explicit value count does not match the target
count. A shortage ending in a direct call or varargs remains permissive because
the final expression may produce multiple values. Ending a shortage with
explicit
nilalso silences the warning and records that the missing values are intentional. local_declaration_arity- Applies the same explicit-value-count check to local declarations.
unused_assignments- Reports assignments to locals that are never otherwise read. This complements
unused_locals, which reports the declaration itself. binary_operator_type_mismatches- Reports binary operators used with statically incompatible operand types, such
as
1 + "hp". Dynamic oranyoperands remain permissive. uncalled_local_functions- Reports local functions that are referenced as values but never directly called. Indirect callback patterns can stay quiet by leaving this opt-in lint disabled.
inline_ignores- Enables exact-code diagnostic suppression comments. This is enabled by
default; set it to
falsewhen a project wants to forbid source suppressions.
Supported comments are:
-- tua-ignore-file TL4048
-- tua-ignore-next-line TL4018
player.setFilter("nearest")
local legacy: number = "soon" -- tua-ignore-line TL1003
tua-ignore-next-line applies to the immediately following line.
tua-ignore-line applies to diagnostics on the same line. tua-ignore-file
applies throughout the file and must be its first nonblank line.
Every directive requires at least one exact code such as TL1003 or TL4048.
Multiple exact codes may be listed. Empty directives, category names, and broad
groups such as TL4000 report TL4025 instead of hiding unrelated diagnostics.
Suppressions do not change program behavior
Invalid codes and unused suppressions produce warnings. A suppression only hides matching diagnostics; it never changes type inference or emitted Lua.
inline_ignore_scopes- Lists the suppression directives accepted by this project. The default allows same-line, next-line, and header-only file suppressions.
inline_ignore_max_per_file- Limits the number of accepted suppression comments per file.
0means unlimited. globals- Adds project-specific global names that should be accepted by diagnostics and linting.
Workspace Resolution¶
The LSP chooses the nearest workspace folder or ancestor containing tua.toml
when resolving diagnostic settings. If no config is found, defaults are used.
Editor Settings¶
The LSP also accepts editor-provided settings through
workspace/didChangeConfiguration.
Configuration precedence is:
- Built-in defaults.
- The nearest applicable
tua.toml. - Editor settings sent by the LSP client.
Editor settings are temporary overlays
Editor settings apply in memory to the running language server and do not
rewrite tua.toml. For diagnostic toggles, use true or false to
override project configuration; leave a value unset or null to inherit
from tua.toml.
Supported editor settings:
tua.diagnostics.*: overrides matching[diagnostics]keys.tua.diagnostics.globals: replaces the configured global allow-list.tua.fileAssociations: maps glob patterns toluaortuaso extra file extensions can be indexed.tua.jit.enabled: overrides[jit].enabledfor opt-in LuaJIT guidance.tua.ecs.enabled: overrides[ecs].enabledfor built-in ECS support.tua.completion.sequenceRanking.enabled: enables the experimental local contextual sequence ranker for completion ordering. It defaults tofalseand never adds non-compiler candidates.tua.completion.sequenceRanking.timeoutMs: maximum sequence-ranking budget in milliseconds. A timeout keeps the pre-sequence completion order.tua.completion.sequenceRanking.maxCandidates: maximum compiler candidates sent to the sequence ranker.tua.completion.multiToken.enabled: enables the experimental multi-token completion lane. It defaults tofalse.tua.completion.multiToken.advanced: allows multi-token suggestions even when normal compiler completion has ordinary confidence.tua.completion.multiToken.allowModelIntegration: explicit opt-in policy gate for local Ollama inline completions. It defaults tofalse.tua.completion.multiToken.maxSuggestions: maximum validated multi-token suggestions appended to completion results.tua.completion.ollama.endpoint: machine-scoped loopback endpoint; defaults tohttp://127.0.0.1:11434.tua.completion.ollama.model: machine-scoped model name; defaults toqwen2.5-coder:1.5b-base.tua.completion.ollama.timeoutMs: generation timeout; defaults to5000.tua.completion.ollama.keepAlive: Ollama residency hint; defaults to10m.tua.completion.ollama.contextTokens: requested Ollama context window; defaults to4096.tua.completion.ollama.maxTokens: user generation ceiling; defaults to256. Tua uses at most 64 tokens for local expressions and 512 for function bodies.tua.ignoredPaths: excludes matching paths from indexing and diagnostics.tua.requirePathSeparator: controls suggested require paths, either.or/. Staticimport(...)lowering uses the same separator when mapping a source path back to the emitted Luarequire("...")module name.tua.preview.enabled: enables explicit experimental editor previews such asTua: Preview Sprite AnimationsandTua: Preview State Machine. Preview metadata comes from the local Tua language server throughtua/inspect; no project source or asset metadata is sent off-device. It does not execute state-machine code or enable proposed VS Code APIs, source-definition/multi-document-highlight/auto-insert behavior, or the external API or MCP processes.
Run Tua: Toggle Experimental Completions to switch both
tua.completion.sequenceRanking.enabled and
tua.completion.multiToken.enabled for the current workspace. If either
feature is off, the command enables both; if both are on, it disables both.
Advanced multi-token and model-integration policy settings are not changed.
Use Tua: Toggle Local Ollama Completions for the separate model-integration
gate and consent flow.