Scripting

When a shortcut is executed it is possible to run JavaScript code snippets before or after execution. You'll find the corresponding settings in the shortcut editor in the "Scripting" section.

Scripting Option in Shortcut Editor Scripting Editor

Additionally, you'll find an option in the app's settings (labeled "Global Scripting") that allows you to run code before the execution of every shortcut, which can be used to define shared functions.

Most of JavaScript's built-in functionalities can be used normally, e.g., to manipulate Strings or Arrays. Additionally, the app has some functions and utilities built in for convenience, all of which are documented below.

Using these code blocks, there are a number of things you can achieve. See the examples below for inspiration.

Pro-tip: Writing code on a phone is tedious. If you're intending to write longer blocks of code, I recommend you check out the Web Editor for more convenient configuration of your shortcuts.

Handling the Response

You can access the response of your HTTP request via the response object.

Please note that the response object is only available in the "Run on Success" code block, as well as in the "Run on Failure" code block in case there was an HTTP response (i.e., a status code of 4xx or 5xx), and will otherwise be null.

Getting the Response Body

The response body is available as a string via response.body.

const myBody = response.body;

If you know that the response body is in JSON format, you can use JSON.parse() to turn it into a JS object, array or primitive.

const myJson = JSON.parse(response.body);

Getting Response Headers

The response headers are available as an object (key-value-pairs) via response.headers. Each key corresponds to the name of the header and its value is an array of strings of all the headers with that name.

There is also a convenience function response.getHeader(name) which can be used to get the value of a specific header by its name. If there are multiple headers with that name, the last one is returned, and if there are none, null is returned.

const contentType = response.headers['Content-Type'][0];

const contentLength = response.getHeader('Content-Length');

Getting the Status Code

The response's HTTP status code is available as an integer via response.statusCode.

const isNotFound = response.statusCode == 404;

Getting Cookies

The response's cookies are available as an object (key-value-pairs) via response.cookies. Each key corresponds to the name of the cookie and its value is an array of strings of all the cookies with that name.

There is also a convenience function response.getCookie(name) which can be used to get the value of a specific cookie by its name. If there are multiple cookies with that name, the last one is returned, and if there are none, null is returned.

const myCookieValue = response.cookies['MyCookieName'][0];

const myCookieValue2 = response.getCookie('MyCookieName2');

If you need more details about a cookie (e.g. its expiration timestamp) you can use response.headers['Set-Cookie'] to read out the cookie headers directly.

Errors

Please note that the response object will be null if there was no response from the server, i.e., in case of a network error. In that case, you can inspect the networkError to get a string describing the error.

Reading & Writing Variables

In the app you can create global variables to be used in your shortcuts, e.g. to dynamically insert values for a URL, a query parameter or part of the request body. You'll find the variable editor via the "Variables" option in the menu in the app's main screen.

This section explains how you can interact with these variables from a script.

getVariable

You can access the value of any of your variables via the getVariable() function. Simply pass the variable's name or ID as a parameter.

const myValue = getVariable('myVariable');

Please note that the returned value will always be a string. If the variable does not exist an error is raised.

setVariable

You can store a value as a string into a variable via the setVariable() function. Simply pass the variable's name or ID as the first parameter and the value you want to store as the second parameter.

setVariable('myVariable', 'Hello World');

Please note that there is a size limit of 30'000 characters. If you set a value larger than that, it will be used unaltered for the current execution, but the value that is stored will be truncated.

If the variable does not exist an error is raised.

As an optional third parameter you can pass a boolean. If it is true, the new value will be stored but not used immediately for the current execution. This is useful for variable types which support the 'Remember value' feature (such as Date Input, Time Input, Text Input, etc.) as it allows to change the stored previous value which is used as the default selected value.

setVariable('myVariable', 'Hello World', true); // only changes the stored value, but variable will still resolve normally if used afterwards

Getting Information about the Current Shortcut

You can easily retrieve information about the current shortcut and the category it belongs to from the shortcut object. This includes the shortcut's ID, name, description and whether it is hidden, as well as its category's ID and name.

shortcut.id;
shortcut.name;
shortcut.description;
shortcut.hidden;
shortcut.category.id;
shortcut.category.name;

Files

Selected Files

