Script API
This page organizes the script API by task. For live autocomplete and complete signatures in VSCode, add this line at the top of a script:
/// <reference path="./.cursorcrane/cursorcrane.d.ts" />Start a Script
Section titled “Start a Script”Every script needs meta and run(ctx):
/** @type {CursorCrane.Meta} */const meta = { type: "action", name: "Example", permissions: [],};
/** @param {CursorCrane.Context} ctx */async function run(ctx) { ctx.toast("Done");}meta field | Purpose |
|---|---|
type | "action" performs a one-off action; "form" opens a form. |
presentation | Optional for forms. "panel" suits continued work; "transient" closes on focus loss. |
name | The script name shown in Cursor Crane. |
permissions | The permissions required by the script. |
Available permissions are "accessibilityAPI", "keyboard", and "mouse". An API cannot be used unless the script declares its required permission.
Find Apps and Windows
Section titled “Find Apps and Windows”Use ctx.applicationManager to inspect running apps:
| Member | Purpose |
|---|---|
applications | All available apps. |
getApplicationByBundleIdentifier(id) | Finds an app by bundle identifier. |
getApplicationByPid(pid) | Finds an app by process ID. |
Each Application has name, bundleIdentifier, and pid.
Use ctx.windowManager to find and switch windows:
| Method | Purpose |
|---|---|
getWindowsByPid(pid) | Gets an app’s windows. |
getWindowsByBundleIdentifier(id) | Gets windows by app. |
getWindowById(windowId) | Finds a window by ID. |
getActiveWindow() | Gets the window currently in use. |
getPreviousWindow() | Gets the previously used window. |
activateWindow(windowId) | Switches to a window. |
Window has title, windowId, and its application.
Find and Control Interface Elements
Section titled “Find and Control Interface Elements”ctx.elementInspector.getElementByPid(pid) gets an app’s interface-element entry point and requires accessibilityAPI. From there, use getWindows() to find the window, then find its buttons, text fields, and list rows.
const application = ctx.elementInspector.getElementByPid(window.application.pid);const root = application?.getWindows().find( item => item.windowId === window.windowId);const saveButton = root?.queryElements('Button[title="Save"]')[0];Element Information
Section titled “Element Information”| Property | Purpose |
|---|---|
title | The title provided by the element. |
displayTitle | A title that is more suitable to show to a person. |
label, description | Additional information about the element. |
kind | The element type, such as Button or TextField. |
windowId | The ID of the window containing the element. |
rect / frame | The element’s on-screen position and size. |
Traverse and Query Elements
Section titled “Traverse and Query Elements”| Method | Purpose |
|---|---|
getChildren() | Gets direct children. |
getVisibleChildren() | Gets children that are currently visible. |
getParent() | Gets the parent element. |
getFocusedWindow() | Gets the app’s focused window. |
getWindows() | Gets the app’s windows. |
getWindow() | Gets the element’s containing window. |
queryElements(selector, maxCount?) | Searches all elements in a window. It traverses children and can block noticeably on a large hierarchy. |
queryVisibleElement(selector, maxCount?) | Searches only the currently visible content. |
getStringValue() | Gets the current value as text, such as the content of a text field. |
getIntValue() | Gets the current value as an integer. |
getDoubleValue() | Gets the current value as a floating-point number. |
See Element Selectors for selector syntax.
Element Actions
Section titled “Element Actions”These methods require accessibilityAPI and can be awaited:
| Method | Purpose |
|---|---|
performPress() | Triggers the element’s main action. |
setStringValue(value) | Sets a new text value on an element. |
setIntValue(value) | Sets a new integer value on an element. |
setDoubleValue(value) | Sets a new floating-point value on an element. |
performClick() | Moves to an element and clicks it. |
performMoveCursorTo() | Moves to an element. |
performShowMenu() | Opens an element’s menu. |
getActions() | Lists the actions supported by an element. |
performAction(identifier) | Triggers a particular action. |
Choose the getter or setter that matches the value type used by the element.
Keyboard, Mouse, and Feedback
Section titled “Keyboard, Mouse, and Feedback”ctx.keyboard
Section titled “ctx.keyboard”Requires keyboard. All three methods return a Promise:
await ctx.keyboard.pressKey("a", ["command"]);await ctx.keyboard.releaseKey("a", ["command"]);await ctx.keyboard.pressAndReleaseKey("return", []);Use "shift", "control", "option", and "command" as modifiers.
ctx.mouse
Section titled “ctx.mouse”Requires mouse:
| Method | Purpose |
|---|---|
moveTo(x, y) | Moves the pointer smoothly. |
warpTo(x, y) | Moves the pointer immediately. |
click(button, modifiers?) | Clicks; 0 is left, 1 is right, and 2 is middle. |
doubleClick(button, modifiers?) | Double-clicks. |
rightClick(modifiers?) | Right-clicks. |
ctx.shell
Section titled “ctx.shell”Requires shell. execute(command) runs a non-interactive zsh command and returns its output:
const result = await ctx.shell.execute("git status --short");if (result.exitCode === 0) { ctx.toast(result.stdout || "Working tree is clean");}The result contains stdout, stderr, and exitCode. Commands share the script’s execution timeout, and output is limited to 1 MiB per stream.
ctx.toast and ctx.logger
Section titled “ctx.toast and ctx.logger”Use ctx.toast(message) for brief feedback. ctx.toast.highlight(rect, text?, timeout?) highlights an area on screen and can show a short hint below it.
ctx.toast("Finished");ctx.toast.highlight(element.rect, "Save button", 3);ctx.logger.log(), error(), warn(), info(), and debug() write to the script log. They are useful for checking progress and errors while you develop a script.
Create a Form
Section titled “Create a Form”A form script returns an array from run(ctx). Every item needs a unique id:
function run(ctx) { return [ { id: "selector", kind: "textInput", title: "Selector", value: "Button", }, { id: "run", kind: "button", title: "Query", submit: true, onClick: formCtx => { formCtx.toast(`Searching for ${formCtx.formData.selector}`); }, }, ];}| kind | Common fields | Best for |
|---|---|---|
label | text, value? | Showing instructions or results. |
numberInput | title, value?, min?, max?, step? | Entering a number. |
textInput | title, value?, placeholder? | Entering one line of text. |
select | title, value?, options | Choosing from a list. |
checkbox | title?, value? | Checking an option. |
toggle | title?, value? | Turning an option on or off. |
button | title, submit?, onClick? | Performing an action. |
Editable items can provide onChange(newValue, ctx); buttons use onClick(ctx). Both can be async functions.
A form ctx also provides:
| Member | Purpose |
|---|---|
formData | Reads the current form values. |
updateForm(items) | Replaces the form. A matching item without a new value preserves the person’s current input. |
closeForm() | Closes the current form. |
People can use Tab, Shift + Tab, and arrow keys to move through a form. When a button is focused, Enter or Space activates it. A button marked submit: true can be activated from anywhere with Command + Enter.
Handle Errors
Section titled “Handle Errors”Use try / catch while developing a script to show a clear message:
try { await ctx.mouse.moveTo(100, 100);} catch (error) { ctx.toast(String(error));}If a script calls an API without the required permission, uses an invalid selector, or cannot reach its target, that call fails. Add a toast or a form message for common failures so the script stays easy to use.