NEOLearn

Script commands

The script and editor.scripts commands that load, list, pause, resume, unload and check scripts, with their arguments and results.

Updated October 17, 2026

On this page

Everything you can do with scripts in the Studio's Scripts panel is also a command, so tools and MCP agents can drive scripts the same way you do. Commands take a JSON object of arguments and return JSON.

There are two groups:

  • script.* commands talk to the running game's scripts. They're available whenever the game runs scripts.
  • editor.scripts.* commands drive the Studio's Scripts panel and the project's script files. See The Scripts panel.

Summary#

CommandArgumentsDoes
script.loadname, source, player?, roles?, owner?, friend?Loads or hot-reloads a script.
script.listnoneLists running scripts, the hash chain and the log.
script.pausenamePauses a script.
script.resumenameResumes a paused script.
script.unloadnameStops and removes a script.
script.typesformat, player?, roles?Generates the script API declarations.
script.apinoneThe game's script API as JSON.
editor.scripts.panelopen?Shows or hides the Scripts panel.
editor.scripts.filesnoneLists the project's script files.
editor.scripts.editnameOpens a script file in Source mode.
editor.scripts.checknoneCompiles, validates and runs script tests.
editor.scripts.live_reloadonTurns hot reload on save on or off.

? marks an optional argument.

script.load#

Loads a script by name, or hot-reloads the script with that name if it's already running (its this.state is kept). The request is queued and applies on the next fixed tick.

NameTypeDescription
namestringRequired. The script's name.
sourcestringRequired. The script's source, in the game's language.
playerstringA player id. With it, the script is that player's live script, subject to [script.players] and the moderation check. Without it, the script is the game's own.
roleslist of stringsThe player's roles in this game (with player).
ownerbooleanThe player owns the game (with player).
friendbooleanThe player is a friend of the owner (with player).

Returns: { "queued": "<name>", "applies": "next fixed tick" }. A missing name or source is an error (`source` is required).

Whether the script actually loaded shows up in the log from script.list: loaded, reloaded, refused ... from player ..., moderation refused ..., or ... didn't load: <error>.

JSON
{ "name": "hello", "source": "import { World, on } from \"neo\";\nexport default class Hello extends World { state = { n: 0 }; @on(\"tick\") t() { this.state.n += 1; } }" }

script.list#

The running scripts and the script log. Takes no arguments.

Returns:

FieldDescription
tickThe script runtime's tick count.
sim_msSimulation time in milliseconds.
chainThe tick's hash chain over every script's state hash (hex).
scriptsOne entry per script, in load order (below).
logLoads, reloads, refusals, unloads, pauses and manifest problems, newest last (up to 200 lines, each starting with [tick n]).

Each entry in scripts:

FieldDescription
nameThe script's name.
principal"creator" for the game's own scripts, or { "player": "<id>", "roles": [...] }.
pausedWhether it's paused.
faultsHow many faults it has had.
last_faultThe last fault's text (handler: reason), or null.
fuel_usedInstructions used in the last tick.
fuel_per_tickIts per-tick budget.
state_hashThe first 8 bytes of its state hash (hex).

script.pause, script.resume, script.unload#

NameTypeDescription
namestringRequired. The script's name.

Returns: { "queued": "<name>" }. Applies on the next fixed tick.

  • Pause: the script stops running. It gets no events or ticks while paused.
  • Resume: the script runs again; its clock catches up and timers that came due resolve.
  • Unload: the script is removed. Loading it again starts from fresh state.

script.types#

The script API declarations, generated from the game's #[derive(ScriptExpose)] types narrowed by neo.toml's [script], as one kind of script sees them.

NameTypeDescription
formatstringRequired. "ts" (a neo.d.ts for JavaScript editors), "py" (a neo.pyi for Python editors), "md" (a Markdown reference) or "json".
playerbooleantrue for what a player's live script sees. Default: the game's own scripts.
roleslist of stringsThe player's roles (with player: true).

Returns: for ts, py and md, { "format": "...", "text": "..." }. For json, the same JSON as script.api.

Names in the output follow the cross-language rule: camelCase in ts, snake_case in py.

script.api#

What the game's own scripts can touch, as JSON: the description agents write scripts against. Takes no arguments.

Returns: { "kinds": [...] }, one entry per visible kind:

FieldDescription
kindThe kind name.
docThe type's doc comment.
spawnableWhether scripts may spawn it.
fieldsEach with name (snake_case), js (camelCase), type_ts, type_py, read, write, range ([min, max] or null) and doc.
methodsEach with name, js, args (name, type_ts, type_py), returns_ts, returns_py, rate_per_s (0 when there's no rate) and doc.

editor.scripts.panel#

NameTypeDescription
openbooleanShow (true, the default) or hide (false) the Scripts panel.

Returns: { "open": true } or { "open": false }.

editor.scripts.files#

The project's script files in assets/scripts (.js and .py). Takes no arguments.

Returns: a list of { "name", "path", "running" }, where running says whether a script with that name is running.

editor.scripts.edit#

NameTypeDescription
namestringRequired. The script file's name, without the extension.

Opens the file in Source mode's code editor. Saving it hot-reloads it in the running game when live reload is on. Returns: { "opened": "<path>" }. See Source mode.

editor.scripts.check#

Runs the check: compiles every JavaScript script and module in the project, validates [script] against the kinds the game exposes, writes neo.d.ts and neo.pyi into assets/scripts, and runs the game's own script tests if it has any. Takes no arguments.

Returns: { "ok": true | false, "report": [...] }, one line per file, check and test.

editor.scripts.live_reload#

NameTypeDescription
onbooleanRequired. Whether changed script files hot-reload in the running game. On by default.

Returns: { "live_reload": true } or { "live_reload": false }.

When a running script's file changes, it reloads with its state kept. When a module file changes, scripts loaded or reloaded after that use the new version.

See also#