Automating iOS: A Comprehensive Guide to Launch Center Pro

Released in December of 2011, Launch Center (the predecessor to Launch Center Pro) was one of the first apps to put the spotlight on URL schemes and actions. Promising the ability to launch "actions" instead of just apps, Launch Center leveraged URL actions to minimize the number of taps it took to complete common tasks in a variety of iOS apps.

In those days, URL schemes were a fairly obscure facet of iOS, and few apps supported them. App Cubby (the developers of Launch Center and Launch Center Pro, now known as Contrast) wanted to change that. With Launch Center 1.2, they introduced the "Supported Apps" list: a list of apps supporting URL schemes with quick links to load actions from those schemes into Launch Center.

A few months later, in June of 2012, App Cubby released Launch Center Pro. The evolution of Launch Center, Launch Center Pro (or LCP) substituted the old list view for a 3x4 grid of large, easily tappable actions.

Where Launch Center had clearly been a utility, Launch Center Pro was a second home screen. Tapping icons in a grid is natural to every iOS user, and LCP took advantage of that to feel instantly familiar. As the slick new app made waves in the tech community, awareness and support of URL schemes began to grow. Launch Center Pro was the spark that would ignite the fire for URL schemes and iOS automation.

In the following months the iOS automation landscape grew as new players entered. Pythonista brought powerful Python scripting to iOS, and Greg Pierce's x-callback-url specification was gaining steam among third-party apps. In January, 2013, Pierce released Drafts 2.5 (Drafts for iPad 1.5), adding custom URL actions via an action menu and powerful support for x-callback-url. This placed Drafts among the front runners for the most powerful iOS automation and inter-app communication possible on iOS. The rest of 2013 would not slow down the pace. Drafts, Launch Center Pro, and Pythonista continued to iterate and improve.

Last August brought Editorial, a new app by the same developer behind Pythonista, which revolutionized the field all over again. Not to be defeated, Agile Tortoise answered with Drafts 3.5, and App Cubby became Contrast as they released Launch Center Pro 2.0 and (soon after) Launch Center Pro for iPad. Today, we're all eagerly awaiting the rumored update of Editorial as well.

Watching these developers fight it out has been an awesome experience. The intense, unceasing competition has brought iOS automation incredibly far in a ridiculously short amount of time. The power of these apps, the increasing support of URL schemes from third party developers and the attention from many independent websites such as MacStories, Unapologetic (my personal website), Geeks With Juniors, I Miss My Mac and many others which latched onto the idea and fostered it in the early days, have grown the field from a ridiculed thought (no one can do real work on an iPad!) to a subject often discussed in the tech press.

Today, Launch Center Pro has come incredibly far from its rudimentary beginnings. Once a simple app launcher held back by the lack of support for more advanced actions by third party developers, interest in URL schemes has let Contrast focus on beefing up LCP's internal functionalities. While on the surface it looks deceptively simple and just a reskin of its original design from June 2012, 2014’s Launch Center Pro is brimming with hidden power and advanced capabilities.

Since no single resource has previously existed to bring you up to speed from a total beginner to a Launch Center Pro power user, my goal is to provide one for you here. Whether you've never even heard of Launch Center Pro until reading this, or you're a seasoned veteran of the app, this article will familiarize you with the app's full feature set.

Table of Contents

URL Schemes and Actions

Launch Center Pro and Drafts (the automation app with the most similar feature set) both seem to have fairly simple visions.

Drafts seeks to be the central place for text input and output on your iOS device. If you want to type something up and are going to send it somewhere, be that Dropbox, Evernote, email, iMessage, a social network or any one of many third-party apps, you start with Drafts.

Launch Center Pro (left) and Drafts (right).

Launch Center Pro (left) and Drafts (right).

Launch Center Pro seeks to be like a speed dial for the common tasks you perform on your iOS devices. If you want to launch an app and immediately perform some sort of basic function within it, there’s a good chance Launch Center Pro can help you achieve that task quicker and with fewer taps. While these visions may seem separate, there is a key concept in the way in which they are each achieved that leaves them deeply intertwined: URL schemes.

I’ve already written extensively about URL schemes in my guide to URL schemes and Drafts actions, and if you're unsure about what URL schemes are or how they work then I encourage you to read through that before going into the more advanced sections of this guide. Regardless, I’ll give a quick overview here, as understanding the concept is key.

On iOS, Apple has implemented a method of security known as “sandboxing”. Each and every iOS app lives in its own “sandboxed” environment. Apps cannot reach outside of their sandboxes and into others to send or receive information from one another. This feature is good for security, as it’s impossible for malicious apps which might slip through the App Store review process to spread harmful files or steal or track data from other apps.

However, in regard to automation, sandboxing means that even well-intentioned apps cannot send and receive good files or pass commands back and forth to collaborate and make use of their individual strengths. This would make automation of tasks between more than a single app almost impossible, but thankfully we were left with a few small loopholes which clever developers have learned to work with.

There are two official ways for iOS apps to communicate with each other: the “Open In” menu, and URL schemes. The Open In menu simply duplicates files from one app’s sandbox into another’s. In general this is not very helpful for automation purposes -- the single, intriguing exception to that being the capabilities introduced in Pythonista 1.4, which allow you to script the Open In menu. This method, however, is not widely adopted, and still has its flaws and drawbacks (primarily: you need to know how to code in Python). That leaves the second way to escape the sandbox: URL schemes.

URL schemes are foundations that can be built into apps which allow the app to be launched (and often various functions within it to be triggered) automatically via URLs. These URLs look very similar to the standard URLs which everyone who has used a web browser understands, except they start with an app name instead of “http”. So instead of launching a website by typing "http://" into your browser, you could launch, say, Drafts by typing "drafts://" into the browser.

Every app has a unique scheme, so Launch Center Pro is launched by "launchpro://", Tweetbot by "tweetbot://", etc. By adding more onto the end of the URL, you can move further into the foundation that developers have built into their apps, launching into specific windows or calling specific functions.

In Tweetbot, for instance, you can call “tweetbot://compose” to launch Tweetbot and be immediately taken to the compose view to type a tweet. If you pass text in with the URL, such as "tweetbot://compose?text="Hello%20World", you will launch Tweetbot into the compose view and it will be automatically filled with the text “Hello World” (in the URL the text has to be percent encoded, but the app will decode this when it receives the text). This works because Tweetbot’s URL scheme has been set up such that "/compose" is mapped to the compose view. Adding "/compose" to any other app's URL will likely do nothing, because every URL scheme is different depending on how the developer decided to build it.

So URL schemes and URL “actions”, as the actual URLs which launch apps and call functions are referred to as, can save you a lot of time by skipping unnecessary taps through complex app hierarchies. This is powerful on its own, but it wasn’t enough for Greg Pierce, the developer of Drafts. Pierce created the protocol known as x-callback-url, which allows you to add parameters into your URL actions that launch a second URL action after the first is successfully completed. This means that we can chain together multiple URL actions to build complex automated workflows, all using the simple plain text URLs which can slip beneath the iOS sandbox barrier.

Drafts and Launch Center Pro

As stated before, the backbones of both Drafts and Launch Center Pro are URL schemes. Or more specifically, URL actions which utilize the URL schemes built into hundreds of third party apps, and even some first party Apple apps.

Drafts has a specialized “action list”, which is basically a long list of custom URL actions which you can launch to send the text you’ve written in a draft to… well, almost anywhere. Since you build most of the URL actions in your Drafts action list yourself, you can make use of Drafts’ powerful variable tags to send all of your text, or only specific lines or sections, to any app or service that is supported by Drafts or has implemented a URL scheme.

Launch Center Pro, however, is different. Where Drafts is focused on text and uses URL actions as an optional supplement to the text input functionality, Launch Center Pro is focused on actions and uses text as an optional supplement. Due to this, instead of Launch Center Pro opening to a text input field and requiring extra taps to run actions on it, it opens to a grid of actions, and depending on the action you choose to run you may or may not be required to type text into an input prompt before it is launched. This fundamental difference is the main separator between Drafts and Launch Center Pro, and this is why both apps fit together and can be used in tandem rather than requiring you to pick a favorite and only use that one.

While Launch Center Pro may have a fairly simple vision (and does its best to be accessible to everyone) URL schemes are by no means simple, and thus, most apps which revolve around them become complex by default.

The goal of this article is to get you comfortable with that complexity. Before we begin, I’ll reiterate once more that if you’re still completely confused by URL schemes after that basic overview, I highly recommend you take the time to read my afore-linked guide to URL schemes and Drafts actions before jumping into this, as all higher level Launch Center Pro functionalities will be far easier to comprehend if you understand the URL actions that they’re built upon.

If you’re confident in your knowledge of URL actions, or if you only want to take LCP to a beginner level and just learn the basic functionality for now, then read on: here’s my comprehensive guide to Launch Center Pro.

The Basics

The first time you open Launch Center Pro, you’ll see an introduction screen consisting of three cards. The first of these describes Launch Center Pro “Actions” as “one-tap shortcuts to quickly perform everyday tasks.” This, in essence, is what Launch Center Pro is all about. The app probably won’t help you do anything that you can’t already do manually, but rather, its core functionality is reducing the time it takes for your most common tasks. After a little preliminary setup, Launch Center Pro centralizes the starting point for your daily workflows, reducing friction and increasing efficiency.