If your shortcut makes use of file parameters or uses the content of a file as the request body then you can access information about these files using the selectedFiles array. Each selected file has an entry, allowing you to read out its file name, size (in bytes), media type and potentially some additional meta information.

const numberOfFiles = selectedFiles.length;

selectedFiles[0].name;
selectedFiles[0].size; // AFTER cropping/rotating
selectedFiles[0].type;
selectedFiles[0].meta;

Each file also has a unique ID, which is currently only useful if you want to forward these files to another shortcut using the enqueueShortcut function.

selectedFiles[0].id;

const allFileIds = selectedFiles.map(file => file.id);

The meta field currently only provides information about images and is otherwise an empty object. It allows to read out an image's orientation and the timestamp of when it was created (in "yyyy-MM-dd HH:mm:ss" format):

const myMeta = selectedFiles[0].meta;

/*
myMeta might look like this now:
{
  'created': '2022-12-31 23:59:59',
  'orientation': 1,
}
*/

The orientation field is an integer with the following meaning:

Reading and Writing Files

If you want to read from an existing file or write data to a file, you first need to mount the directory which contains the file. This can be done via the "(Mounted) Directories screen. Once you have a mounted directory, you can use the getDirectory() function to get a handle to it. Pass the name of the mounted directory as the first parameter. This handle then lets you read and write files, using the readFile(), writeFile() and appendFile() functions.

For readFiles(), pass the name or path of the file you wish to read from as the first parameter, relative to the mounted directory. The file must exist, otherwise an error is raised. As an optional second parameter, you can pass the encoding that should be used to read the file, which defaults to UTF-8. The file's entire content is returned as a string.

const dir = getDirectory('myMountedDirectory');
const fileContent = dir.readFile('someDir/someFile.txt');

For writeFile() and appendFile(), pass the name or path of the file you wish to write to as the first parameter, relative to the mounted directory. If the file or a directory along its path does not yet exist, it is automatically created.

For writeFile(), if the file already exists, its contents will be replaced without warning! For appendFile(), the new content will be appended and the existing file content is preserved.

As the second parameter, pass the content you wish to write into the file. If this is an array, Uint8Array or Int8Array, it will be written as bytes. Otherwise, it will be written as a string, using UTF-8 encoding.

const dir = getDirectory('myMountedDirectory');
dir.writeFile('someFile.txt', 'New file content');
dir.appendFile('someFile.txt', [72, 101, 108, 108, 111]);

User Interaction

This section describes how you can interact with the user (i.e., you), during the execution of a shortcut, e.g., to ask for additional input, to confirm an action or to display information.

showToast

With this function you can display a toast message on the screen. Simply pass your message as the first parameter.

showToast('Hello World');

Please note that no toast will be displayed if the string you pass is empty. Also note that a toast will show at most two lines of text, so it is best suited for short messages.

showDialog

With this function you can display a dialog window on the screen. Simply pass your message as the first parameter, and optionally a title for the dialog as the second parameter. The dialog will be displayed until its "OK" button is pressed.

showDialog('My Message', 'My Title');

showDialog('You can also use <b>basic</b> <i>HTML</i> for formatting the message.');

Please note that no dialog will be displayed if the string you pass is empty.

prompt, confirm

Similar to how JavaScript works in a browser, you can use prompt() and confirm() to ask the user for input as part of a workflow.

prompt() will open a dialog window asking for text input. The entered text is then returned as a string. If the dialog is cancelled, null is returned instead. Pass a message in as the first parameter, and optionally a second parameter to prefill the text input field.

confirm() will open a confirmation dialog. It returns true if the dialog is confirmed, or false if it is cancelled. Pass a message in as the first parameter.

if (confirm('Are you sure?')) {
  // Do something only if the user clicked 'OK'
}
const myName = prompt('What is your name?');

promptNumber

You can use the promptNumberfunction to open an input dialog that asks for a number. The entered number will be the return value, or null if the dialog is cancelled. If the entered value is not a valid number NaN will be returned.

As the first parameter pass the text to display on the dialog. This must not be empty. As an optional second parameter you may pass a default value which is used to prefill the input field.

const myNumber = promptNumber('What is your favorite number?', 42);

promptPassword

The promptPassword() function opens a text input dialog that asks for a password. The entered password is then returned, or null if the dialog is cancelled. Pass a message in as the first parameter, and optionally a second parameter to prefill the text input field.

