Script API Reference
All functions and objects available in the Muxit script sandbox. All calls are synchronous — no await needed (await still works if you prefer).
Device Access
| API | Description |
|---|---|
connector(name) | Get a device proxy by name |
device(name) | Alias for connector() |
const psu = connector("psu");
psu.voltage // read property (no parens)
psu.voltage = 12 // write property (assignment)
psu.reset() // execute action
psu.rampTo(24) // call custom methodLogging
| API | Description |
|---|---|
log.info(msg) | Info-level log |
log.warn(msg) | Warning-level log |
log.error(msg) | Error-level log |
log.debug(msg) | Debug-level log |
console.log(msg) | Alias for log.info() |
Events
| API | Description |
|---|---|
emit(event, data) | Publish event (namespaced as script:<event>) |
on(event, handler) | Subscribe to events (auto-cleaned on stop) |
stream(connector, stream, data) | Emit stream data to dashboards |
Timing
| API | Description |
|---|---|
delay(ms) | Sleep (abortable on stop). Always use in loops to avoid excessive CPU usage |
timestamp() | Current ISO 8601 UTC string |
AI
| API | Description | Tier |
|---|---|---|
ai(prompt) | Single-shot LLM call, returns string response | Maker |
ai(prompt, image) | LLM call with base64 JPEG image — the model sees the picture and answers in text | Maker |
say(text, opts?) | Send message to Chat Panel; spoken aloud when the speaker toggle in the top status strip is on. opts.emotion hints at delivery style. | Free |
ai() uses Muxit's managed AI proxy and requires a Maker subscription. On the Free tier it throws AI_REQUIRES_PRO (legacy error name — the actual gating tier is Maker). The image overload runs on the same Maker gate; what's gated to Pro is the agentic Vision AI tool surface in the Chat Panel and MCP (take_snapshot, identify_objects, OpenCV trackers, spatial mapping) — not the explicit ai(prompt, image) call from a script. say() uses browser text-to-speech and is available on all tiers.
say() details:
say(text, opts?) queues text for the dashboard's text-to-speech engine and shows it as a script bubble in the chat panel. Calls from any script land in a single FIFO queue on the dashboard so they can never overlap or replay as a burst — utterances finish in the order they were emitted.
opts.emotion is a hint string ("excited", "sad", "whisper", "serious", …). The browser TTS engine approximates emotions with rate/pitch tweaks; server-side TTS providers (added in a later release) honour them natively.
say("Reading complete.")
say("Calibration done!", { emotion: "excited" })
say("Limit switch triggered.", { emotion: "serious" })On Free? Use Muxit's MCP server with your own AI client (Claude Desktop, Claude Code, ChatGPT) — it's free on every tier and exposes the same connectors and scripts. See the AI guide.
ai() details:
- Returns a text string (non-streaming, ~1024 max tokens)
- Uses the LLM provider configured in Settings (same as AI chat)
- No tool calling — for quick inference only (classify, extract, describe)
- No conversation history — each call is independent
imageparameter: base64-encoded JPEG (e.g., fromconnector('webcam').snapshot)
// Text inference
const result = ai("Is 85°C too hot for this motor?");
// Vision analysis
const snap = connector('webcam').snapshot;
const analysis = ai("Is the part in the correct position?", snap);User Interaction
Block the script until a dashboard user answers, or the timeout fires.
| API | Description |
|---|---|
ask.confirm(message, opts?) | Yes/No prompt — returns true / false |
ask.choose(message, choices, opts?) | Pick one of the strings in choices |
ask.text(message, opts?) | Free-form text — returns the user's string |
Options (opts):
| Field | Description |
|---|---|
timeout | Milliseconds (≥ 1000) to wait before falling back to default / throwing |
default | Value returned if the timeout expires. Omit to throw PROMPT_TIMEOUT |
requireObserver | When true, the timeout clock only ticks while ≥ 1 dashboard is subscribed |
- Return values are indistinguishable from human answers — consult script logs if you need to know whether a default was used.
- An omitted
timeoutwaits indefinitely (until the script is stopped). timeout < 1000is rejected at call time as a likely typo (seconds vs milliseconds).
// Yes/no with a 30 second timeout, defaulting to "no".
if (!ask.confirm('Home all axes before run?', { timeout: 30000, default: false })) {
log.warn('User declined — skipping homing');
}
// Force operator attendance: clock pauses if all dashboards disconnect.
const port = ask.choose('Select instrument port', ['COM1','COM2','COM3'], {
requireObserver: true,
timeout: 120000,
default: 'COM1',
});
// No default → throws PROMPT_TIMEOUT if nobody answers.
const label = ask.text('Run label?', { timeout: 60000 });File I/O
The sandbox has no fs, require, or import — for file access, use a FileAccess connector (the default workspace ships one named files, sandboxed to workspace/data/).
Bind the path once with .file(path) and call methods on the returned handle — the rest of the script doesn't repeat the path:
| API | Description |
|---|---|
connector('files').file(path) | Returns a path-bound handle |
f.write(content) | Overwrite a text file (creates parent dirs) |
f.append(content) | Append to a text file — ideal for logs/CSV |
f.read() | Read as UTF-8 text |
f.writeBinary(base64) / f.readBinary() | Binary I/O via base64 |
f.exists / f.size / f.info() | Metadata |
f.rename(newPath) / f.delete() | Mutations (rename updates the handle in place) |
connector('files').listFiles({ path }) / listDirs({ path }) | Directory listings |
const files = connector('files');
const csv = files.file('temps.csv');
csv.write('time,temp_c\n');
while (script.running) {
csv.append(`${timestamp()},${connector('sensor').temperature}\n`);
delay(1000);
}Open temps.csv in a tab — the chart/table refreshes automatically each time the script appends a row. Full action list in the FileAccess driver reference.
Script Lifecycle
| API | Description |
|---|---|
script.running | true while active, false after stop |
script.name | This script's filename (without .js) |
Pressing Stop interrupts the V8 engine synchronously — statements after the main loop, and finally blocks, are not guaranteed to run. Put setup and safe-state writes before the loop and design each iteration to be safe to abort.
Standard Globals
Math, JSON, Date, parseInt, parseFloat, isNaN, isFinite, Number, String, Boolean, Array, Object, Map, Set, Promise
Not Available
require, import, fs, process, net, http, child_process, eval, Proxy, Reflect, global, globalThis.
For filesystem access, use a FileAccess connector instead of require('fs').
For detailed explanations and examples, see the Script Guide.