Skip to content

Running scripts

Modlumi runs JavaScript. If you write TypeScript, compile it first with tsc (see Getting started) and run the emitted .js file. Modlumi refuses .ts files with a reminder to compile them.

Choose File → Run Script… and pick a .js file. The script runs against the open model and the interface pauses until it finishes. Output from console.log, errors and their stack traces appear in Window → Script Console and in the application log.

You can also type JavaScript into the box at the bottom of Window → Script Console, much like the console of a browser or Node.js:

> const m = modlumi.activeModel
> m.entities.length
4
> for (const entity of m.entities) {
... console.log(entity.type)
... }
Edge
Edge
Edge
Edge

The console prints the value of each input unless it’s undefined, with strings in quotes. An input that isn’t finished yet, such as a for loop whose closing brace is still missing, continues with a ... prompt. To run an unfinished input anyway, for example to see why it doesn’t parse, enter an empty line. Up and Down recall earlier input, and right-click the output to copy or clear it.

Variables and functions stay defined for later inputs, and entities you keep in variables stay usable while the same model is open. await works at the top level of an input, so await somePromise prints its result.

Window → Script Editor is a JavaScript editor inside Modlumi, with syntax highlighting, line numbers, find and replace (Ctrl+F) and undo. Use its buttons or shortcuts to make a new script (Ctrl+N), open one (Ctrl+O) and save it (Ctrl+S, or Ctrl+Shift+S to save a copy). Modlumi asks before throwing away unsaved changes, including when you quit.

Press Run or F5 to save the script and run it against the open model. Output appears in the Script Console. If the script fails, the editor marks the failing line in red and shows the error below the code; hover the line for the full message.

To try out part of a script, press Run Selection or Shift+Enter. It runs the selected code, or the current line, in the Script Console and moves to the next line. On a line that opens a block, such as a for loop ending in {, the lines up to the matching closing bracket run with it. Variables it creates stay available in the console, so you can inspect them there.

The editor reopens the script you had open when you last closed Modlumi. Recent lists the last eight scripts you opened or saved.

Scripts started from the app, including console inputs, stop after 60 seconds, so an endless loop can’t freeze Modlumi. Press Esc to stop a script sooner; after a moment the window title shows this hint. See Limits and sandbox for what happens when a script is stopped.

Pass --run-script to run a script once, after the model loads:

Terminal window
modlumi --run-script outline.js
modlumi model.skp --run-script inspect.js
modlumi --run-script outline.js --snapshot-viewport outline.png

If the model fails to load or the script fails, Modlumi exits with a nonzero status and skips any requested snapshots. A successful script leaves the window open, unless snapshots were requested; then Modlumi takes them and exits.

Startup scripts have no time limit. Add --script-timeout SECONDS to stop one that runs too long.

Add --background to run a script without a window, a display or file dialogs. Modlumi exits when the script finishes:

Terminal window
modlumi --background --run-script outline.js
modlumi --background model.skp --run-script inspect.js --script-timeout 60

An optional .skp or .modl file loads before the script; otherwise the script starts with an empty model. Modlumi exits with status zero when the script finishes normally and nonzero when loading or the script fails, or when it’s stopped by --script-timeout. Output and stack traces are written to the console afterward.

Background runs can’t be combined with --mcp, --snapshot-viewport or --snapshot-ui.

Each file runs as an ES module in a fresh JavaScript engine, so nothing from an earlier run, or from the console, is visible to it. A script can import other modules with relative paths:

main.js
import { square } from "./shapes.js";
square(modlumi.activeModel, 2);
shapes.js
/**
* @param {modlumi.Model} model
* @param {number} size
*/
export function square(model, size) {
model.operation("Square", () => {
model.entities.addEdges([[0, 0, 0], [size, 0, 0], [size, size, 0], [0, size, 0], [0, 0, 0]]);
});
}

Import paths name the .js files, also when you compile them from TypeScript. import.meta.url is the file: URL of the running module, and import.meta.main is true only for the script you ran. The modlumi API is a global and can’t be imported. Console inputs aren’t modules; they can import only by absolute path, with await import("/path/to/module.js").

Models, entities, selections and collections borrow the open document. They work during the run that created them, and in later console inputs while the same model is open. Once a different model is opened, using one throws ReferenceError. Points, vectors, transformations and cameras are plain values and stay usable.