const myPassword = promptPassword("Please enter your password:");
const myPassword2 = promptPassword("Please enter your password:", "secret123");

promptColor

The promptColor() function opens a color picker. The selected color is returned in hex RGB (e.g. FF0000 for red), or null if the picker is cancelled. As an optional parameter you can pass in the preselected color.

const myColor = promptColor();
const myColor2 = promptColor("#FF0000");

promptDate

The promptDate() function opens a date picker. The selected date is returned, or null if the picker is cancelled. As the first parameter, you may pass the date format that should be used for the return value (defaults to yyyy-MM-dd), and as a second parameter you may pass the preselected date (in yyyy-MM-dd format).

const myDate = promptDate();
const myDate2 = promptDate("yyyy-MM-dd", "2050-12-31");

promptTime

The promptTime() function opens a time picker. The selected time is returned, or null if the picker is cancelled. As the first parameter, you may pass the time format that should be used for the return value (defaults to HH:mm), and as a second parameter you may pass the preselected time (in HH:mm format).

const myTime = promptTime();
const myTime2 = promptTime("HH/mm", "13:37");

showSelection

This function allows you to display a multiple-choice dialog from which an option can be picked. It takes one argument, which must be either an object consisting of key-value string pairs, or a list of strings. It returns the selected value as a string, or null if the dialog is closed without a selection (e.g. by pressing the back button).

// Using an array of strings
const starterPokemon = showSelection(['Bulbasaur', 'Charmander', 'Squirtle']);

// Using an object
const favoriteColor = showSelection({
  '#ff0000': 'Red',
  '#00ff00': 'Green',
  '#0000ff': 'Blue',
});

playSound

With this function you can play a notification sound. If no argument is passed, it will use the system's default notification sound. You can use the Code Snippet picker inside the app to select a different sound.

playSound();

speak

With this function you can have a piece of text be read out loud, using the device's text-to-speech engine. Simply pass the text you want to read as the first parameter, and optionally a language identifier as the second parameter.

Please note that only the first 400 characters will be read. Please also note that the second parameter is ignored if the language is not supported.

speak('Hello World');

speak('Dieser Text ist deutsch', 'de');

This function may not be supported by all devices.

vibrate

With this function you can cause the device to vibrate (if supported). As an optional first parameter, you can pass the number of the vibration pattern you want to use, and as an optional second parameter you can pass a boolean denoting whether the execution should wait for the vibration pattern to finish or not.

Vibration patterns:

vibrate(2, true);

scanBarcode

The scanBarcode function lets you scan a barcode (e.g. a QR code). On success the function returns the raw data of the barcode as a string. If the scanner is cancelled, null is returned instead.

const code = scanBarcode();

The scanning itself is done by an external app, specifically either QR Droid, Barcode Scanner or Binary Eye, which means you need to have that app installed for this function to work. This also means that the HTTP Shortcuts app itself will not need access to your camera directly.

Modify Shortcuts

This section lists all the built-in functions which you can use to modify existing shortcuts programmatically.

renameShortcut

With this function you can rename a shortcut. Simply pass the name or ID of a shortcut as the first parameter and the new name as the second one. You can also pass an empty string as the first parameter to target the current shortcut.

renameShortcut('Old Name', 'New Name');

changeDescription

With this function you can change the description of a shortcut. Simply pass the name or ID of a shortcut as the first parameter and the new description as the second one. You can also pass an empty string as the first parameter to target the current shortcut.

changeDescription('My Shortcut', 'New Description');

A shortcut's description is only visible in categories that use a list layout, not in those that use a grid layout.

changeIcon

With this function you can change the icon of a shortcut. Simply pass the name or ID of a shortcut as the first parameter and the name of the icon as the second one. You can also pass an empty string as the first parameter to target the current shortcut. Use the "Add Code Snippet" button in the app to select an icon. Alternatively, you can check the source code for all the available icons names (look for the prefix "R.drawable.", everything after it is a valid icon name).

changeIcon('My Shortcut', 'bitsies_lightbulb');

setShortcutHidden

This function allows you to show or hide individual shortcuts inside the app. Simply pass the name or ID of a shortcut as the first parameter and true or false as the second parameter. You can also pass an empty string as the first parameter to target the current shortcut.