After dismissing the introduction, you will see the Launch Center Pro home screen. This is a three-by-five (four-by-six on iPads and three-by-four on 3.5 inch screened iPhones) grid of rectangles, and the central UI element for the entire app. Within each box on the grid is an icon, and beneath each icon is a description.

There are only two possible types of grid items: actions and groups. Action icons are familiar rounded rectangles, and can be app icons, custom color/icon combinations, photos, or web clips. Every “action” has a URL action attached to it, and tapping the action's icon in the grid will cause its URL action to be triggered. Group icons are white circles with grey borders and thin, iOS 7-inspired grey icons inside of them. Groups are basically folders filled with more actions. Tapping and holding on one will open it, replacing the actions and groups on the main grid with actions you have placed in the group. To launch one of these actions, simply drag your finger from the group icon across the grid to the action you want to run, then let go. If you let go while your finger is still hovering on the group’s icon, the group will close and the main grid will be restored. This method of interaction is what makes Launch Center Pro such an excellent app.

If you want to launch an action, no matter where the action is, you can get to it by either a single tap, or a tap-swipe. That’s a maximum of two hundred and ten completely different actions, all accessible from the same place without lifting your finger twice.

If this is your first time opening Launch Center Pro, your grid will be pre-populated with default actions and groups. You can play around with these if you’d like, but generally you’ll want to customize your LCP home screen entirely for you, so feel free to delete them all immediately. You can also pick a different theme for your grid if you don’t like the default white theme. Dark and Classic themes are available in the settings pane (found in the top left corner of the LCP main screen).

All adding, deleting, and moving of actions is done by tapping the small pencil icon in the top right corner of the app. This puts your grid into edit mode, where every action and group gets a small “x” button on its top left corner, and every unused box gets a large plus button directly in the center. You can tap the “x” buttons to delete actions or groups (be careful deleting groups, as every action inside of them will also be deleted), or tap the plus buttons to add new ones. While in edit mode you can also drag actions or groups around to rearrange your grid.

If you tap a group while in edit mode, it will open, changing the grid view to display the grid of actions for that group. This sub-grid can be edited and manipulated in the same way as the main grid, but any new actions added from this view will only appear when you tap and slide from the group’s icon.

Furthermore, since Launch Center Pro only supports going one group deep, you cannot create a group within a group, and the plus button in a sub-grid immediately creates a new action instead of prompting you to choose either an action or a group. When editing a group’s grid, the “x” button on the group’s icon turns into a small “i”, and you can also tap that to change the name or the icon for the group, or delete it entirely. To return to editing the main grid, just tap the group icon again to close it.

The final aspect of edit mode is editing your actual actions, which can be done by simply tapping the square for any action on the main grid or in the sub-grid of a group. This opens the action editor (also opened when tapping the plus button and choosing to create an action), which is the place you will go to add or edit every action you ever create in Launch Center Pro.

The Action Editor

The action editor window slides up from the bottom of the screen when you choose to add or edit an action. The editor consists of seven rows (eight if you are editing an existing action, as it adds another button at the bottom to delete the action), the first two are for the name and URL of your action. These two rows are editable text fields, and tapping in them will allow you to manually type a name and a custom URL action. This is very important for getting a more advanced functionality out of Launch Center Pro, but many basic actions are available without being typed manually. These preexisting actions are accessed from the “Action Composer”, the button in the third row of the action editor.

The Action Composer

The Action Composer is one of the most impressive parts of Launch Center Pro. The guys at Contrast have pursued the arduous task of manually building a huge library of URL actions for hundreds of different apps. The entire library is available via the Action Composer, where it is broken down into five different sections.

The first option, “System Actions”, displays a list of actions which are either Launch Center Pro specific actions, or iOS system level actions not necessarily tied to a particular app.

The second option, “Installed Apps”, lists every action from the Launch Center Pro action library for which the corresponding app is installed on your device. These first two sections will likely be the ones you use the most, but the last three can be useful as well. The “All Supported Apps” section is a great place to go if you want to check out the URL scheme for an app you have heard about or are considering downloading.

Since this library has been built manually, you should take the absence of your app being listed with a grain of salt, as it could just mean that the Contrast developers haven’t gotten around to adding it or haven’t yet heard about it. If your app is available though, it can be useful to view its section in the Action Composer and see whether it includes a variety of different actions, signifying a powerful scheme. Once again though, sometimes apps are added with their basic launch URL but without some of their more advanced action capabilities.

The “Featured Apps” section is a great place to look if you’re trying to find some great new apps. Apps in here are generally pretty high caliber, and all of them have some sort of URL scheme.

Finally, the “Recently Added” section is composed of the most recent additions to the action library. I have never found this section to be of great use, but maybe you will find a reason to utilize it.

In any of the last three sections, if you see an app in the list that you don’t have installed, but would like to download, you can tap the download icon on the right side of every app to be redirected to the App Store page to download it.

Within the Action Composer, tapping any of the section buttons will slide the Composer to the left to reveal a list of available apps (the one exception being the System Actions section, which just displays a list of actions since they are not tied to apps). Tap an app to see a list of supported actions for it. From there you can tap any of the actions to choose one of them to be sent to the action editor.

Many of these actions have options for customization, while others are more simple. Flashlight, for instance, found in System Actions, has no need to be customized, so choosing the Flashlight action will immediately dismiss the Action Composer and return you to the main action editor. After choosing an action, the name and URL will be automatically filled into the action editor’s “Name” and “URL” rows. In this case, the name would be “Flashlight” and the URL would be launch://light. If you were to pick a different action, such as Bookmark, you would be directed to another pane to fill in the Name and website URL for the website to open. After entering those and pressing done, the Action Composer would auto-fill the top two sections of your new action in the editor with the given name and website URL.

Everything done in the Action Composer can be done manually by typing the URL actions yourself, but the function of the Composer is to stop you from needing to remember the URL schemes of every app on your iOS device. Since this is the largest, most accessible and best organized library of URL actions that I am aware of, I have found it useful even when building actions for Drafts or Editorial, as I can consult Launch Center Pro’s library any time I want to remember the scheme or syntax of a particular app that I am using in a workflow.

Keyboard Prompts and Other Variables

When customizing actions in Launch Center Pro, be it within the options of an action in the Action Composer, or while manually editing a URL in the main editor, an extra row of icons will appear at the top of your keyboard. The first is the keyboard prompt icon, and tapping it will pop up a list with three options: System Keyboard, Fleksy Keyboard, and Number Pad. Whichever option you choose, you will be faced with that type of keyboard and a prompt box each time you run your action. Whatever text you type into the box will be automatically encoded and inserted into the URL action before it is launched.

As discussed at the beginning, Launch Center Pro is an action based application instead of a text based one, so you don’t get presented with a text box unless you ask for it. Keyboard prompts are the way you ask for it. Any action that you want to send text through requires you to either hard code text into it (very limited use cases there), or use a keyboard prompt.

Whichever type of prompt you choose will cause some text wrapped in square brackets to be placed in your action URL. This will be in the format of [keyboard-type:prompt-title], where "keyboard-type" is the option you chose from the list (for the system keyboard this will simply be “prompt”, for Fleksy it will be “prompt-fleksy”, and for the number pad it will be “prompt-num”) and "prompt-title" is a title to display at the top of the prompt box that will appear each time you run the action.

Here’s an example of putting all of this together. If you wanted to build an action which uses Launch Center Pro’s in-app messaging actions to send a message, and you want to type your message using the special Fleksy keyboard instead of the standard system one, you would tap the pencil button to enter edit mode, find an empty slot in your action grid where you want the action to be placed, tap the plus button in this empty slot to bring up the action editor, tap the "Action Composer" button in the third row, choose "System Actions" in the Action Composer, choose "In-App Messaging" from the list of available actions, and finally tap "Send Message to Group" from the list of action options.

This will bring up a menu with three text boxes for you to fill in. The first is a title, which you can leave as the default “Send Message”, or change to anything you desire. The second text box can optionally be filled in to choose a certain contact or group of contacts for the message to be sent to. If you want to choose who to send it to by yourself each time you run the action, leave this box blank. The final option is for the Body of your text, and tapping this field will bring up the keyboard with the custom icon row at the top. Tap the first icon and choose “Fleksy Keyboard”. This will place the text [prompt-fleksy:Body] in the third text box. Now tap done.

Back in the action editor, the name of your action has now been changed to “Send Message” (unless you picked a different name), and the URL for the action will be this:


Here’s a quick break down of the action:

  • launch:// is the top level of the URL scheme for Launch Center Pro. In-app messaging is a built in action, so Launch Center Pro is going to start by calling itself.
  • messaging? tells Launch Center Pro that you are calling its in-app messaging function.
  • body= tells Launch Center Pro to fill in the body of the message with whatever comes after the question mark.
  • [prompt-fleksy:Body] tells Launch Center Pro to display a prompt box, labeled “Body” and using the Fleksy keyboard for input. Whatever text is typed into this box will be percent encoded and and then substituted into the action in place of the prompt text. If you typed “Hello, World!” into the box and hit Done, the actual action that would be launched would look like this: launch://messaging?body=Hello%2C%20World%21, and this action would bring up the in-app messaging window in Launch Center Pro with the body already filled in with the text “Hello, World!”. All you need to do from there is enter the recipient and hit send.

