Log inGet started

shell

Updated October 20, 2026

Engine emulated Unix shell — same shell that powers the MCP bash tool.

require("@builtin::modules.api.engine.shell") -- shell (also available as global 'shell')

The shell namespace: 6 functions.

globals/shell/run

shell.run(command: string, sessionKey: string?) -> ShellResult

Execute a command in the engine's emulated Unix shell and return once it has completed. This is the same shell as the MCP bash tool — 60+ builtins (ls, cat, grep, find, echo, ...) operating on the virtual scene filesystem. A command that runs Luau (run, luau, zm, zero) needs the engine's frame loop, and a command whose work is a wait (sleep) cannot take its interval while holding it, so from a coroutine the whole line is queued to run off the frame loop and this yields until it finishes; everything else runs inline. The queued run starts the line again from the top, so a line that had already written a file, sent a request, read input or started a background job comes back with the explanation in stderr and shell.runAsync as the way to run it whole.

Parameters

  • command string — Shell command to execute.
  • sessionKey string (optional) — Which caller's shell session the command runs in. A session holds what a command leaves behind: the directory cd moved to, exports, shell functions, set -e. It hands that to the next command run under the same key. Omit it and the command runs in the session of the caller this code runs on behalf of, the one that caller's bash commands also use; code with no attested caller behind it runs in the session every caller that names none shares.

Returns ShellResult — Command result { stdout, stderr, exitCode, ok }.

local r = shell.run("ls /zero/source")

globals/shell/runAsync

shell.runAsync(command: string, sessionKey: string?) -> string

Asynchronous version of shell.run. Returns a promise ID that resolves to a JSON-encoded result string. Use with task.await().

Parameters

  • command string — Shell command to execute.
  • sessionKey string (optional) — Which caller's shell session the command runs in. A session holds what a command leaves behind: the directory cd moved to, exports, shell functions, set -e. It hands that to the next command run under the same key. Omit it and the command runs in the session of the caller this code runs on behalf of, the one that caller's bash commands also use; code with no attested caller behind it runs in the session every caller that names none shares.

Returns string — Promise ID — pass to task.await() to get the JSON result.

local json = task.await(shell.runAsync("find /zero -name '*.luau'"))

modules/shell/run

run(command: string, sessionKey: string?): ShellResult

Execute a command in the engine's emulated Unix shell and return once it has completed. This is the same shell as the MCP bash tool — 60+ builtins (ls, cat, grep, find, echo, ...) operating on the virtual scene filesystem. A command that runs Luau (run, luau, zm, zero) needs the engine's frame loop, and a command whose work is a wait (sleep) cannot take its interval while holding it, so from a coroutine the whole line is queued to run off the frame loop and this yields until it finishes; everything else runs inline. The queued run starts the line again from the top, so a line that had already written a file, sent a request, read input or started a background job comes back with the explanation in stderr and shell.runAsync as the way to run it whole.

Parameters

  • command string — Shell command to execute.
  • sessionKey string? (optional) — Which caller's shell session the command runs in. A session holds what a command leaves behind: the directory cd moved to, exports, shell functions, set -e. It hands that to the next command run under the same key. Omit it and the command runs in the session of the caller this code runs on behalf of, the one that caller's bash commands also use; code with no attested caller behind it runs in the session every caller that names none shares.
local r = shell.run("ls /zero/source")

modules/shell/runAsync

runAsync(command: string, sessionKey: string?): string

Asynchronous version of shell.run. Returns a promise ID that resolves to a JSON-encoded result string. Use with task.await().

Parameters

  • command string — Shell command to execute.
  • sessionKey string? (optional) — Which caller's shell session the command runs in. A session holds what a command leaves behind: the directory cd moved to, exports, shell functions, set -e. It hands that to the next command run under the same key. Omit it and the command runs in the session of the caller this code runs on behalf of, the one that caller's bash commands also use; code with no attested caller behind it runs in the session every caller that names none shares.
local json = task.await(shell.runAsync("find /zero -name '*.luau'"))

typed/builtin//modules/api/engine/shell/shell/run

shell.run(command: string, sessionKey: string?) -> ShellResult

Execute a command in the engine's emulated Unix shell and return once it has completed. This is the same shell as the MCP bash tool — 60+ builtins (ls, cat, grep, find, echo, ...) operating on the virtual scene filesystem. A command that runs Luau (run, luau, zm, zero) needs the engine's frame loop, and a command whose work is a wait (sleep) cannot take its interval while holding it, so from a coroutine the whole line is queued to run off the frame loop and this yields until it finishes; everything else runs inline. The queued run starts the line again from the top, so a line that had already written a file, sent a request, read input or started a background job comes back with the explanation in stderr and shell.runAsync as the way to run it whole.

Parameters

  • command string — Shell command to execute.
  • sessionKey string (optional) — Which caller's shell session the command runs in. A session holds what a command leaves behind: the directory cd moved to, exports, shell functions, set -e. It hands that to the next command run under the same key. Omit it and the command runs in the session of the caller this code runs on behalf of, the one that caller's bash commands also use; code with no attested caller behind it runs in the session every caller that names none shares.

Returns ShellResult — Command result { stdout, stderr, exitCode, ok }.

local r = shell.run("ls /zero/source")

typed/builtin//modules/api/engine/shell/shell/runAsync

shell.runAsync(command: string, sessionKey: string?) -> string

Asynchronous version of shell.run. Returns a promise ID that resolves to a JSON-encoded result string. Use with task.await().

Parameters

  • command string — Shell command to execute.
  • sessionKey string (optional) — Which caller's shell session the command runs in. A session holds what a command leaves behind: the directory cd moved to, exports, shell functions, set -e. It hands that to the next command run under the same key. Omit it and the command runs in the session of the caller this code runs on behalf of, the one that caller's bash commands also use; code with no attested caller behind it runs in the session every caller that names none shares.

Returns string — Promise ID — pass to task.await() to get the JSON result.

local json = task.await(shell.runAsync("find /zero -name '*.luau'"))
  • api
  • reference