setShortcutHidden('My Shortcut', true);

You can make hidden shortcuts visible via an option on the Settings screen.

setCategoryHidden

This function allows you to show or hide categories. Simply pass the name or ID of a category as the first parameter and true or false as the second parameter.

setCategoryHidden('My Category', true);

There must always be at least one non-hidden category. If you try to hide the last visible category with this, nothing will happen.

Control Flow

This section lists some of the options you have to control the execution flow of your script.

wait

The wait function allows you to delay execution by waiting (also called sleeping) for a specified number of milliseconds before continuing with the execution of the script.

wait(3000); // delay execution by 3 seconds

Please note that this is a blocking action, meaning that you will not be able to interact with the app during the waiting time.

abort, abortAll and abortAndTreatAsFailure

With the abort function you can abort the execution of the shortcut.

abort();

If the shortcut was called from another shortcut via the executeShortcut function, only the current shortcut will be aborted. If you want to abort also the calling shortcut, you can use abortAll().

As part of the "Run on Success" code block, you can also use the abortAndTreatAsFailure() function, which skips the rest of the "success" steps and instead treats the execution as a failure, meaning that the "Run on Failure" code will be run, as well as any other failure-related steps such as displaying an error message. You can use this in cases where the default behavior of only checking the HTTP status code is not enough to determine whether a request should be considered a success. As an optional parameter, you can pass a string which will be used as the error message.

// Basic example
abortAndTreatAsFailure();

// More realistic example
const responseBody = JSON.parse(response.body);
if (responseBody.status === 'error') {
  abortAndTreatAsFailure(responseBody.error);
}

Text Processing

This section lists some of the built-in text processing functions.

base64encode and base64decode

With the base64encode and base64decode functions you can encode or decode a given string using Base64.

const encoded = base64encode('Hello world');
const decoded = base64decode(encoded);

The return type of base64encode is a string, the returned value of base64decode is a Uint8Array. You can use toString() to convert it to a string if needed.

hash

With the hash function you can compute the hash of a given string. The first parameter denotes the hashing algorithm to use (supported algorithms are MD5, SHA-1, SHA-256, and SHA-512) and the second one the string to hash. The return value is in hex format.

const hashed = hash('SHA-256', 'Hello world');
// the value of `hashed` is '64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c' now.

hmac

With the hmac function you can compute the HMAC of a given message. The first parameter denotes the hashing algorithm to use (supported algorithms are MD5, SHA-1, SHA-256, and SHA-512), the second one the secret key, and the third one the message (as a string or byte array) for which to compute the HMAC. The returned value is a Uint8Array.

const myHMAC = hmac('SHA-256', 'my_key123', 'Hello world');
const myHMACasHex = toHexString(myHMAC);
// the value of `myHMACasHex` is '34d60d40202ae16ae3dd70c9715b1900f9fe30cf10af483e74ea8f6bef18bd09' now.

parseHTML

The parseHTML function allows to parse an HTML string into an object representation. Each HTML element is converted into a JS object with attributes name, attributes, children, and text (if any), as is showcased by the following example:

// Given some XML string
const myHTML = `<html lang="de">
  <head>
    <title>Hello World</title>
  </head>
  <body>
    <ul style="color: red">
      <li>Item 1</li>
      <li>Item 2</li>
    </ul>
  </body>
</html>`;

const result = parseHTML(myHTML);

/*
The result variable now holds the following object (blank text fields omitted for clarity):
{
  "name": "html",
  "attributes": {
    "lang": "de"
  },
  "children": [
    {
      "name": "head",
      "attributes": {},
      "children": [
        {
          "name": "title",
          "attributes": {},
           "children": [],
           "text": "Hello World"
        }
      ]
    },
    {
      "name": "body",
      "attributes": {},
      "children": [
        {
          "name": "ul",
          "attributes": {
            "style": "color: red"
          },
          "children": [
            {
              "name": "li",
              "attributes": {},
              "children": [],
              "text": "Item 1"
            },
            {
              "name": "li",
              "attributes": {},
              "children": [],
              "text": "Item 2"
            }
          ]
        }
      ]
    }
  ]
}
*/

// We can now easily extract the parts we're interested in
const title = result.children[0].children[0].text;

As a second parameter, you can provide a CSS-style selector query to search for and parse only specific parts of the HTML. In this case, the returned value is an array of all found elements.