The second icon on the extended keyboard is the contacts button. Tapping this will bring up a window of all of your iOS contacts, and from there you can pick a contact's phone number or email address, and it will be filled into your action.

This is how you pick recipients when you want to make actions specifically hard coded for particular people. Recalling the above example for in-app messaging, you would use the contacts icon if you wanted to fill in the "To" section as well as the "Body" section, which would mean that when you run the action and type in your body, the in-app messaging window will pop up with the recipients already filled in, so all you have to do is hit send. The URL action for this will look largely the same, but with an added "to" parameter which is given the value of the number of the contact you chose. If your contact's phone number were "520-123-4567", your action would look like this:


The third icon on the extra keyboard inserts the clipboard variable. Similar to the prompt variables, this is represented by the word clipboard inside of square brackets ([clipboard]). Wherever this is used in an action, the variable will be replaced by the encoded contents of whatever is on your clipboard at the time you launch the action.

The fourth icon is for Dropbox. Specifically, for generating Dropbox links.2 If you include the [dropbox] variable inside of your actions, you will see a dialogue pop up revealing the contents of your Dropbox every time you run your action. Choose a file from the Dropbox dialogue and the link to that file will be encoded and sent along with your action.

As a simple example, you could use this in email actions to quickly generate and send links to files in your Dropbox over email. For something like that you would pick "In-App Email" from the System Actions list, then choose "Email with Body & Subject", and then fill in the necessary parameters from there.

To access your Dropbox files, add the [dropbox] variable somewhere in the subject area for the action. Remember, you can mix multiple input variables to get your actions how you want them. It's likely in this case that you'll want to add a few lines of text describing the file you're sending a link to, so first add a [prompt:Body] variable, then a couple newlines for readability, then the [dropbox] variable. You might also want an input prompt for the subject, [prompt:Subject].

The code for the resulting action would look like this:


Running the action would first give you a popup asking for a subject, then another requesting a body, and finally display a window showing all of your Dropbox files. Pick a file to dismiss the dialogue, and finally the in-app email dialogue will pop up with the subject and body filled in, the body including a link to your Dropbox file located two lines below the end of the main text. From there just choose the recipients and press send to finish.

The final extended keyboard icon shown when editing or building actions is the TextExpander snippet icon. If you use this in your action, whatever shortcut you place within the angle bracket snippet indicators ("<shortcut>") will be expanded before the action is run, and the text from the expanded snippet will be sent in the action. Don't forget that each time you change your snippets you need to go to settings in LCP (and any other apps that you use with TextExpander) and choose "Update TextExpander Snippets".


The fourth and fifth rows in the action editor are labeled “Icon” and “Schedule”, respectively. The Icon section is particularly important, as this is where you will choose the faces of your actions on your action grid. The Icon section provides three main options: Default, Custom, and Photo. The "Default" option will pull the app icon of whichever app your action pertains to from Launch Center Pro’s database. If your action is a bookmark, it will use the favicon from the bookmark’s website.

The "Custom" option allows you to choose an icon, background color, and background style for your actions. Launch Center Pro has a wide variety of icons to choose from, and those combined with the twelve different colors and six different background styles for your icons gives you more than enough choices to have unique icons for every action you build.

The final icon option, "Photo", allows you to either take a photo or choose a photo from your photo library to be used as the action's icon. I find this particularly useful when picking icons for iMessage or phone call actions assigned to specific friends or family members. Finding a picture of your friend’s face among the other icons is much easier than picking a default icon that somehow defines them or reading the text of every name in order to pick them out. Eventually most of your actions will be dealt with by muscle memory, but it’s still nice to be able to use photos. If you want to, you can even add a small frame around the border of your photo icon.

Scheduling actions is another useful feature that Launch Center Pro provides. This section allows you to schedule an alert for a specific date and time. A notification will pop up at the time of the alert, and tapping the notification will automatically run the action attached to it. You can schedule repeating alerts as well, so if you have a certain task that you want to complete every day at a particular time, such as a Day One journal entry, you can use Launch Center Pro to get a notification which will launch you directly into Day One at the specified time and on the specified interval (you can choose hourly, daily, week daily, weekly, monthly or yearly).

Moving and Sharing

The final two rows of the action editor allow you to move or share your action. The move option seems a bit out of place to me, as it should really be somehow available in edit mode while you’re editing the rest of your grid, but as it is, this enables a special moving mode in which you can move the selected action into or out of groups. In the standard editing mode, you can move actions and groups around, but there is no way to get an action that is already inside a group out of it, or vice versa. The move option is good to have around, but will hopefully be better integrated with the rest of the editing mode at some point in the future.

The Share Action button can be very useful for sharing your action with others in an easy way. Unlike the Drafts share button, which creates an often massive direct import URL and copies it to your clipboard, the Launch Center Pro share button redirects you to the website, where Contrast provides a service to save actions at individual webpages.

After you tap the share button, the title and URL of your action will be filled in automatically, but you can also optionally type in a description of your action for others to read. When everything is ready, tap “Create”, and a unique webpage will be created for your action, displaying the title, description and URL for it above an “Install” button. You can send the link to this webpage to others, and they can follow it to install your action on their own Launch Center Pro grids.

The advantage this implementation holds over that of Drafts is that a website URL is short enough to be included in a Tweet, so you can tweet your Launch Center Pro actions, solving a problem that many of us have wrestled with in the past when trying to share import links for Drafts actions. If you do want a direct import link, you can tap and hold on the Install button on your action’s webpage and copy the link, which itself is a direct import link. I use this method to include Launch Center Pro import links on my website without having to redirect people to another page first.

Advanced Techniques

Launch Center Pro can be a powerful tool even if you only use it for basic functions. Launching apps or calling simple actions, like iMessage or phone call actions for specific contacts, all from the same place can speed up many daily tasks. This functionality, however, is only the tip of the iceberg for what Launch Center Pro is capable of.

Using x-callback-url, hidden prompt types, headless and recursive actions, Drafts or Pythonista URLs and more, we can take Launch Center Pro to another level of powerful automation.

Manually Building Actions

The Action Composer is a great tool, and does wonders to simplify and speed up the process of building URL actions, but when building more advanced actions we generally want to see all of the code at all times, and have full control. Due to this, I encourage you to build all your advanced URL actions either in a text editor like Drafts, or directly in the URL section of Launch Center Pro’s action editor.

If you do choose to build your actions in Drafts, you can use install my import action in Drafts, and run it to import your code directly into LCP after writing it in Drafts.

The Launch Center Pro URL Scheme

You’re in the advanced section now, so I’ll assume you have some amount of knowledge about the basics of URL schemes.

The Launch Center Pro URL scheme is much larger than any other I’ve seen, but every path will still start by calling the primary Launch Center Pro “domain name”, launch://. From here you have a variety of different options, and each one will call a different function within Launch Center Pro:

  • launch://brightness -- Set or toggle the brightness level on your device.
  • launch://messaging -- Activate the LCP in-app messaging function.
  • launch://email -- Activate the LCP in-app email function.
  • launch://dropbox -- Activate the LCP in-app Dropbox function.
  • launch://clipboard -- Call one of the LCP clipboard functions (generally used to add text or a photo to the clipboard).
  • launch://define -- Define a word using the system dictionary.
  • launch://speak -- Read text out loud to you.
  • launch://facebook -- Open the LCP in-app Facebook post dialogue.
  • launch://tweet -- Open the LCP in-app tweet dialogue.
  • launch://sinaweibo -- Open the LCP in-app Sina Weibo post dialogue (this feature only works in regions where Sina Weibo is accessible).
  • launch://sharesheet -- Open the iOS system share sheet.
  • launch://dial -- Open the LCP in-app contacts viewer where you can pick a contact and immediately dial their number.
  • launch://light -- Turn on the flash on your device.1

Most of these schemes go a bit further, allowing you to add text, photos and more automatically via the URL, but I encourage you to just use the Action Composer so that you don’t have to remember the proper syntax for every one of these paths.

Also worth mentioning is that Launch Center Pro has registered a few other top-level URL schemes besides the one shown above, the main example being launchpro://.

Multiple registered URL schemes work the same way as having extra website URLs which redirect to a main one, except they don't actually need to redirect. launch:// and launchpro:// are completely interchangeable beginnings to any LCP URL action. I mention this because launchpro:// was registered before the simpler launch://, so many people who have been building LCP URL actions for a long time (myself included) are used to and continue to use the launchpro:// scheme.

