NEOLearn

The [script] manifest

Every key of the [script] section of neo.toml, its type, default and meaning, and the errors NEO reports for a bad manifest.

Updated October 17, 2026

On this page

The [script] section of a game's neo.toml is its script manifest. It names the game's script language and scripts, sets the budgets, says what the game's own scripts may touch, and controls live scripting by players. A game without a [script] section runs no scripts and exposes nothing.

neo.toml
[script]
language = "js"
scripts = ["assets/scripts/platform.js"]
fuel_per_tick = 1_000_000
fuel_per_call = 500_000
calls_per_tick = 2_000
memory = "16MB"

[script.expose.Platform]
fields = { position = "get set", speed = "get", label = "get", display_name = "get" }
methods = ["boost"]

[script.expose.Player]
fields = { position = "get", name = "get" }

[script.expose.Cube]
fields = { position = "get set", size = "get set" }
spawn = true

[script.players]
allowed = "nobody"
fuel_per_tick = 100_000
calls_per_tick = 100
memory = "4MB"

[script.roles.player]
grant = ["Platform.position:get", "Player.position:get"]

[script.roles.builder]
grant = ["Cube:spawn", "Cube.position:set", "Cube.size:set", "Platform.boost:call"]

[script.roles.admin]
grant = ["Platform.display_name:get set"]

Every grant is checked against what the game's Rust types declare with #[derive(ScriptExpose)] (see Exposure and permissions). The manifest can narrow what Rust declares, never widen it.

[script]#

KeyTypeDefaultMeaning
languagestring"js"The game's one script language: "js" (or "javascript") or "py" (or "python").
scriptslist of strings[]The game's own scripts, as paths relative to the project. They load in this order, as the game's scripts.
fuel_per_tickinteger2_000_000Instructions each script may use per tick, across all its calls.
fuel_per_callinteger1_000_000Instructions for one call into a script (one event, or the tick).
calls_per_tickinteger10_000World calls each script may make per tick.
memoryinteger or string"64MB"Memory per script: a number of bytes, or a string with a unit (B, K/KB, M/MB, G/GB; for example "16MB").
exposetablenone[script.expose.<Kind>] sections (below).
playerstablenoneThe [script.players] section (below).
rolestablenone[script.roles.<role>] sections (below).

A script's name is its file name without the extension (assets/scripts/platform.js runs as platform). Sizes use powers of 1,024: "16MB" is 16 × 1,048,576 bytes. The budgets are explained in Limits and determinism.

[script.expose.Kind]#

What the game's own scripts may do with one kind. Kind stands for the kind name as declared in Rust (kind = "Platform"). A kind with no section doesn't exist for the game's scripts.

KeyTypeDefaultMeaning
fieldsinline tablenoneField name to access: "get", "set" or "get set" ("read" and "write" also work). Use the snake_case names. position is the entity's transform, if the type declares one.
methodslist of stringsnoneMethods the scripts may call.
spawnbooleanfalseWhether the scripts may create this kind with spawn.
TOML
[script.expose.Door]
fields = { open = "get" }
methods = ["open"]

[script.players]#

Live scripting by players: scripts a player loads into a running session.

KeyTypeDefaultMeaning
allowedstring"nobody"Who may load live scripts (values below).
fuel_per_tickinteger200_000Per-tick instructions for each player script.
fuel_per_callinteger200_000Per-call instructions for each player script.
calls_per_tickinteger200World calls per tick for each player script.
memoryinteger or string"4MB"Memory per player script.

Values of allowed:

ValueWho may load live scripts
"nobody"No one.
"owner"The game's owner.
"friends"The owner and the owner's friends.
"role:<name>"The owner and players holding the role <name>.
"everyone"Every player.

The player budgets are the same for every player and device. A player's script also has to pass the game's moderation check (by default, sources over 64 KB are refused).

[script.roles.role]#

Grants for players holding a role; role stands for the role's name. Every player holds the role player, so [script.roles.player] is what all player scripts get. A player's scripts get the player grants plus those of every other role they hold, and start with nothing else.

KeyTypeDefaultMeaning
grantlist of stringsrequiredThe role's grants (forms below).
GrantAllows
"Kind.field:get"Reading the field.
"Kind.field:set"Writing the field.
"Kind.field:get set"Both (a comma also works: "get,set").
"Kind.method:call"Calling the method.
"Kind:spawn"Spawning the kind.

Fields and methods that Rust restricts to roles (roles = [...] in the derive) are removed for players who hold none of those roles, whatever the grants say. The game's own scripts aren't affected by role restrictions.

Errors#

A manifest with a problem doesn't half-work. NEO reports one of these, prefixed with neo.toml [script] and the key it's about:

ProblemMessage
language isn't a known languageone of "js" or "py" (one language per game)
A languages key (more than one language)a game packages one language: use language = "js"
scripts isn't a list of stringsa list of paths / paths are strings
A budget isn't a non-negative integerexpected a non-negative integer
A bad memory valuea size is a number of bytes or a string like "16MB", unknown size unit, or ... isn't a size
An unknown key in [script]unknown key
An unknown key in [script.expose.<Kind>]unknown key (fields, methods, spawn)
A bad access stringaccess is "get", "set" or "get set" (or empty access)
spawn isn't a booleanspawn = true | false
A bad allowed value"nobody", "owner", "friends", "role:<name>" or "everyone"
A role without a grant lista list of grants
A grant in the wrong formexpected Kind.name:access, or only Kind:spawn names a kind alone

These errors are checked against the game's Rust declarations:

ProblemMessage
A kind no Rust type registers`Platfrom` isn't a script kind (no #[derive(ScriptExpose)] registers it)
A field Rust doesn't declare`Platform.speedd` isn't declared for scripts
More access than Rust declares`Player.position` grants more than the type declares
A method Rust doesn't declare`Platform.bost` isn't a declared script method

What happens when there's a problem:

  • The section can't be read (a syntax or type error): the game logs manifest refused: ... and runs with no scripts exposed.
  • A grant doesn't match the declarations: a script that would run under those grants is refused, and the load log says why. The game's other parts keep running.

The Scripts panel's check validates the whole manifest against the declarations and lists every problem at once. See The Scripts panel.

See also#