const myHTML = '...'; // same as in the example above

const result = parseHTML(myHTML, 'ul > li'); // query for all `li` elements which are direct descendants of `ul` elements.

/*
The result variable now holds the following list of objects:
[
  {
    "name": "li",
    "attributes": {},
    "children": [],
    "text": "Item 1"
  },
  {
    "name": "li",
    "attributes": {},
    "children": [],
    "text": "Item 2"
  }
]
*/

In case you're not familiar with CSS selectors, here's some examples:

parseXML

The parseXML function allows to parse an XML string into an object representation. Each XML element is converted into a JS object with attributes name, attributes, children, and text (if any), as is showcased by the following example:

// Given some XML string
const myXML = `<element>
    <foo bar="123">Hello World</foo>
</element>`;

const result = parseXML(myXML);

/*
The result variable now holds the following object:
{
  "name": "element",
  "attributes": {},
  "children": [
    {
      "name": "foo",
      "attributes": {
        "bar": "123"
      },
      "children": [],
      "text": "Hello World"
    }
  ],
  "text": "\n    \n"
}
*/

// We can now easily extract the parts we're interested in
const rootElement = result.name; // will be "element"
const childElement = result.children[0].name; // will be "foo"
const childAttributes = Object.keys(result.children[0].attributes); // will be ["bar"]
const childBarAttribute = result.children[0].attributes.bar; // will be "123"
const childText = result.children[0].text; // will be "Hello World"

toString and toHexString

The functions toString and toHexString can be used to convert a Uint8Array to a string, which is particularly useful in combination with the hmac and base64decode functions.

const myValue = base64decode('SGVsbG8=');
const result = toString(myValue);
// the value of `result` is 'Hello' now.

Network

getWifiIPAddress

With this function you can retrieve the IPv4 address of the device on the current Wi-Fi. It will return null if there is currently no Wi-Fi connection.

const myIP = getWifiIPAddress();

getWifiSSID

With this function you can retrieve the SSID (i.e., the name) of the Wi-Fi network the device is currently connected to. It will return null if there is currently no Wi-Fi connection or if the SSID can not be determined.

const mySSID = getWifiSSID();

For this function to work, location services need to be enabled and the app needs to be granted the permission to access the device's location. This is a technical limitation imposed by the Android OS. See also the Permissions page for details.

Wake-on-LAN

You can use the wakeOnLan function to send a magic packet to turn on another device on your network. The first parameter has to be the MAC-address of the device. As the optional second parameter, you can pass the network/broadcast address to be used, and as the third parameter you can define the port.

wakeOnLan('01-23-45-67-89-ab');

wakeOnLan('01-23-45-67-89-ab', '255.255.255.255', 9);

Send MQTT message

The sendMqttMessages function allows you to connect to an MQTT broker, send (i.e. publish) one or more messages to it, and then disconnect again. The first parameter is the URI of the server/broker, the second (optional) parameter provides options for the connection (e.g. username and password) and the third parameter is a list of all the messages that should be sent.

sendMQTTMessages(
  "tcp://192.168.0.42:1234",
  {"username": "admin", "password": "1234"},
  [
    {"topic": "hallway-lamp/set", "payload": "{\"state\":\"ON\"}"},
    {"topic": "desk-lamp/set", "payload": "{\"state\":\"ON\", \"brightness\": 255}"},
  ]
);

Please note that this does not provide any particular quality of service guarantees, and that it is not possible to subscribe to topics this way, meaning you can't receive any MQTT messages.

Send TCP Packet

You can use the sendTCPPacket function to send a TCP packet to another device on your network. This can be useful when interacting with devices that have a telnet interface.

Pass the packet data as the first parameter (either as a string, Uint8Array or array of numbers denoting bytes), the target host's name or IP address as the second parameter and its TCP port as the third parameter.

sendTCPPacket('hello', '192.168.1.42', 1337);

sendTCPPacket([0x68, 0x65, 0x6C, 0x6C, 0x6F], 'example.com', 4242);

If you want to listen for incoming data from the TCP connection, you can specify so by passing in a configuration object as the fourth parameter. This object may have the following fields:

const reply = sendTCPPacket('hello', '192.168.1.42', 1337, {
  read: 'text',
  timeout: 300,
});