Many older actions posted online might also contain this and other older top-level schemes (in-app actions used to require their own special schemes, so launchpro-clipboard://, launchpro-messaging://, launchpro-email:// and more are all registered to the app as well, but thankfully we no longer need to differentiate our actions like this) so if you run into them just remember that they now mean exactly the same thing as launch:// and the small differences can be ignored.

Launch Center Pro x-callback-url Support

Unlike many other apps, Launch Center Pro only supports x-callback-url for a few types of actions. Since LCP’s URL scheme is so far-reaching, x-callback functionality would not make sense on some of its actions (such as turning on the flashlight), but I do wish the list extended a bit further.

As it is, Launch Center Pro supports x-callback-url in its URL schemes for brightness, messaging, email, Dropbox, clipboard, defining, and speaking. It lacks this support in its URL schemes for tweeting, posting to Facebook and calling the iOS share sheet, three actions with which I could see chaining as useful.

For the actions x-callback-url is supported in, simply add x-callback-url/ between launch:// and the chosen path. So if you were going to use x-callback-url to chain a second action to an in-app messaging action, your URL would start like this:


From there, the x-callback-url syntax is standard. Add &x-success= after your first action, then add your second action onto the end of that to get them to chain. The second action needs to be percent-encoded, but Launch Center Pro supports the same format for easy encoding as Drafts does: just wrap your second action in {{curly brackets}}.

Here’s an example of an action to send your last photo to a friend, then chain back and email it to another:


And here's the breakdown for that action:

  • Before even running the action, LCP will first parse it for special identifiers such as input prompts and curly bracket encoders. There aren't any prompts in this action, but it will find the second portion of the action to be surrounded by double curly brackets, so it will remove those and percent-encode that section of the action, then run it from the beginning.
  • launch:// tells LCP that we are running one of its actions, and enables all the possible paths of in-app actions that we could follow;
  • x-callback-url/ enables the x-callback-url protocol, telling LCP to start searching for x-callback parameters throughout the rest of the action;
  • messaging? narrows the focus to the LCP in-app messaging actions. Since many extra parameters such as the "to" or "body" parameters are the same for multiple types of LCP actions, we have to first tell it which type of action they are applying to before we can use them;
  • to=555-555-1212 tells LCP that we are sending this message to the phone number "555-555-1212". Obviously this is a fake number, but when you build this action yourself you will use the contact button on the extended keyboard here to pick the contact you're actually sending the message to, and it will automatically fill the space after the "to=" parameter with that phone number or email address;
  • &attach=lastphoto is a special parameter available for LCP actions which, not surprisingly, attaches the most recent photo that has been placed on your camera roll. In this case, since we're in a messaging action, your message will pop up with that last photo automatically placed inside the body and ready to send;
  • &x-success= is an x-callback-url parameter which is triggered after the successful completion of the preceding action. In this case, once you press send on the messaging dialogue that pops up with the most recent photo attached, x-success is triggered and the next portion of your action, the part that we initially encoded in curly brackets, is decoded and run as normal.

Decoded, the second action looks like this:


Here's that breakdown:

  • launch:// calls LCP again, informing it that it is running one of its own actions;
  • email? tells LCP that it's now running an email action, as opposed to a messaging action like the first one was;
  • sets the recipient of the email to "";
  • &subject=Photo sets the subject of the email to "Photo";
  • &body=Here%27s%20a%20photo%20I%20took%21 adds "Here's a photo I took!" to the beginning of the body of the email;
  • &attach=lastphoto attaches the most recent photo from your camera roll, the same photo you just attached to the message you sent in the previous action, to the email.

Now all that's left is to hit send on the in-app email dialogue that just popped up with everything specified in your action filled in and you're done. Since all of these parameters were pre-specified in the code of your action, that entire process will happen within just a fraction of a second, pausing only to wait for you to hit send on the message box and then the email box.

Hidden Prompt Types and Lists

Launch Center Pro also comes equipped with a few extra options for keyboard prompts which can’t be found on the menu from the extended keyboard. Similar to how you can use [prompt-num] to bring up the number pad keyboard for your input method, you can also use a few other keywords after “prompt-“ to access even more keyboards:

  • [prompt-twitter] calls up the system keyboard designed for tweeting, which gives easy access to the “@“ and “#” symbols.
  • [prompt-url] puts the “.com” and “/“ keys front and center.
  • [prompt-phonepad] gives special phone characters.
  • [prompt-namephonepad] uses the standard keyboard for the first layer, but replaces the number layer with a full number pad.
  • [prompt-emailaddress] limits the keyboard to valid email characters and gives quick access to the “@“ symbol.
  • [prompt-return] gives you a return key. The standard prompt box replaces the return key with a “launch” key that dismisses the prompt and sends whatever text you have typed. If you want to be able to include line breaks in your text, use this prompt type.
  • [prompt-list] also replaces the launch key with a return key, but when you send the text, all line breaks are converted to commas. Some task apps can receive comma separated lists via URLs and convert them into individual tasks, etc. and the prompt list feature can make things like that easier.

Using the type of prompt that best fits your action can add one more layer of convenience to your new workflows. The [prompt-return] function is particularly useful, as many circumstances require line breaks in text and this is the only way to get them easily.

There is one final input type for Launch Center Pro, and this one opens up a whole new realm of possibilities: lists.

Lists allow you to build a menu of options that will pop up each time you launch an action. You can specify titles for the options and give each title a value, or just use the values as the titles. When you pick an option from the list, the feature acts just like the standard input prompts, replacing the list variable inside of your action with the value of the option you chose. With lists you can build versatile and powerful multiple choice decisions into your actions. Thus, running the same action can do a few different things depending on the situation.

The basic syntax for lists looks something like this:

[list:Title|Option 1|Option 2|Option 3]

If you placed that exact list inside of an action and ran it, you would be faced with a pop up menu titled "Title" with four buttons labeled "Option 1", "Option 2", "Option 3" and "Cancel". When you press one of the buttons it will swap out the list variable in the action with the text of the button you pressed, percent-encoded (except the Cancel button, which just cancels the entire action).

You can add as many options into your list as you want; if they extend off of the screen then the list of buttons becomes scrollable to reach lower options. In your code, just make sure to separate each option you add with a pipe ("|") symbol. The title parameter is technically optional, but I encourage you to always use it, as it makes actions more understandable and shareable.

Here's an example of using a list to build a Tweetbot search action with hard-coded parameters:

tweetbot:///search?query=[list:Search Query|||Launch Center Pro|Apple]

Running this action from LCP will pop up a menu with the four options from the list as buttons, and a fifth "Cancel" button. When you select an option, that text will be swapped into the Tweetbot URL and then the action will be run as normal. If you run the action as is above, then choose "Launch Center Pro" from the list, the entire list variable will be replaced by the percent-encode text "Launch%20Center%20Pro", so the actual action that LCP runs will look like this:


All the swapping happens instantaneously in the background of course, so you won't see the swap or the new URL, you'll just be redirected to Tweetbot where the search box will pop up with "Launch Center Pro" already plugged in.

While these most basic lists can be useful in and of themselves, they become even more powerful with their ability to attach different text to the parameters than that which is displayed on the buttons. By adding "=" after the text of each option, we can change the option into just a title for the button, and selecting the title will add different text into the action. In the above example we could use this to make the exact function of our buttons a little clearer, so you understand exactly what tapping each button will do:

tweetbot:///search?query=[list:Search Query|Search Tweetbot for ""|Search Tweetbot for ""|Search Tweetbot for "Launch Center Pro"=Launch Center Pro|Search Tweetbot for "Apple"=Apple]

Running this code would display a menu that performs the exact same function as the first one did, but the buttons now display more descriptive titles.

The power of Lists does not stop here. Adding hard coded text into your actions is great, but this is the advanced section, so lets dig deeper into the higher level capabilities that we can drag out of LCP lists. This section requires a lot of percent-encoding, and a strong grasp on how Launch Center Pro handles URL actions, so I'll give a more in-depth overview of those features before we get started.


Hopefully you already have a basic understanding of percent-encoding, but I'll give a quick synopsis of the practice since it is integral to building more advanced URL actions with lists or multiple nested actions.

Percent-encoding a piece of text or code will take most of the special, non-alphanumeric characters and encode them into two-character strings of numbers and capital letters, each string prefixed with a single "%" sign (hence the name "percent encoding"). This is often also referred to as "URL encoding", because any URL, be it a URL action or just a standard web URL, must have these characters encoded in order to function.

Here are the values for a few of the most common characters to need encoding in iOS URL actions:

  • ' ' (single space): %20
  • \n (newline, represents hitting the return key): %0A
  • :: %3A
  • /: %2F
  • ?: %3F
  • =: %3D
  • [: %5B
  • ]: %5D
  • %: %25

So a very basic URL action, such as launchpro://, which simply launches Launch Center Pro, would be percent encoded to launchpro%3A%2F%2F. This might look complex, but just break it down between each percent sign: "%3A" represents a colon, ":", and two "%2F" strings represent two forward slashes, "//". The complex looking string after "launchpro" is still just the simple "://" that we started with. Not too hard, right? This is really as complex as percent encoding ever gets, it simply takes whatever special characters are found in a string and swaps them out for their corresponding two-character string with a percent sign in front of it.

Take a glance at this slightly longer percent encoded URL action:


Breaking the action up at percent signs, we see mostly familiar characters: "%3A%2F%2F", as we already saw above, translates to "://". "%3F" translates to "?", %3D to "=", and "%20" to a blank space. I didn't list "%2C" or "%21" above, but they are "," and "!", respectively. So altogether this action decodes to:

launchpro://clipboard?text=Hello, world!

That's just a simple action to copy "Hello, world!" to your clipboard!

Of course, regardless of whether you know the percent values for basic characters, manually encoding a URL action would be incredibly tedious work. That's why we have methods to do it for us automatically such as wrapping code fragments in {{double brackets}} (works in Drafts and Launch Center Pro) or running actions to encode the contents of the clipboard so we can copy normal actions and paste their encoded versions where we need them. Still, it's smart to at least be able to understand these encoded values so that you are not intimidated when you see an encoded action. It's exactly the same as the actions you already can build and understand, simply with the special characters changed a bit.

So what happens if we need to double encode a string? Well in the first round of encoding, all the special characters were already swapped out with their percent values. This means the only remaining special characters are the percent signs from the originally encoded values.

Our simple launch:// action looks like this when double encoded:


This may look unreadable at first, but remember, every percent encoded character is a string of exactly two characters, prefixed with "%". So break the action up at the percent signs and decode each two-character string that follows: "%253A" is not a four-character percent encoded value, it's an encoded "%25" followed by the regular character "3A". Decode the encoded value, which itself is a percent sign, and you're left with "%3A". Do the same for the two "%252F" strings and you get "%2F%2F". Since this was originally double encoded, you've now dropped down a layer and are left with the single encode launchpro%3A%2F%2F. Decode those values and we're back to our unencoded launchpro://.

I'm not going to break down the more complex clipboard example we used above from its double encoded form because it's not necessary. You should already see the pattern: every level of encoding after the first one is just encoding a bunch of percent signs as "%25" and sticking that in front of the previous two-character strings. A triple encoded colon just encodes another percent sign: "%25253A". Decode it one level to "%253A", another to "%3A", and one more to be back to ":". Even if you encoded a colon one hundred times, it would just result in a percent sign followed by ninety-nine "25"s in a row, and finally a "3A". The value of every multi-encoded character lies in the last two characters in the string.

It's highly unlikely that you'll ever need to encode a string by hand at all, much less more than a single time. The only reason I've ever even single encoded an action manually is when it was a very simple one like launchpro:// and I didn't feel like copying it and leaving my text field to find a clipboard converter action when I could just type out "%3A%2F%2F". Even if you never have to do this yourself though, in the next section we'll be playing with double and triple encoded actions, and if you don't have a full grasp of how their encoding works, they start to look far more complex than they actually are.

The Launch Center Pro URL Handler

Now you understand encoding and decoding URL actions, but it's also useful to know exactly how an app deals with a URL action when it receives one, particularly when you're talking about a launcher app like LCP or Drafts. These apps include special variables, encoders, and other advanced features that need to be resolved to encoded text before the URL can be run, and each app might handle this in a different manner.

For Launch Center Pro, the special values in quesiton are [input variables], <TextExpander Snippets> and {{double curly bracket encoders}}. We'll refer to all of these together as the "special identifiers" available in LCP URLs. Input variables, as we discussed above, can be keyboard [prompt]s of varying types, [dropbox] link generators, multiple choice [list]s, or [clipboard] variables. TextExpander snippets are anything wrapped in greater than and less than signs, and they expand to whatever you've set their shortcuts to in TE. Finally, any text that you wrap in double curly brackets will be percent-encoded a single time.

Remember, URL actions can only be run if every single character that needs to be is properly percent encoded. Thus, if you try to run an action with "[prompt]" stuck in the middle of it, you will get an error because the brackets are not encoded. Same goes for greater than and less than signs and curly brackets. The reason special identifiers are allowed in our LCP actions is because Launch Center Pro's URL handler parses every URL before running, searching for these items. When it finds one, it resolves it before continuing. In the case of input prompts, "resolving" them means throwing up a prompt box for us to type into. Whatever text that we type is percent encoded and swapped out with the prompt identifier in the action.

For lists, the list identifier, including all its option parameters, is swapped out for the text attached to the button we pick. TextExpander snippets are expanded in the background to their encoded value without requiring user input. Any text wrapped in curly brackets is completely encoded and the brackets are removed. If the text was already encoded one or more levels, it is encoded again.

For most simple actions, thinking about the order of operations of these resolutions and how LCP goes about running a URL is unnecessary, but as we start to demand more from our actions, we can run into confusion.

The basic order goes something like this: First LCP validates that the URL can actually be run by looking at the top level "domain" of your action and making sure that your device has the app which the domain applies to installed. If you fail this step you'll get an error before it even starts to parse your action. Once it is confirmed that your action has the ability to be run (note that this is not confirming that your entire action works completely, just checking that it can even start to be run. You can easily pass this test and still have a fatal error in your code.), LCP scans the URL once and resolves all input prompts, lists and TE snippets in chronological order as it finds them, then it scans the URL a second time and all sections surrounded by curly brackets are encoded. Once every special identifier has been resolved, LCP runs the action from the start to the finish.

Once more, here is the exact order of the three steps LCP takes before running a URL:

  1. Validate the URL;
  2. Scan the URL searching for and chronologically resolving input prompts, lists, and TE snippets;
  3. Scan the URL a second time searching for and chronologically encoding any sections wrapped in curly brackets.

Once the action is running, if it is an x-callback-url action, then when LCP reaches the encoded part after "&x-success=", it decodes the chained action and immediately runs it as is. The key concept here: it does not scan for special identifiers a second time on a chained action. In other words, if you encode a prompt variable into your second action as %5Bprompt%5D, don't expect to see that input prompt pop up when the second action is decoded and called. Instead the text "[prompt]" will be passed into the action and it will keep running as normal.

There are a couple different ways to get around this annoyance. First, you can place unencoded input prompts within curly bracketed sections so that, as we see based on the order of the scanning steps, the prompts will be resolved before the section is encoded. For most actions, even going up to two nested actions, this method works great, but when you get into more advanced techniques with more than two nested actions, or start asking for more power from lists, you'll need to use the second, somewhat more complicated method: the launch://?url= scheme.

Using the Launch Center Pro URL Parameter

The Launch Center Pro URL scheme includes an optional url parameter, which can be used to surprisingly powerful effect.

Adding launch://?url= to the front of any standard URL action will seemingly quite simply just run the URL action. However, there are some key advantages to running a URL like this as opposed to running it directly.

Primarily, any URL action run from the url parameter will first be rescanned by LCP, so any special identifiers that were encoded during the first scan will actually get a second chance to be resolved. Furthermore, starting an action with launch://?url= will validate the URL automatically, because obviously Launch Center Pro knows that it is itself installed on your system. As you'll see in a moment, this bypassing of the validation step, coupled with the rescanning of the action passed into the url parameter, allows for some of LCP's most impressive advanced techniques.

We'll start with the rescanning part. For most actions, resolving all of your input prompts immediately is perfectly fine, but sometimes it makes more sense to delay when prompts further down the chain get resolved, and the url parameter can give you this type of control. Let's say you have an action that sends an in-app text message and then chains back and sends an in-app email, but you want all of this to happen via input prompts so that you don't have to tap around amidst all the text fields to get to each space you want to fill.

The standard way to make this work would look like this:

launch://x-callback-url/messaging?body=[prompt-return:Message Body]&x-success={{launch://email?subject=[prompt:Email Subject]&body=[prompt-return:Email Body]}}

And running that action would pop up three prompt boxes in a row, one titled "Message Body", the next titled "Email Subject" and the last titled "Email Body". After you've filled in and submitted each of the three boxes, the in-app messaging box will pop up where you can pick a recipient and send the message you typed. After you press send, the in-app email box pops up for you to fill in those recipients and hit send to finish the action. This action is okay, but wouldn't it make more sense to finish up sending the message right after you've typed it rather than after you've also finished typing out the entire email? Another point of confusion is that after typing the email, you aren't presented with the dialogue to send that email, but rather, thrown back to the message you typed to pick recipients for that first. This flip flopping adds friction to what should be a simple, easy workflow. Let's get rid of the friction.

If we get rid of the curly brackets and instead manually encode the email action, the scanner will not pick up the input prompts for the email subject or body. You will be prompted to type your message, then immediately given the message dialogue to send it off. Upon hitting send, x-success is triggered and the email action is run. Without our special method, LCP wouldn't scan the action for special identifiers again, so our email dialogue would pop up with the subject set as "[prompt: Email Subject]" and the body as "[prompt-return:Email Body]". However, toss the encoded email action into the url parameter of an otherwise blank LCP action and surround the whole deal with curly brackets and we'll get what we want:

launch://x-callback-url/messaging?body=[prompt-return:Message Body]&x-success={{launch://?url=launch%3A%2F%2Femail%3Fsubject%3D%5Bprompt%3AEmail%20Subject%5D%26body%3D%5Bprompt-return%3AEmail%20Body%5D}}

Let's break this action down like the URL handler does.

First, LCP checks that launch:// is a valid URL that can run on the system. Obviously that checks out, so now it scans the action for special identifiers, starting with input variables, lists, and TE snippets. It finds one input prompt and pops up a box titled "Message Body". You type in your message and hit "Launch" and that variable is resolved to whatever you typed. Now it scans again for curly bracket encoders, finds one set of them, and encodes our entire second action (meaning our email action, already encoded once, is now double encoded).

Once finished scanning, LCP actually runs the action, popping up the in-app messaging dialogue with the text from your prompt in the body. Add your recipients (there's currently no way to access the contacts dialogue via any sort of variable, so we have to stick to doing that from the actual message dialogue unless you can remember the phone numbers of every one of your contacts) and press send. This completes the first action and triggers x-success.

Now LCP throws away what it has already run and decodes the encoded chained action. Without scanning, it immediately runs the action, which calls LCP itself and passes it a url parameter. The url parameter resets the action, so LCP receives the new URL from the parameter, decodes it (since the originally double encoded email action URL was already decoded one level after x-success, this second decoding puts it back into an unencoded state) and starts the whole process over. launch:// is validated and the URL is scanned for special identifiers. It finds two input prompts, popping up boxes for you to resolve each of them. That finished, the action is scanned again for encoders, but since none are found it is run as is: the email dialogue pops up with the subject and body filled in, you pick your recipients, hit send, and the workflow is done.

Of course, all of that happens in a tiny fraction of a second, so when you run this action for yourself it will all seem instantaneous.

Now that you know what's happening in the background, we'll keep using that knowledge to leverage more power than just delaying input prompts.

As we saw in that last action, prefixing our actions with launch://?url= allows us to momentarily bypass the validation portion of the URL handler. A fantastic side effect of this is that it allows us to build lists with options that actually call their own actions instead of just adding text to another action.

Let's say you wanted to build a sort of action menu for the Messages app. Instead of creating a group in LCP with individual actions that you have to drag your finger to get to, you just want a single action which you can tap to bring up a menu of options, all of which are Messages actions to open up your conversation with a particular friend.

The intuitive way to do this would be to make an action that is just a list variable, and the actual actions that can be run are only located inside the list's options. In this way, the code in your LCP action would begin with [list: and then go on to define the list of actions. Try running something like this and you'll get an immediate error because you've failed to pass the URL handler's validation test: there's no app on your system that can be called by the URL [list:...]. Fortunately, we have an action that lets us pass that test automatically: just throw your list into the url parameter of an empty LCP action. If we wanted our action menu to be pretty simple, having just three options to jump to our conversation with three different friends, our code would now look something like this:

launch://?url=[list:Message Tim, Jony or Craig|Tim=sms:846-236-2275|Jony=sms:747-566-9483|Craig=sms:542-569-4247]

When run, this action will pass the first test, since the app itself is installed on the system. Next, the first round of scanning will find a list variable which needs to be resolved. We pick who we want to message and the list is resolved to the encoded value of that option. Next it scans for curly brackets, but finds none, so the action is run. The URL calls LCP and passes it the action we selected from our list, encoded, via the url parameter. LCP decodes the action, runs through its steps but find no variables that need resolving, and runs the action as is. From there we get bumped into the Messages app with a conversation open to the chosen recipient.

A static action menu like this is great, but it would be much more flexible if we could call for a prompt within whatever action we choose from our list. In fact, we can do that. It just takes a little tweaking of the list variable syntax.

Prompts in Lists

While it's a seemingly simple concept, placing input prompts in lists so that they are only called if the corresponding option is picked turns out to be a bit more complex than you would think.

When you launch a list using the standard list syntax, by default it encodes the contents of all of your options before it scans them for variables. If you have a list that looks something like this: [list:Title|Prompt=[prompt]], LCP does not present you with an input prompt when you select "Prompt" from the list. Rather, when you select "Prompt", it automatically resolves the list to the text "%5Bprompt%5D", because it encoded your prompt before presenting you with the list menu. To stop this overzealous encoding, you can use double brackets for your list variable instead of single brackets: [[list:Title|Prompt=[prompt]]]. This method does not encode the contents of your list, so if you put that list into an action and choose the "Prompt" option, you will get an input prompt, and whatever you type into that will be the value that the list variable is resolved to.

This method can make your lists infinitely more flexible: you can hard code most of your options into the list, but leave the final option as an input prompt so that in case you ever want an option that isn't part of the menu, you can just choose the prompt and manually type something.

The one thing to be careful about when using the double bracket lists is that since your list is no longer automatically encoded, you have to either manually encode any other options that are in the list which include special characters, or wrap those options in curly brackets to mark them for encoding. Note that the only parts of the list effected by this are the parameters after the equal signs, so you don't need to encode the title of the list or any of your button titles which you're attaching other values to. In the case of the Tweetbot search action we built previously, we can tweak the action to add a fifth option, an input prompt, by changing the code to this:

tweetbot:///search?query=[[list:Search Query|Search Tweetbot for ""={{}}|Search Tweetbot for ""={{}}|Search Tweetbot for "Launch Center Pro"={{Launch Center Pro}}|Search Tweetbot for "Apple"={{Apple}}|Prompt for Query=[prompt]]]

Unfortunately, there seems to be a few bugs with placing prompts in lists like this. In the case of the Tweetbot URL above, there will oddly be a trailing "]" after the text when you choose one of the hard coded options. I think this has to do with LCP closing the list variable at the second of the last three hard brackets, thus leaving a single "]" at the end of all the options. The prompt still works because it ends up with a closing bracket anyway, but the other options get an add on. This bracket doesn't actually have any effect on Tweetbot searches, but it's worth noting that it could affect other actions that you build using this method in more nefarious ways. Hopefully the bug will be fixed soon, but in the meantime if your action is actually affected negatively by it, you can get around the issue by using the method in the next section, it's just a bit more work.

Action Menus with Input Prompts

Using the launch://?url= scheme to build action menus gets even more powerful when we can include input prompts in the actions. We'll use a simple Fantastical action menu as an example. The menu will have three options: one to parse a prompt as an event, one to parse a prompt as a reminder, and one to simply launch Fantastical.

The code for such a menu would look like this:

launch://?url=[[list:Fantastical Action Menu|Parse Event={{fantastical2://parse?sentence=}}%5Bprompt%5D|Parse Reminder={{fantastical2://parse?sentence=}}%5Bprompt%5D{{&reminder=1}}|Launch Fantastical={{fantastical2://}}]]

Let's break this down. First LCP validates the URL because of the launch://?url=, then it starts scanning for input prompts, lists, etc. It finds our double bracketed list variable and throws our action menu up to resolve it. When we pick an action, the list variable is replaced by it.

Moving to step three, LCP scans the action again looking for encoders. It finds the ones that we've placed around our action (since we used the double bracketed list, we have to use the encoders because it isn't automatically encoded) and encodes them.

Note that every part of the actions in the list are wrapped in curly brackets except for the input prompts, which are already encoded. This is how we avoid the bug mentioned in the previous section: since our prompt starts out in an encoded state, its closing bracket doesn't mess with LCP when it is scanning the list. Instead, it gets passed over until the action of whichever option you picked is loaded onto the the launch://?url=.

With all unencoded special identifiers resolved, LCP moves to the next step and runs the action. As before, our empty LCP action now decodes and calls the attached URL, also resetting the URL handler so it starts scanning again. On this scan, our previously encoded prompt has been decoded, so it is picked up as a special identifier and we get a prompt box to resolve it. The value of what we typed is encoded into our Fantastical action and the action is run, sending us to Fantastical to parse our event or reminder, depending on which action we picked.

While the original method of placing prompts within lists usually works alright, I encourage you to use this method whenever possible just to play it safe and avoid any possible bugs with lingering closing brackets. Using this method on the Tweetbot menu from earlier simply requires looking at the action a little differently. Rather than running a Tweetbot action directly and only filling in the part after ?query= via our list, we instead run another empty LCP action and each of our list options fills in the entire Tweetbot URL, including the hard coded text or the input prompt, depending on which one is chosen. The resulting action is significantly longer, but most of the extra work is just copying and pasting the main part of the Tweetbot action, so I think it's worth it for the added stability.

One last thing to note: the curly bracket encoders that we wrapped all of our hard-coded options in last time are now being used to encode the Tweetbot action itself, so anything that was being automatically encoded originally now needs to be encoded manually and placed within the curly brackets. The result is double encoded search queries, which are necessary to run the action from an LCP url parameter. In this case we only need to manually encode "Launch Center Pro" since the other search queries don't have any special characters that need encoding, but in your actions you may need to do more work.

After converting the Tweetbot action to the launch://?url= format, it ends up looking like this:

launch://?url=[[list:Search Query|Search Tweetbot for ""={{tweetbot:///search?}}|Search Tweetbot for ""={{tweetbot:///search?}}|Search Tweetbot for "Launch Center Pro"={{tweetbot:///search?query=Launch%20Center%20Pro}}|Search Tweetbot for "Apple"={{tweetbot:///search?query=Apple}}|Prompt for Query={{tweetbot:///search?query=}}%5Bprompt%5D]]

Running both formats of this action will appear completely identical in LCP, but they are doing very different things behind the scenes, and for that the longer model is much better.

Nested Lists

The intuitive thought for how to nest a list inside of a list would be to follow the same easy syntax as we used in the first Tweetbot action with a prompt: use double brackets for the first list and single brackets for the second. Unfortunately, LCP gets even more buggy when you try that than it does with standard input prompts, and you'll probably end up causing the app to crash or getting a completely nonfunctional action.

Luckily, we can get around this in almost the exact same way we did with our nested prompts: encoding the nested list. The only difference between the two methods is that to get LCP to scan and resolve the nested list we need to place it in the url parameter of a second empty LCP action so that, just like with our action menus above, it will pass the first test that validates that the URL can be run.

So let's add more functionality to our Tweetbot search action. If you have multiple Twitter accounts (like I do), you might want to perform your searches via a specific account, and you also might want a different list of searches depending on which account you're searching from.

You could have two action lists, one for each account, or you could just have one action with a nested list: first pick the account and then get the corresponding search list. My two main accounts are @theaxx and @ajguyot. I use the former mainly for tech related tweets and a purely tech oriented timeline, while the latter is for tweets more applicable to people I know personally and with a timeline mainly of my local friends. For this search action, I'll keep the menu the same for my @theaxx account, but search for "U of A" (my school), "Wildcats" (our mascot) and "Tucson weather" from @ajguyot (complaining about the heat is a staple of Tucsonian conversation).

To begin, we'll build the two action menu lists (the ones to be nested) first. Both of these actions will actually function perfectly as non-nested action menus because they are set within LCP url parameters. Nesting them after they're built is quite simple. We already built the action menu for @the_axx above, and our nested URL will be identical.

The one for @ajguyot, in my case, will look like this:

launch://?url=[[list:Search Query|Search Tweetbot for "U of A"={{tweetbot://ajguyot/search?query=U%20of%20A}}|Search Tweetbot for "Wildcats"={{tweetbot://ajguyot/search?query=Wildcats}}|Search Tweetbot for "Tucson Weather"={{tweetbot://ajguyot/search?query=Tucson%20Weather}}|Prompt for Query={{tweetbot://ajguyot/search?query=}}%5Bprompt%5D]]

Now build the outer part of the action, including the parent list, but with the option values not yet filled in:

launch://?url=[[list:Search Tweetbot Via...|@the_axx=|@ajguyot=]]

To finish it off, just single encode both of the action menus and place them after their corresponding equal signs in the parent list. The final product will look like this:

launch://?url=[[list:Search Tweetbot Via...||@ajguyot=launch%3A%2F%2F%3Furl%3D%5B%5Blist%3ASearch%20Query%7CSearch%20Tweetbot%20for%20%22U%20of%20A%22%3D%7B%7Btweetbot%3A%2F%2Fajguyot%2Fsearch%3Fquery%3DU%2520of%2520A%7D%7D%7CSearch%20Tweetbot%20for%20%22Wildcats%22%3D%7B%7Btweetbot%3A%2F%2Fajguyot%2Fsearch%3Fquery%3DWildcats%7D%7D%7CSearch%20Tweetbot%20for%20%22Tucson%20Weather%22%3D%7B%7Btweetbot%3A%2F%2Fajguyot%2Fsearch%3Fquery%3DTucson%2520Weather%7D%7D%7CPrompt%20for%20Query%3D%7B%7Btweetbot%3A%2F%2Fajguyot%2Fsearch%3Fquery%3D%7D%7D%255Bprompt%255D%5D%5D]]

Launching that action will present you with a list titled "Search Tweetbot Via..." that includes two options: "@the_axx" or "@ajguyot". If you choose the first option you'll immediately see the same action menu we built before. If you choose the latter, you'll get the second action menu, the @ajguyot specific one, with options to search for "U of A", "Wildcats", or "Tucson weather". Whichever menu you pick from will first direct Tweetbot to the corresponding Twitter account before conducting the search.

Obviously, trying to search via my Twitter accounts, and for queries that are probably different from what you want, is not very useful. But use the exact same method to build up your own action menu lists and then just encode and nest them and you can have a powerful nested list menu that is applicable to you as well.

Building Bigger Action Chains

Sometimes two actions doesn't cut it. Certain workflows require three or four different actions to be chained in order to fully automate the process. In Drafts, we chain more than two actions by saving each pair of actions as their own action and then calling that action by name from a different one. In Launch Center Pro, chaining in that manner is impossible because we cannot call saved actions by name via URL scheme to run them; every action has to be hard coded into our chain.

While this makes chains of more than two actions complex and hard to read, it does not render them impossible. If you require some sort of huge six or more action chain to satisfy your workflow, I advise you just go build that in Drafts -- it's better fit for such a task. However, some LCP workflows could practically stretch to needing three or four chained actions, and doing so is actually fairly easy. Visually, large chained actions appear incredibly complex, but this is just because they require high levels of encoding. As we discussed earlier, deep encoding is not actually all that complicated, it's just really hard to read. To get around the reading difficulty, just lay out your chained actions individually, unencoded, and then go down the list encoding each line one more time than the last before pushing them all together.

Let's say you want to build an action to upload your last photo to Dropbox and then send the link, along with some comments, via both iMessage/SMS and Email. First build your three actions, in their unencoded forms, starting with the Dropbox action to upload your last photo:


This action uploads the most recent photo on your camera roll to Dropbox in the "/Photos" folder, then copies the link to that photo to your clipboard. Now make the next action to send that link via iMessage:


This action will prompt you for a body for your message, then add the Dropbox link that's on your clipboard to the line right beneath whatever you type in the prompt. Finally, build the last action:


This will first prompt you for the subject of your email, then the body, and finally place the Dropbox link from the clipboard (make sure not to copy anything to the clipboard in the messaging action in the middle or you'll lose the link) on the line underneath your text.

Now you have three individually functioning actions. All you have to do to chain them is stick them together with the proper levels of encoding and a few strategically placed launch://?url= actions. I find the easiest, least mistake-prone way to go about putting them together is to lay them all out on individual lines right beneath each other and add &x-success= to the end of every main action except the final one. First though, the empty LCP actions.

As we discussed earlier in the guide, placing an action behind launch://?url= will cause LCP to rescan it for special identifiers. In our individual action for this chain, each one has a few special identifiers which we don't want resolved until the actions before it have been run. To make sure these are resolved at the proper time, we just place the action in the url parameter of an empty LCP action. This, of course, means the action in the url parameter needs to encoded another time. That will add a lot more levels of encoding to our actions, but it's worth it to get special identifiers working as they should.

Before we start encoding, we'll lay our actions out on individual lines, resulting in this:

  • launch://x-callback-url/dropbox/addphoto?attach=lastphoto&path=%2FPhotos&getlink=1&x-success=
  • launch://?url=
  • launch://x-callback-url/messaging?body=[prompt-return:Body]%0A[clipboard]&x-success
  • launch://?url
  • launch://x-callback-url/email?subject=[prompt:Subject]&body=[prompt-return:Body]%0A[clipboard]

With that done, just encode each line one time less than the line number it's on (the first line is not encoded, the second line is encoded once, the third line is encoded twice, etc.) and finish by deleting the lines between them. Thus, our actions from above, with each line encoded once more than the last, will look like this:

  • launch://x-callback-url/dropbox/addphoto?attach=lastphoto&path=%2FPhotos&getlink=1&x-success=
  • launch%3A%2F%2F%3Furl%3D
  • launch%253A%252F%252Fx-callback-url%252Fmessaging%253Fbody%253D%255Bprompt-return%253ABody%255D%25250A%255Bclipboard%255D%2526x-success%253D
  • launch%25253A%25252F%25252F%25253Furl%25253D
  • launch%2525253A%2525252F%2525252Fx-callback-url%2525252Femail%2525253Fsubject%2525253D%2525255Bprompt%2525253ASubject%2525255D%25252526body%2525253D%2525255Bprompt-return%2525253ABody%2525255D%252525250A%2525255Bclipboard%2525255D

And finally, removing newlines, this:


Laying it out before encoding each line makes the process of building bigger chains a lot easier, but it can still be a big hassle to run an action to single encode each piece four or five times in a row to get them to the right level of encoding. Furthermore, it leaves the process a lot more prone to you accidentally encoding a line one time more or less than it needs to be, and ruining the whole action.

Determining where a bug is between actions that are encoded four or five times is a ridiculous task. For this reason, I built an LCP list action menu which presents you with options to automatically encode the contents of your clipboard up to six times. Just cut the piece of the action you're ready to encode, jump over to LCP, and run my "Encode Clipboard x Times" action. Then, pick the number of times your line needs to be encoded from the list and it will be encoded to that level automatically. Paste the line back in and you're good to go.

Here's the Direct Import Link for the "Encode Clipboard x Times" action.

For anyone who wants it, here also is the Direct Import link for the action we built above, which will upload the last photo on your Camera Roll to Dropbox and then present you with (properly timed) prompt boxes to fill in and send first a message and then an email with the link.

Taking Advantage of the Clipboard Variable

One advantage that Drafts has over Launch Center Pro is that all Drafts variables are persistent across actions. If you place a [[title]] variable in a Drafts action in both the primary action, and the second action chained via x-callback-url, that variable will be swapped out for the same content, the first line of the Draft, in both actions. Launch Center Pro variables are different.

Since LCP is based on actions instead of text, when we call up an input prompt, it will only substitute for the single corresponding prompt variable in the code. After it is substituted, that text essentially disappears, there is no way to access it in another part of the action. However, there is one persistent variable that LCP does support: the [clipboard] variable.

If you want to build an action which requires (or would be significantly easier if you could type text once and use it multiple times in the action or actions chained to it) [clipboard] will allow you to do so.

In general, I try to avoid clipboard hacks. They're messy because they change the system clipboard, and therefore reach outside the confines of the URL action we're using them for. Sometimes though, there is no other way to accomplish an action without typing the same text again and again.

Using [clipboard] as a persistent variable isn't difficult, but it will require one of our earlier techniques. The basic theory is that we will first run an action which copies an input prompt to the clipboard, thereby saving whatever text we wish to use to a place that we can draw it from more than just once throughout the action. Next, we chain our actual action to the back of the clipboard action and call [clipboard] instead of [prompt]. That will draw the text that we saved to the clipboard in the prompt from our first action. Now when we chain another action, we can call [clipboard] again and reuse the text for a second time, or as many times as necessary.

We'll build another example action to make this clearer. Similarly to our last action, let's say we want to send both an iMessage and an email, but this time we want to use the same text in each body, and draw it from a single prompt box (instead of sending a Dropbox link with different prompt boxes for the message and the email bodies). First we'll build the action like we would if we're using different prompt boxes. It's quite simple, and looks like this:


Now we'll build the clipboard action which we're going to use to decrease our work to only one prompt box. It's also really simple:


The logical next step would be to swap out the prompt variables in our first action for clipboard variables and then tack it onto the x-success in the clipboard action, and that is what we need to do, but first there's one last step.

As you learned in the section on the LCP URL handler, Launch Center Pro scans the action and resolves all variables before doing anything else. Thus, if the handler finds clipboard variables in the first scan, it's going to resolve them before it runs the action that copies your prompt to the clipboard. That will fill your actions with whatever text you previously had on your clipboard before running this action.

You can probably already guess the fix for this: just encode the chained action an extra time and put it on the back of a launch://?url= action. As a result, the first scan will only resolve the prompt variable in your clipboard action, then the action will run and copy that prompt to the clipboard, and finally it will decode the rest of the action, scan again, and resolve both clipboard variables to the text from your prompt.

Altogether, the resulting action looks like this:


Running this action will give you a single prompt-return box, labeled body. Type your chosen body and press "Launch" to be presented with an in-app message box with the message already filled in with your text. Choose the recipient and send the message and then automatically be presented with an in-app email action with the body filled in with the same text. Just choose a recipient and type a subject and send to complete the action.

Recursive Actions

In Drafts, recursive actions are fairly simple: just call the name of the current action in its own x-success action. Unfortunately, as I've already mentioned, LCP does not support calling saved actions by name. However, if we combine all of the strategies we've already discussed, we can use a clipboard hack, url parameters and our knowlegde of the LCP URL handler to make powerful recursive actions without relying on Drafts as a helper app.

We'll make a recursive action to parse an unlimited number of events in Fantastical. For this task, we'll use a basic Fantastical action to parse an event and then chain to another action. The action looks like this:


If we wanted this action to be chained twice, we would just encode it and add it to an LCP action url parameter, then tack it to the back again, like so:


To repeat it a third time, we would just encode again and put it in another x-success. There's a pattern: after the first time, the action is exactly the same, just the first action in an LCP url parameter, except with more levels of encoding. Since the action never needs to change again, we can save it onto the clipboard and then call the clipboard as an action in x-success.

Adapting the Fantastical action to successfully call the clipboard results in this:


That action will parse an event in Fantastical, then launch LCP, resolve the clipboard variable, and run whatever is on the clipboard. If the clipboard houses an action, that action will be run. The trick is making sure the clipboard houses that action, but we already know how to do that: just load the action onto the clipboard via an LCP clipboard action, then chain back and launch the clipboard like we did earlier.

We want the clipboard to run this action:


So our clipboard action will look like this:


The result will load our Fantastical action onto the clipboard, then launch the clipboard as an action. The Fantastical action itself will first call up a prompt, then send the prompt to be parsed as an event in Fantastical. It will then automatically add the event and return to Launch Center Pro. To make this action recursive, we just need one last step: instead of simply returning to LCP afterwards, we'll return and call the clipboard again. To do this, just change the x-success variable of the action we are loading onto the clipboard from launch:// to launch://launch://?url=[clipboard], properly encoded of course.

The final result:


This is a recursive action which will present you with a prompt box, then send that prompt box as an event to be parsed in Fantastical, then return to LCP and automatically give another prompt box. The process will repeat until you press "Cancel" on the next prompt box instead of "Launch".

Here is the Launch Center Pro Direct Import Link for the recursive Fantastical action.

For anyone interested, here is another LCP Direct Import Link for almost the same action, except this one parses items as reminders instead of events.

Headless Actions and Bookmarklets

Using the power brought on board by lists, we can build “headless actions”. A phrase coined by Federico Viticci, headless actions are those which are called externally, but utilize Launch Center Pro’s unique capabilities. The actions are “headless” because they do not require an action to be present in your grid in order to run. Although you can definitely set up an action like this to be called from Drafts, Pythonista, Editorial or some other app, one of the best ways to utilize them is via a bookmarklet.

In Federico’s example, he calls the headless action from a bookmarklet which sends the URL of a webpage over to LCP. In Launch Center Pro, a list is brought up with a variety of possible actions which will send the URL to different apps or services. Using a Launch Center Pro list and Federico’s idea, we can set up any number of different actions to be called using the data sent from Safari, building a versatile action menu for use in many different situations.

Headless actions are still a bit of a hack, very limited by the aforementioned issues with LCP lists, but they are just more examples of the powerful possibilities of Launch Center Pro if you spend the time to think about and build something great with it.

Integrating With Drafts and Pythonista

Drafts and Pythonista can be great partners with Launch Center Pro. While LCP is certainly powerful on its own, it does not have quite as far reaching capabilities as Drafts for Dropbox or email actions, and it has no Evernote actions at all.

As mentioned earlier, Launch Center Pro also does not support x-callback-url for every type action, most notably social media posting actions, but Drafts does. Luckily, since every action in Drafts can be called via external URL actions, you can place launchers for your Drafts actions in your Launch Center Pro action grid. I use this for quite a few actions, such as my Cross Post and Triple Cross Post actions.

However, while it works perfectly to just call your Drafts actions from LCP and end up in Drafts after they have been completed, I always like to end up back in the app I started in after I run an action. I think the overall experience is nicer and more natural if you end up back inside of Launch Center Pro after you launch one of these external actions from it. This is possible to do in almost every situation involving Drafts actions, but it may take a bit of tweaking to do so.

Drafts sometimes has a tendency to rush through actions and call x-success parameters before it finishes all of its tasks. If your x-success parameter sends you back to Launch Center Pro, you may jump out of Drafts before it has finished some of its directives, causing them to be halted by iOS. Generally I run into this issue when I have a chained action inside of a chained action. While Drafts is unwrapping the first action and running through it, it skips back and calls x-success in the parent action. This annoying behavior can be easily fixed, however, by splitting your actions up so that you never nest a chained action. It requires a few more actions than the Drafts version, but once you’ve built the chain you can hide the excess actions from your Drafts list and never be bothered by them again.

In the Launch Center Pro version of my Cross Post action, I had to split the Drafts Cross Post action into two new actions in order to get Drafts to delay long enough to finish posting to both services. The first action posts to, then chains back and calls the second action. The second action tweets, then chain back to launch LCP. I’ve found that the little bit of extra work put into splitting action chains up in order to end where I started from makes my experience feel less like a hack, which I like.

Pythonista scripts can also be called from Launch Center Pro using the Pythonista URL scheme. This means that if you have any tasks that are too complicated for URL actions, you can still have quick and easy access to scripts you build for them from your Launch Center Pro action grid. You can utilize the LCP input prompts to send any necessary text to the scripts as well.

Using Drafts or Pythonista alongside Launch Center Pro lets you utilize the best aspects of all three iOS automation titans. Launch Center Pro has unarguably the best UI for launching actions, but Drafts and Pythonista have some more powerful capabilities. Thanks to URL schemes, we don’t have to pick one of these apps as our primary automation assistant, we can choose them all.

Wrap Up

Beyond its brilliantly simple grid design, Launch Center Pro contains an extraordinary amount of power and versatility.

After reading this guide, you should be able to tap into that power, making use of some of the most advanced capabilities of any iOS app. Fully integrating Launch Center Pro into your life will take time: you first have to evaluate your workflows and daily tasks to see which ones can be sped up through URL actions. Once you know what you want to accomplish, just remember the information from this article and building the necessary actions and setting up your own Launch Center Pro action grid should be easy.

You can find Launch Center Pro on the App Store at $4.99 for iPhone and $7.99 for iPad (sold separately).

  1. With the advent of Control Center this feature is effectively obsolete, but before iOS 7 this was by far the fastest and easiest way to turn on your flash. 
  2. To enable this functionality, you first have to connect your Dropbox account with Launch Center Pro in settings.