JavaScript essentials
ApplesauceOS provides JavaScript plus device automation APIs. You can call functions such as openApp() and ocr() directly; their at.openApp() and at.ocr() spellings refer to the same APIs. UIHelper, ObjC, RemoteObjC, C and RemoteC are also available globally and through at.
Runtime helpers such as require, fetch, timers and console are global. Do not assume every runtime property has an at alias.
Variables, decisions and reusable functions
function openSettings() {
if (!openApp("com.apple.Preferences")) {
throw new Error("Settings did not open");
}
}
openSettings();
console.log("Current app:", frontMostAppId());Use const for a value you will not reassign and let for a changing counter. An if chooses what to do. A function groups reusable work. throw new Error(...) makes a failed assumption visible in the run output.
Units are part of the API
| Operation | Units |
|---|---|
| Touch positions, UIHelper rectangles, visual matching | Native screen pixels, top-left origin |
| UIHelper timeouts/intervals, tap hold, timers, async HTTP timeout | Milliseconds |
| Swipe duration, waitForApp timeout, execResult timeout, showNotice | Seconds |
| usleep / msleep / sleep | Microseconds / milliseconds / seconds |
| OCR | Points by default; request coordinates: "pixels" for screen touches |
getScreenInfo() reports portrait panel dimensions, not a scale field. Use current orientation when calculating screen-relative gestures. Coordinates from a resized screenshot must be mapped to the original image.
Handle the correct error shape
const [items, error] = ocr({coordinates: "pixels"});
if (error) throw new Error(error);
console.log(items.length);OCR and visual search return a pair. File-writing helpers return an error string or null. UIHelper and native calls throw on failures. execResult returns status fields. Each reference page states the contract; do not assume all APIs return a boolean.
Asynchronous work
Saved scripts do not support top-level await. Wrap asynchronous code in an async function and let failures remain visible:
(async () => {
const response = await fetch("https://example.com", {timeout: 5000});
if (!response.ok) throw new Error("HTTP " + response.status);
console.log(await response.text());
})().catch(error => {
console.error(error.message);
throw error;
});Pending HTTP requests and timers keep the runtime active. Clear intervals when finished. A detached Promise with no tracked work is not a completion mechanism. Synchronous sleeps delay timer callbacks. Stop cancels pending runtime work but cannot undo an already executed native action.
MCP run_javascript is different: its source is an async function body, so it supports return and await. start_script uses the saved script/project behavior described above.
Keep loops bounded
Prefer waitForElement over fixed long sleeps. Use a timeout and a maximum number of attempts for retries or scrolling. Never catch and ignore every error: this can hide cancellation, invalid selectors and real failures.
For alerts and alternate screen states, use the interruption-handling pattern.