Send UDP Packet

You can use the sendUDPPacket function to send a UDP packet to another device on your network. Pass the packet data as the first parameter (either as a string, Uint8Array or array of numbers denoting bytes), the target host's name or IP address as the second parameter and its UDP port as the third parameter.

sendUDPPacket('hello', '192.168.1.42', 1337);

sendUDPPacket([0x68, 0x65, 0x6C, 0x6C, 0x6F], 'example.com', 4242);

Miscellaneous Built-In Functions

This section lists all of the built-in functions which do not fall into a specific category.

enqueueShortcut

With this function you can enqueue a shortcut to execute after the current one (or after the last enqueued one if there are already shortcuts scheduled to execute). Simply pass the name or ID of a shortcut as the first parameter.

enqueueShortcut('My Other Shortcut');

Optionally you can pass an object as the second parameter to provide values for variables. This will not change the stored values of the variables but they will assume the specified value when the other shortcut is executed. This is particularly useful for dynamic variable types (such as "Text Input" or "Multiple Choice Selection").

enqueueShortcut('My Other Shortcut', {
  'My_Variable1': 'Hello World',
  'My_Variable2': ':D',
});

As an optional third parameter, you can pass the number of milliseconds by which to delay the execution. This way you can schedule a shortcut to run at a later point in time.

Please note that the delay will not be exact and can not exceed 5 minutes.

enqueueShortcut('My Other Shortcut', null, 2 * 60 * 1000); // runs in 2 minutes

Note that the shortcut will only be executed once the current shortcut (and all shortcuts that have been enqueued before it) has finished executing. It will not be executed immediately. If you need the shortcut to run immediately, use executeShortcut instead.

Also note that this might lead to infinite loops if the enqueued shortcut also enqueues shortcuts. To reduce the impact of this in case it happens accidentally, the app will delay every 10th execution by 5 seconds so that you have enough time to stop the execution manually. If you're really sure that you do want an infinite loop, you can work around this protection by setting a delay of at least 500 milliseconds.

executeShortcut

This function allows you to execute another shortcut within the current one and receive its result. Pass the name or ID of a shortcut as the first parameter.

executeShortcut('My Other Shortcut');

Optionally you can pass an object as the second parameter to provide values for variables. This will not change the stored values of the variables but they will assume the specified value when the other shortcut is executed. This is particularly useful for dynamic variable types (such as "Text Input" or "Multiple Choice Selection").

executeShortcut('My Other Shortcut', {
  'My_Variable1': 'Hello World',
  'My_Variable2': ':D',
});

The function will return an object which contains a status field which you can query to see if the shortcut's execution was successful. It may contain the values "success", "failure", "unknown", or "aborted".

const result = executeShortcut('My Other Shortcut');
if (result.status === 'success') {
  const body = result.response.body;
  alert(body);
} else if (result.status === 'failure') {
  if (result.networkError) {
    alert(result.networkError);
  } else {
    alert(result.response.body);
  }
}

Please note the following technical limitations:

Passing data back

If you wish to pass data from the called shortcut to the calling shortcut, you can either do this by storing values into variables (using setVariable()) in the called shortcut and then reading those values in the calling shortcut (using getVariable()), or you can use the setResult function. The latter accepts a single string argument. This string can then be accessed by the calling shortcut on the object returned by the executeShortcut function via its result key.

// What the called shortcut does:
setResult('Hello World');

// What the calling shortcut does:
const resultObject = executeShortcut('My other shortcut');
const myResult = resultObject.result; // will now have the value "Hello World"

This same mechanism also allows passing data back to Tasker in the case where the shortcut was triggered from Tasker.

Forwarding Files

When executing or enqueuing another shortcut, it is possible to forward one or more selected files to it. This can be useful if you have a shortcut that uses a file in a form parameter or its request body, and you want to use the same file also for another shortcut to include in another request. To do this, pass the IDs of the files in via the special $files variable. You can pass either a single file ID or an array of file IDs, as shown in the following examples:

// Pass a single file
enqueueShortcut('My Other Shortcut', {
  '$files': selectedFiles[0].id,
});

// Pass 2 files
enqueueShortcut('My Other Shortcut', {
  '$files': [selectedFiles[0].id, selectedFiles[1].id],
});

