What it does
terminal
In-engine shell terminal (zui). Mounts a resizable terminal window
that runs commands through the same bash MCP tool agents use, giving
full access to the VFS (ls, cat, grep, find, echo, etc.).
Commands are typed on the bottom input row and submitted on Enter;
output streams into the scroll area above. Built-in clear / cls
commands clear the history without round-tripping through the shell.
Exports
M.createState() -> TerminalState— make a fresh terminal state (empty history, no pending requests).M.buildWidget(state: TerminalState) -> any— build the window widget tree from a state.M.mount(opts: MountOpts?) -> TerminalHandle— register the terminal as a UI screen and return a handle to tick + tear down.
Types:
TerminalLine = { text: string, color: string }TerminalState = { lines: { TerminalLine }, input: string, waiting: boolean, pending: { [any]: boolean }, max_lines: number }MountOpts = { state?: TerminalState, screen_id?: string }TerminalHandle = { state: TerminalState, update: (dt?) -> (), onCallback: (id: string, data: any) -> (), destroy: () -> () }
Usage
local Terminal = require("@builtin::modules.engine.editor.terminal")
local handle = Terminal.mount()
-- in the host tick loop:
handle.update(dt)
-- on shutdown:
handle.destroy()
Notes
- The terminal does not own a Luau task — the host is responsible for
calling
handle.update(dt)every tick. Enter detection runs through aZin.bindings.evalPressedbinding descriptor because widget callbacks are unreliable for Enter. - Pending MCP requests are tracked on
state.pending; output for each request is appended (colour-coded red onis_error) and the "..." waiting marker disappears when the pending set drains. - History is bounded at
max_lines(default 1000); the oldest lines drop off the front as new output arrives. clear/clsare intercepted before dispatch so they never hit the shell.
Discussion
Scoped to this part · feeds back into the world's score.
Sign in to post.sign in
No comments yet. Be the first.