// Pass all files
enqueueShortcut('My Other Shortcut', {
  '$files': selectedFiles.map(file => file.id),
});

This mechanism works both for the enqueueShortcut and the executeShortcut function.

Log Event

The logEvent function allows you to log custom events into the Event History (which you'll find in the app's main menu). This can be used for debugging and troubleshooting. Pass an event title as the first parameter and optionally a message with details as the second parameter.

logEvent('Hello World');

logEvent('My title', 'My message');

logEvent('My complex event', {'foo': 'bar'});

Generate UUID

You can use the uuidv4() function to generate a random UUID (Universal Unique Identifier, version 4). The returned value is of type string.

const myUUID = uuidv4();

Get Clipboard Content

The getClipboardContent function allows you to query the latest item in your device's clipboard, i.e., the last piece of text that you copied from somewhere. If there is nothing in the clipboard or if its content is not text (e.g., if you copied an image instead), this function will return null instead.

const clipboardValue = getClipboardContent();

Copy to the Clipboard

With the copyToClipboard function you can copy a value to the device's clipboard. Simply pass the value you want to copy as the first parameter.

copyToClipboard('Hello World');

Share Text with Another App

You can use the shareText function to share a piece of text with another app. Simply pass the value you want to share as the first parameter. This will open the system's share picker where you can select which app to share into.

shareText('Hello World');

Please note that the text that is shared can be at most 200000 characters long, otherwise it will be truncated.

Open another App

The openApp function allows you to open another app via its package name. If no app with the given package name is installed, an error is displayed.

openApp('com.github.android'); // Opens the GitHub app

Open a URL

This function allows you to open a URL in another app. This typically opens a browser, but it can also be used to invoke a deep-link into another app. An error message is displayed if the URL is malformed or if there is no app installed that can handle the URL.

openUrl('https://www.wikipedia.org/');

Please note that this can not be used to open files.

As a second parameter, you may pass the package name of the browser or app that should handle the URL. You may instead also pass "custom-tabs" or "custom-tabs([package-name])" to open the URL using a custom tab instead of a standalone browser window.

openUrl('https://example.com', 'org.mozilla.firefox');
openUrl('https://example.com', 'custom-tabs(org.mozilla.firefox)');

Send Intent

With this function you can send an Intent. It takes an object as its only parameter, where the object should have one or more of the following properties:

Parameter Description Type / Values
type Defines how the intent should be sent. 'broadcast' (default), 'activity' or 'service'
action A string that specifies the generic action to perform (such as view or pick). string
category A string containing additional information about the kind of component that should handle the intent. string
categories Same as category but allows specifying multiple values. list of strings
dataUri A URI that references the data to be acted on string
dataType The MIME type of the data string
className The full name of a class that is to be started by the Intent string
packageName The name of an application package that is to be started by the Intent string
extras A list of extras, i.e., additional parameters to be sent list of objects (see below)
clearTask Whether to set the FLAG_ACTIVITY_CLEAR_TASK flag boolean
excludeFromRecents Whether to set the FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS flag boolean
newTask Whether to set the FLAG_ACTIVITY_NEW_TASK flag boolean
noHistory Whether to set the FLAG_ACTIVITY_NO_HISTORY flag boolean

Each extra consists of the following properties:

Parameter Description Type / Values
name The name of the extra string
type The type of the extra 'string' (default), 'boolean', 'int', 'long', 'double', 'float'
value The value of the extra depends on the type

Please note that it is unfortunately not possible to send intents that require the app to hold a specific permission, as there is no way to dynamically add such a permission to the app. This is a technical limitation that the app itself cannot address. The recommended workaround is to use a 3rd-party automation app such as Tasker to perform such actions and trigger their tasks/workflows either via an intent or via the triggerTaskerTask function (see below). Another possibility would be to fork the app, add the required permission to it and build it yourself.

Here is a generic example showing the syntax:

sendIntent({
  type: 'activity',
  action: 'my.special.action',
  packageName: 'com.example.foobar',
  className: 'com.example.foobar.MainActivity',
  extras: [
    {
      name: 'favorite_number',
      type: 'int',
      value: 42,
    },
  ],
});

The following example shows how you can use this function to open another application, in this case a browser to display a website:

sendIntent({
  type: 'activity',
  action: 'android.intent.action.VIEW',
  dataUri: 'https://example.com',
});

The above example is equivalent to calling openUrl('https://example.com').

If you want to just open a specific app without sending any data to it, you can do so by specifying the app's package name and using the android.intent.action.MAIN action. The following example will just open Google Chrome:

sendIntent({
  type: 'activity',
  action: 'android.intent.action.MAIN',
  packageName: 'com.android.chrome',
});

The above example is equivalent to calling openApp('com.android.chrome').

Trigger Tasker Task

If you have Tasker installed on your device, you can use this function to trigger one of its tasks. Pass in the name of the task as the first parameter, and optionally an object containing some key-value pairs to pass along as local variables as the second argument.

triggerTaskerTask('doStuff');

triggerTaskerTask('mytask', {
  myLocalVariable: 'hello',
  andAnother: 'world',
});

Please note that you may need to manually go to the app's permissions and allow the app to run Tasker tasks for this to work, and also you will need to allow this in Tasker's settings under "Preferences > Misc > Allow External Access".

Set Wireguard Tunnel State

If you have Wireguard installed, you can use the setWireguardTunnelState function to enable or disable a tunnel. Pass in the name of the tunnel as the first parameter, and as the second parameter pass true to enable the tunnel or false to disable it.

setWireguardTunnelState('my-tunnel', true);

For this to work, you will need to grant the app a special permission, and you will need to enable the "Allow remote control apps" setting in the Wireguard app. You might also need to exclude the Wireguard app from battery optimizations and allow it to run unrestricted.

Get Location

If you want to query your device's physical location, you can do so via the getLocation() function. It can take up to 20 seconds for the location request to complete, and it might not always be possible to determine the location.

The resulting object consists of the following fields:

Field Description Type
status Indicates whether a location could be determined. Will be 'success' or 'unknown' string
latitude The latitude in degrees, or null if the location is unknown number
longitude The longitude in degrees, or null if the location is unknown number
accuracy The estimated horizontal accuracy radius in meters at the 68th percentile confidence level, or null if the location or the accuracy is unknown number
coordinates The latitude and longitude concatenated with a comma, for convenience string
const myLocation = getLocation();
if (myLocation.status == 'success') {
  alert(`I am currently at ${myLocation.coordinates}`);
} else {
  alert('I am so lost right now');
}

Please note that this function makes use of Google Play Services. If those are not available on the device, or if you've installed the app from F-Droid, then a fallback is used which may be less accurate, less reliable or take longer to find the location.

Examples

This section lists some examples for typical use-cases of the code execution feature.

Generate values for use in the request

Sometimes you need to generate a value, for example the current date, or a random number, to be used in your request. You can do this by generating the value and then storing it into a variable that you then use in your request. Here's an example:

const randomNumber = Math.floor(Math.random() * 10);
setVariable('myNumber', randomNumber);

const currentDate = (new Date()).toDateString();
setVariable('today', currentDate);

Parse a JSON response

Here's an example on how to parse the response of your shortcut, and display the result or store it into a variable for later user.

const temperature = JSON.parse(response.body).temperature;
showDialog(`The current temperature is ${temperature}°C`, 'Temperature');

setVariable('temperature', temperature);

Change icon and label based on response

This example shows how the shortcut icon and label can be changed based on the received response. The example assumes that the server returns 'OK' if the request was a success.

if (response.body == 'OK') {
  renameShortcut('', 'Success');
  changeIcon('', 'freepik_check'); // changes the icon of the current shortcut to a green checkmark
} else {
  renameShortcut('', 'Failure');
  changeIcon('', 'freepik_close'); // changes the icon of the current shortcut to a red cross
}

Ask for confirmation before execution shortcut

This example shows how you can show a custom confirmation message before the shortcut executes and only execute it if the user confirms by clicking 'OK'.

if (!confirm('Should I do the thing?')) {
  showToast('Not doing the thing.');
  abort();
}

Or you might want to bypass the confirmation step if you are in your home network:

if (getWifiSSID() != 'My Home Network') {
  if (!confirm('Should I do the thing?')) {
    showToast('Not doing the thing.');
    abort();
  }
}

Read the response out loud

This example shows how you can have the received response be read out loud (using text-to-speech). The example assumes that the response is in plain-text (i.e., not HTML, JSON, ...).

speak(response.body);