This Week's Sponsor:


Ensure that if a device isn’t secure it can’t access your apps.  It’s Device Trust for Okta.

Automating iOS: A Comprehensive and Updated Guide to Launch Center Pro

Note: The following is a complete update of our original Launch Center Pro guide published in April 2014. It has been rewritten and updated for the latest 2.3 and 2.3.1 versions of Launch Center Pro with new sections, actions, videos, and more.

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 on 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 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.

August 2013 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. In May of 2014, Editorial 1.1 made waves once again, and was quickly followed by the huge Launch Center Pro 2.3 update (more on that later). Right now we have the next update to Drafts to look forward to, hopefully including the intriguing new action builder Greg Pierce has teased on Twitter.

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. Moreover, after this year’s WWDC, the new Extensions coming in iOS 8 could redefine the field once again, and I can’t wait to see how these developers will evolve their apps to compete in this impending new era of iOS automation.

Today, Launch Center Pro (or “LCP”) has come incredibly far from its rudimentary beginnings. Once a simple app launcher held back by the lack of support for more advanced actions from third party developers, the expanding interest in URL schemes have let Contrast focus on beefing up LCP’s internal functionalities. While on the surface it looks deceptively simple, and no more than 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 had 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 LCP’s full feature set.

Download Launch Center Pro

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, and in general is not very helpful for automation purposes. 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 nine rows (ten 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 six 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 four 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.

The “Featured Actions” section is new in LCP 2.3, and includes a list of actions which Contrast has deemed interesting enough to feature more prominently. These are generally more complicated actions which would require advanced knowledge of the app for users to make on their own. As of now this list is pretty small; perhaps in the hustle to get 2.3 out the door Contrast forgot to fill this list with more actions, so I’m hoping it gets more attention soon. I would also love to see an option somewhere in the app to submit actions to Contrast for consideration of being added to the list. A feature like that could give more people greater incentive to make cool actions, as well as creating a central place for others to find these actions. Both of those would be huge benefits to all Launch Center Pro users. If Contrast made more use of this section, and curated it with powerful actions submitted from many different users, I could see this becoming one of the most used sections in the Action Composer.

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: Keyboard Prompt, Number Pad, and List 1. We’ll get to List later, but if you choose one of the first two options, 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 number pad it will be “prompt-num”. Other hidden special keyboards will be discussed later on, and each has its own identifying string as well.) 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, 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 “Keyboard Prompt”. This will place the text [prompt: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: launch://messaging?body=[prompt:Body].

Here’s a quick breakdown 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:Body] tells Launch Center Pro to display a prompt box, labeled “Body” and using the standard LCP 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 give you two options: Choose Contact Now or Ask Each Time. Picking the former brings up a window with all of your iOS contacts. 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:


If you pick the Ask Each Time option, that will insert the [contact] tag into your action. New in 2.3, this tag will automatically call up the contact picker every time the action is run. This seems like a small feature, but it’s actually quite useful. Personally, I prefer typing all of my messages in the actual iOS Messages app rather than in the Launch Center Pro prompt boxes or the in-app messaging windows. As such, most of my messaging actions use Apple’s URL scheme for Messages: sms:. Following the colon in each action is the phone number for one of my friends or family members which I text regularly. Thus, when I run one of the actions, it opens directly to my conversation with the corresponding contact. This saves me tons of time searching through list items in the Messaging app to find the friend I want to message, a particular annoyance if they are somewhere far down the list of conversations.

The problem I’ve always had with this workflow is that any time I want to send a message to a contact who I don’t text regularly, and thus does not warrant their own action in my LCP group, I have to do it manually in Messages, which requires a lot more taps than my LCP shortcut (open Messages, swipe back to exit open thread, tap Compose button, start typing contact name, choose contact, tap text box, start typing message versus open LCP, tap-swipe to correct action which automatically switches me to in the proper thread, start typing message).

Thanks to the new [contact] tag, I can now go to LCP first no matter who I want to text and still be switched to in order to type. The URL action for this is one of the simplest you’ll see: sms:[contact]. With this action, I can open LCP, tap-swipe to my “other contact” action (which automatically brings up the contact picker), slide the picker to the proper letter for the contact I’m looking for and choose that contact’s number, then automatically be sent to with the cursor in the text box ready to type. In practice, this may only be a few taps less (although every tap counts for iOS automation enthusiasts, so that alone would be a good reason to use this), but the key is that I can now start in Launch Center Pro every time I want to send a message to someone (replying to messages not counting, as I of course just swipe the notification and go straight to the app), and the swipe to start typing or pick a contact is almost exactly the same no matter who I intend to message. This coalescence of similar tasks into one central place is one of Launch Center Pro’s biggest advantages.

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 (encoded as %0A in URL actions) 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 type within the brackets after the colon ([textexpander: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).

Location Triggers

The next two option in the Action Editor are Location Triggers and Notification Sounds. Notification sounds are pretty self explanatory: you can choose to assign one of several sounds to an action and any time a notification for that action is triggered your device will emit the sound that you pick from this list. Location triggers are more interesting.

With location triggers, you can now set up geofences or iBeacons to trigger action notifications on your devices when you enter or leave specific locations. I don’t have any iBeacons to test that functionality with, but I’ve been testing the geofences with a simple action which I’ve found quite useful.

I do most of my work from my local Starbucks, and thus go there almost every day to write or pursue other side projects. I also use Begin to keep a simple list of tasks which I need to get done every day. To test LCP’s location triggers, I’ve been using a geofence to give me a notification every time I enter Starbucks. Swiping the notification automatically launches Begin so I can review the list of tasks I’m planning on getting done before I leave. Furthermore, LCP provides me with the same action notification when I leave Starbucks, so I always remember to launch Begin again and check off all of the tasks I successfully completed during my stay. Another thoughtful addition within this feature is the ability to set multiple locations for the same action. There are two Starbucks locations fairly close to my house, both of which I visit fairly frequently. Since I don’t have a particular schedule for which one I’m working at on a given day, I can easily just set my Begin action to trigger when I arrive at and leave from either of these locations.

That is a very simple example of what LCP’s location triggers can do. You can launch any action with them, from opening an app to performing an entire chain of actions across multiple apps and services. Beyond arriving and leaving, LCP can also filter when location triggers are called by time of day and day of week. If you trigger a notification whenever you go to work, but you only work on weekdays, you can tell LCP to never trigger that notification on Saturdays or Sundays. Furthermore, if you always arrive at work between 8 AM and 10 AM, you can tell LCP to only trigger a notification between those time periods. That way if you leave for lunch, when you come back you won’t be bothered with the same location based notification at a time when you don’t want it. Another way to avoid duplicate notifications is through the useful “suppress duplicates” setting. This parameter allows you to suppress any duplicate notifications for a specified amount of hours/minutes, with a max of just under 24 hours. The default is 30 minutes, so if, for instance, you have an action set to trigger when you leave your house, but you forget something at home and have to return and get it before leaving again, you will only be notified once upon leaving instead of twice.

Location triggers are a great addition to Launch Center Pro, adding versatility to the old “scheduled actions” function which has been around since day one, but which I never found particularly useful, as my schedule Is not very regular.

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, LC Callback, IFTTT and Giphy integration, 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 writing 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 of 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 create your actions in Drafts, you can use install my import action, 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.3
  • launch://qr – Activate Launch Center Pro’s built in QR code scanner.
  • launch://ifttt – We’ll get to this later.

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 deprecated 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:

launch://x-callback-url/messaging?to=555-555-1212&attach=lastphoto&x-success={{launch://email?to={{}}&subject=Photo&body={{Here's a photo I took!}}&attach=lastphoto}}

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 there are encoders. LCP will find the portions of the action surrounded by double curly brackets, remove them, and percent-encode those sections of the action before running 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.

With proper final encoding, the second action will look like this when it is run:


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.

Fun With Prompts

Launch Center Pro also comes equipped with a few extra options for input 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-numbersandpunctuation] immediately shows the “123” keyboard. It also doesn’t switch back to the “ABC” keyboard when you press the space bar. I’ve found this prompt useful when I want to type in times, as there is no prompt to bring up the iOS system date picker to input times or dates.
  • [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 pressed, instead of inserting a line break it will insert (by default) a comma. 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. As of Launch Center Pro 2.3.1, the list feature has even more abilities. You can override the default functionality to insert any character, or string of characters, instead of a comma. This is done by adding your chosen characters in parentheses before the closing bracket. For example, [prompt-list(, )] will insert a comma followed by a space into your prompt box every time you hit return, resulting in more readable lists if you want to use them for something besides sending data to task apps. You can place any character or string between the parentheses, and the ability to turn the return button into anything you want it to be could have great time saving benefits.

Beyond choosing different prompt types to present yourself with the most useful keyboard for a given task, Launch Center Pro 2.3.1 has also added the ability to include default text inside of your prompts, and even choose a position within the default text to start your cursor. When a prompt which has default text is activated, the text will automatically appear inside of the prompt box. If you’ve set a cursor position, your cursor will appear in that position with the rest of the default text displayed on either side of it.

This feature doesn’t add much that we couldn’t do before by simply hard coding text into our actions on either side of a prompt, but it can be nice for making that hard coded text more explicit so you never forget what it says, or in case you need to tweak it sometimes before running an action. To include default text, simply add an equals sign after your specified prompt type, but before the closing bracket of the prompt, and then type the default text after the equal sign. If you want your cursor to appear somewhere other than at the end of the default text, include a backslash followed by a pipe symbol (\|) within the default text, and when you run the action those symbols will be removed and the cursor will be where they were.

LCP 2.3 also introduced the ability to place prompts inside of prompts. Thanks to other behind the scenes improvements, this feature is completely intuitive: simply place another bracketed prompt inside of a first one. Paired with the default text features from 2.3.1, this results in some interesting new possibilities.

This summer I’m working as an intern at my church. Among other things, I’m collaborating with a small team to rebrand the church and redesign its website. For a large, old organization, this is a long process, and it requires that I go to a lot of meetings. Previously I was using a basic LCP action to manually type the details of each meeting and send them to Fantastical to be parsed, but I’ve now designed a neat action which combines the new nested prompt and default text features to make the process quicker and easier. Here’s the action:

fantastical2://x-callback-url/parse?sentence=[prompt:Review=Meeting[prompt:Attendees= With ] at [prompt-NumbersAndPunctuation:Time] on [prompt:Day] ]&add=1&x-success={{launch:}}

This is a pretty straightforward action which launches Fantastical, sends it a sentence to be parsed, automatically imports the sentence, and returns to LCP when finished. The one part you may find nebulous is the mass of prompts which make up the sentence we want Fantastical to parse. Here they are pulled out of the action:

[prompt:Review=Meeting[prompt:Attendees= With ] at [prompt-NumbersAndPunctuation:Time] on [prompt:Day] ]

This is actually just a single prompt, but with a few nested prompts within it. The outside, parent prompt is titled “Review”, and all of the nested variables are part of its default text. Launch Center Pro will parse these chronologically before it parses the parent prompt. So when the action is run, the first thing you will see is a prompt titled “Attendees” which has the default text ” With ” already present in the text box. This is of course where you would type the attendees of the meeting. When that’s done, tap the Next button to get another prompt, this one titled “Time” and with the “123” keyboard being shown instead of the standard “ABC” keyboard. Type in the time of your meeting and press Next again. The next prompt is labeled “Day”, and you should type the day of the week of your meeting into it. Now that all of the nested variables have been resolved, you will see the parent prompt title “Review”. The prompt box will have the contents of everything you’ve typed thus far, so it will be something along the lines of “Meeting With John at 11:30 on Thursday “. This prompt box serves two purposes. If in this particular instance you want to add more information, such as a more descriptive title for the meeting or a date (in case the meeting is not in the current week), the cursor is already positioned with a space after the day of the week, so you can immediately type “July 31”, or whatever your date is to be, and launch your action from there. If you want to edit a different part of the prompt, just tap where you want to type and go from there.

The parent prompt’s second purpose is to give you a chance to review your sentence and correct any mistakes before sending it. The &add=1 parameter tells Fantastical to automatically parse your prompt and return to LCP without you needing to interact with it. This is nice in the sense that it saves you an extra tap after waiting for the delay of swapping to and loading another app, but less nice in that once you launch your action you can’t check to make sure everything has been parsed properly. The last prompt box provides you an opportunity to quickly glance over your sentence and make sure you didn’t have any typos before it is sent for parsing.

Default text and nested input variables allow you to add a new level of finesse to your actions which was previously impossible. These aren’t groundbreaking new features, but they can be used to make our actions clearer and easier to deal with or share with others.

Other Input Tags, Attachments, and Lists

Other than prompts, there are also a few other useful input tags for you to try out. We already discussed the [dropbox] tag, but there are a few variations to draw some more functionality out of it as well.

  • [dropbox-text]will bring up the Dropbox file picker just like the normal Dropbox tag, but this time when you choose a file, the full text contents will be inserted into the action instead of just a link to the file in your Dropbox.
  • [dropbox-direct] will insert the direct link to your Dropbox file rather than the link to the share page as the standard tag does.
  • Adding a colon and a file path after the prompt type can open the Dropbox picker directly to a folder. For instance, [dropbox:Apps/Launch Center Pro] will open the Dropbox picker directly into your “/Apps/Launch Center Pro” folder. This method works with [dropbox-text] and [dropbox-direct] input tags as well.

Launch Center Pro 2.3 also brought integration with the popular GIF aggregation service Giphy. GIFs can now be sent as attachments in LCP’s messaging and email actions, or added into any action by inserting a GIF’s direct link. You can programmatically access Giphy’s trending section, search for GIFs with a keyword via hard coded text or input prompt, or use a URL to attach a specific GIF. GIFs can be downloaded and attached with the photo:gif command, but use the [gif] input tag to send their direct links instead.

There are three variations of the [gif] tag:

  • The standard [gif] with nothing added on will open up the built in Giphy browser to the Trending GIF page. Choose a GIF to have its direct link placed inside of your action.
  • [gif:search term] will open the Giphy browser with a predefined search for whatever you put in place of “search term”.
  • [gif-id:ZHbgdNcM9Tv4Q]will directly link to the GIF with whatever ID you use after the colon.

There’s an important distinction to be made between attaching a GIF and linking to a GIF. First off, only a few actions even support actually attaching media, and not all of these work with GIFs. An attachment actually sends the file itself, while linking just sends a link to the file which is hosted somewhere online. Since URL actions only allow the transfer of text, the only actions which can support true attachments are those which Launch Center Pro includes built in support for (or uses an iOS system level functionality for). Thus, messaging, email, and Dropbox actions can include attachments, as can the Tweet, Facebook, and Share Sheet actions which use the iOS integration with Twitter and Facebook 4 and the iOS system Share Sheet. All other actions will require you to just send links to photos or GIFs rather than actually attaching them.

Attaching photos or GIFs is done with a slightly different syntax than standard input tags. Rather than using brackets, attachments are specified by parameters in URLs for actions which support them. Here’s a list of photo attachment parameters and their functions:

  • ?attach=photo brings up a menu of options for where to get the photo. This allows you to choose where to get your photo each time. The more specific attachment types below are shortcuts to the options which will pop up on this list each time, as well as a few which can only be accessed by explicitly defining them and will not present on the list.
  • ?attach=photo:last attaches the last photo on your camera roll.
  • ?attach=photo:camera brings up a camera for you to take a new photo.
  • ?attach=photo:frontcamera same as camera except this defaults to the front facing camera. Perfect for quickly snapping selfies.
  • ?attach=photo:library brings up the photo picker for your entire library.
  • ?attach=photo:cameraroll brings up the photo picker with your camera roll already open.
  • ?attach=photo:dropbox allows you to pick a photo from Dropbox.
  • ?attach=photo:clipboard uses the photo on your clipboard.
  • ?attach=photo:gif brings up the Giphy browser in the trending GIFs section.
  • ?attach=photo:gif&gif-search=search-term brings up the Giphy browser with a predefined search of whatever you put in place of “search-term”.
  • ?attach=photo:gif&gif-id=ZHbgdNcM9Tv4Q automatically downloads and attaches the GIF with whatever ID you place in the ID parameter.

Here’s an action to attach the last photo added to your camera role to an email:


And an action to attach a GIF from Giphy’s trending section to a new message:


That will bring up the trending section, from which you can choose a GIF, and then automatically place that GIF inside of a message. From there you can manually type the recipient and content of the message and send it.

Next, here’s a somewhat more interesting action which will allow you to search for a GIF and then send it via text message or email, or tweet a link to it:

[[list:Share GIF Via...|Message=launch://messaging?attach=photo:gif&gif-search=[prompt:Search for GIF]|Twitter=launch://?url={{launch://tweet?text=[gif:[prompt:Search For GIF]]}}|Email=launch://email?attach=photo:gif&gif-search=[prompt:Search for GIF]]]

Direct Import Link for Email Last Photo action

Direct Import Link for Message Trending GIF action

Direct Import Link for Share GIF action

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 show more descriptive titles.

With Launch Center Pro 2.3, Contrast introduced a new UI for building lists. As I mentioned before, when you tap the input tag button on the custom keyboard while making an LCP action, it has a third option, “List”. Choosing this option brings up a new window for building lists without manually typing them out. The UI has an input box for the list’s title and a section to type in any amount of list items, each with a title and output. When you’re finished, tap “Done”, and your list will be created automatically and inserted into the code wherever you had been typing. After you have pressed Done there is no way to recall the list builder window, so you should still be able to understand list syntax if you’re going to use them, but this definitely makes the original building of lists significantly easier.

Lists can be nested as well, just like prompts. We can use a list to make the New Meeting action a little simpler. The third nested prompt is for the day of the week, but since there are only seven days in a week, that makes a perfect time to use a list of options and avoid having to type out the day manually. Nesting a list is as easy as nesting a prompt, you just place the list inside the brackets of the parent prompt, where you want the text to appear. Here’s the action using a list:

fantastical2://x-callback-url/parse?sentence=[prompt:Review=Meeting[prompt:Attendees= With ] at [prompt-NumbersAndPunctuation:Time] on [list:Day|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Undefined Day=] ]&add=1&x-success={{launch:}}

I added an eighth option for “Undefined Day” as well, so that you don’t have to cancel the whole action if you don’t want to define a day in your sentence (for instance, if the meeting is later in the same day that you are creating the event). Run the action and you will now be presented with a list of options for your third variable, and whichever option you choose will show up in the final parent prompt for you to review before parsing.

Direct Import Link for New Meeting action

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. Previously these advanced actions required a lot of percent-encoding and a strong grasp on how Launch Center Pro handled URL actions, but new changes in Launch Center Pro 2.3 (which we’ll get to in more detail momentarily) have rendered that knowledge less integral to building most actions.

That said, I still think it’s important to understand everything 2.3 is doing behind the scenes, as it will help you grasp where you need to place your curly bracket encoders and how many you need to use, as well as making it easier to debug an action if you have an error with your encoders. Furthermore, no other app besides Launch Center Pro has implemented such far reaching techniques to simplify the writing of URL actions, so if you’re trying to build a complex URL action in Drafts, Editorial or another app, or dealing with any pre-2.3 LCP actions, you will still need to know the details of encoding.


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 same “://” 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 curly 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 characters “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 any more complex examples than the easy double encoded one above 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, in the next section we’ll be playing with double and triple encoded actions, and while they don’t look nearly as bad as they used to before LCP 2.3, if you don’t have a full grasp of their encoding needs then understanding all of the brackets and debugging actions will be very difficult.

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] and {{double curly bracket encoders}}. We’ll refer to both 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, [TextExpander] snippets, or [clipboard] variables. Finally, any text that you wrap in double curly brackets will be percent-encoded a single time for each set of brackets it is surrounded by.

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.

With Launch Center Pro 2.3 and 2.3.1, Contrast made some major changes to the LCP URL handler. Previously, the first thing LCP would do when you ran an action was to validate that the URL could actually be run by the system. It did this by looking at the “domain” of your action and making sure that your device had the app which the domain applied to installed. Failing that step would cause your action to get an error before it even started.

As of 2.3, LCP no longer requires URLs to be validated before it parses them for identifiers. I’m not certain if this step was completely removed or just pushed somewhere back in the order of operations. Regardless, it doesn’t particularly matter because if you run an action for an uninstalled app it’s not going to work anyway whether LCP stops the action first or not. The most important note about this change is that we can now begin our URL actions with special identifiers without needing to use the old launch://?url= hack. Action menus (list variables in which each option expands to an entire action instead of just a word) can begin immediately with [list..., removing an entire level of unnecessary and confusing encoding and making these menus much easier to build.

Since validation is no longer necessary, LCP now parses your action for special identifiers immediately after you launch it. However, this step has been altered from its old version as well. Pre-2.3, LCP parsed the URL chronologically, resolving each individual special identifier as it went. If any identifiers were nested inside of the identifier that it found first, it would often result in errors or completely ignoring the nested identifiers. Post-2.3, the URL handler now searches for the nested identifiers first, then expands out to the parents. This new method has huge implications for advanced actions. Since Launch Center Pro can look inside of identifiers before trying to resolve them, we can now use nested prompts and lists or nested curly bracket encoders without needing to jump through the insanely complex hoops that we used pre-2.3. Building URL actions is now completely intuitive: if you want to double encode something just wrap it in two sets of encoders. If you want to have a prompt come up after choosing an option in a list, just place a [prompt] inside of a [list]. Lists in lists or prompts in prompts? It’s all possible, and extremely easy, after Launch Center Pro 2.3.

With the new URL handler, Contrast wants to make the lives of action builders easier by reducing the amount of work we need to do to get advanced actions working. To do this they’ve built a basic level of intelligence into the way the handler parses URL actions. Now LCP looks at the whole action before resolving variables in order to determine which ones actually need to be resolved and which don’t.

For instance, as I stated above, LCP usually parses any nested variables before the parent variables. However, there are exceptions to this rule depending on what your action looks like and which type of variable you are dealing with. If you nest a prompt inside of a list option, you probably don’t want that prompt to pop up before the list does in case you pick a different option which doesn’t call the prompt. LCP knows this, so in this situation it will resolve the parent variable, the list, and then only resolve the nested prompt if you pick the list option which contains it. LCP 2.3 and 2.3.1 are filled with various special cases like this in which the handler tries to intelligently guess what we want, and in my testing Contrast has done a fantastic job with this implementation.

That said, the handler can’t always guess what we’re thinking, particularly when we’re dealing with higher level actions and trying to push the app to its limits. Thankfully, with 2.3.1, Contrast has provided us with a variety of “special operators” which we can use as tools to manually override any incorrect guesses the URL handler might make when parsing our actions. These single character operators are placed directly after the first hard bracket beginning a variable in LCP, and can be used on any type of variable. Before we get into the particular uses of these manual overrides, we need to go a little more in depth with how the URL handler treats input variables in LCP 2.3.1.

First off, with 2.3.1, there is no longer a need to explicitly define whether or not to encode a variable. In previous versions we would surround variables with either one or two sets of hard brackets. A [[double hard bracketed]] variable would leave the contents unencoded after being resolved while a [single hard bracketed] variable would encode the contents after resolving. Now all variables are encoded based on their context within the URL, so single and double hard bracketed variables are treated exactly the same. Furthermore, variables are no longer affected by curly bracket encoders. Use encoders to make sure that any plain text is encoded to the proper level, but any encoding of input variables should happen automatically, or if it fails for some reason then we will fix it with the new special operators instead of with curly bracket encoders.

The basic gist of the way LCP decides how to encode input variables is that if a URL action begins with a variable, or if the variable lies somewhere within the action’s path instead of in a parameter value, then the result will not be encoded. A parameter value is generally anything after an equal sign, the custom data which you are sending via your URL.

For example, take a basic Drafts URL action: drafts://x-callback-url/create?text=Hello%20World&action=Copy%20to%20Clipboard. This action includes two parameters, text and action. In the action the values for those parameters are Hello%20World for the text parameter and Copy%20to%20Clipboard for the action parameter. As in any URL action, these parameter values need to be encoded while the rest of the action should not be encoded. Every piece of the action besides the encoded parameter values is part of the action’s “path”. Just like a standard folder path or a website URL path, a URL action path tells the app in question where you want to navigate within its URL scheme, and the parameter values will be used by the app to complete whatever task you are calling within it.

A lot of advanced Launch Center Pro actions dynamically manipulate the path of a URL instead of simply filling in parameters. Action menus fill in entire URL action paths and launch them, while other types of actions may allow users to switch between different actions within the same app by mixing and matching smaller pieces of the action path. In almost all of the cases where you are manipulating the action itself instead of only its parameters, you don’t want to encode the results of your variables because that will break your action. As such, LCP 2.3 and higher checks the context of your input variables and determines whether they are in the path or in a parameter. If a variable is found to be in the path, it is left unencoded. If it is found to be in a parameter, it is encoded. This method works in almost every situation, but as with almost anything related to URL schemes, there are special edge cases which will break that rule.

A notable example is the 1Password URL scheme. For some reason the developers chose to make the 1Password search terms a part of each 1Password URL action’s path instead of setting them as parameters. A 1Password URL action to search for Twitter logins would look like this: onepassword://search/Twitter. There are no parameters: 1Password just puts your search term inside of the path. As such, if the rules stopped at path versus parameter, and you searched for a term which had a URL unsafe character in it via an LCP prompt, the prompt would not be encoded and your action would break. Thankfully, Contrast found a clever way around edge cases like these: if a variable is located within a path then when you send the text to resolve the variable to, LCP will first check that text for any URL unsafe characters (such as a space). If any are found, the text will be encoded before the action is run. This solves the problem presented by URL schemes like 1Password’s in almost every situation. If you’re finding that you have an edge case which breaks these rules, you can manually override the functionality with the special operators mentioned before in order to make it work. Unfortunately (or maybe fortunately) I can’t show any examples of that because not one of my actions, even the most complicated ones, have managed to break the rules and cause an error.

There are also new rules related to x-success variables for chained actions. These are pretty basic: if you have an unencoded variable which is located within an x-success action, it will not be resolved until that x-success action is being run. So when the URL handler makes its first pass of a chained action, it is only looking to resolve variables in the first action and ignoring anything in the chained second action. This prevents annoying problems we used to face in which every input variable from both chained actions would need to be resolved before anything was actually run. In the first version of this guide I used an example of an action which let you first type an in-app text message and then chain back and type the subject and body for an in-app email. The problem with the basic version of the action was that it would give you all three prompt boxes first, then go back and run the action. Thus you would type the message, then type the email, then send the message, then send the email. This order was disruptive and annoying because it forced you to keep switching back and forth between the message and the email. Pre-2.3, we had to jump through a long and complicated series of hoops in order to properly time delay those prompts so they came up in the correct order. Post-2.3 that order happens automatically. With zero additional coding, the prompts are prompted in the proper order: first you type the message prompt, then you send the message, then you type the email prompts, then you send the email. The code for this action looks just like you would expect:

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

Before LCP 2.3, to get that action with that order, we had to write this code:

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}}

Another benefit to this new x-success rule is that you don’t need to worry about encoding prompts multiple times when chaining more than two actions. All of the prompts which are deeper down the chain will be ignored until the action in which they reside is up to bat to be run, then they will be resolved at a time when they only need to be encoded once, and LCP handles that automatically. One less thing for us to think about when building complex actions.

Altogether, these new rules have successfully solved nearly every potential problem I’ve thrown at LCP 2.3.1. In general you won’t even need to worry about them, because their purpose is to work in the background and make your actions just work without extra effort. Sometimes there will be issues though, and that’s why Contrast has added in manual overrides. Here’s a list of all the special operators and what they do (“input” is substituted for the type of input variable, such as “prompt” or “list”):

[+input] increases the auto-calculated encoding level by one for each “+” placed in front of the variable type. The word “auto-calculated” is important here. Putting a “+” operator in your variable does not mean that it will be encoded only once. Rather, it means it will be encoded one more time than LCP was going to automatically encode it. If LCP was not planning to encode it, then the plus would cause it to be encoded once. If it was planning to encode it, a plus would result in encoding the result twice. For example, if you were to run this action: launch://clipboard?text=[+prompt] and then type in “This is a test” when the prompt box appears, the result would encode the text an extra time and copy “This%20is%20a%20test” to your clipboard. If you did the same thing, but used two pluses ([++prompt]), the result would copy “This%2520is%2520a%2520test” to your clipboard.

[-input] decreases the auto-calculated encoding level by one for each “-” placed in front of the variable type. If you use this operator in a prompt which was not going to be encoded anyway, it will have no effect. Otherwise, you can use it to fix any issues with LCP over-encoding variables. I haven’t actually found any instance of that occurring, but keep this tool in mind if you do run into one.

[~input] overrides any automatic encoding, keeping the resolved variable unencoded. You can add any number of pluses after the “~” but before the variable type to manually set an exact level of encoding (e.g., [~++prompt] will double encode whatever you type into your prompt regardless of what context the variable is in).

[^input] will delay the resolution of the variable by one scan of the URL handler for each “^” placed in front of the variable type. One small possible use for this is to pass the literal identifier into an action instead of resolving it. For instance, running drafts://x-callback-url/create?text=[^clipboard] from LCP would create a new draft in Drafts which actually consists of the text “[clipboard]” instead of being filled in by the clipboard contents.

[!input] will force the resolution of the variable on the URL handler’s first pass. This works even when the variable is in a chained x-success action, so one use for it is to revert LCP to the old model of resolving variables. As an example, if for some reason you wanted to take the messaging and email action from above and revert it to the old functionality (where you fill in all of the input prompts before sending the message or the email) you can do that simply by adding exclamation mark operators into the variables in the second action, like so:

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

That action will prompt you first for the “Message Body”, then for the “Email Subject”, then for the “Email Body”. Only after you have filled all of those in will the in-app messaging window pop up with the text from your first prompt. Once sent, the in-app email window will pop up with the subject and body filled in with your second and third prompts, respectively. In this case that change is largely useless, and probably even detrimental to the action, but there may be a different action in which you want to force all of the prompts to pop up first before anything else actually happens. If you do build an action like that, keep in mind that the exclamation point operator can make it work the way you want it to.

Another display of the new URL handler’s enhanced abilities: when you place prompts inside of list options, you no longer have to encode them like you did with the old version of LCP. You can leave them unencoded and the handler will know to only resolve the ones located in the list option you end up picking. In the case of the Tweetbot search action we built earlier, 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 Search Term=[prompt:Search Term]]

Note that since you no longer need to encode any input variables to make them work in lists, you also don’t need to encode anything else in the list options. In previous version of LCP, if we added in a prompt it often required us to wrap all of the list options in curly brackets or manually encode them. In the new versions you have to be careful, because wrapping list options in curly brackets will now actually break the list. With all of the new changes, Contrast has done a fantastic job at maintaining backwards compatibility with old actions, but this is one place in which they were unable to do so. As such, if any of your old list actions are suddenly not working in the new versions of LCP, just remove the curly brackets and make sure your variables aren’t manually encoded and your problem should be taken care of.

Another old problem that the changes to the URL handler have solved is overzealous clipboard resolution. Before 2.3, if you chained an action in which the first action in the chain saved something to the clipboard, and the second action then called the clipboard (often referred to as a “clipboard hack”), the clipboard variable in the second action would be resolved before the first action was run. The result was that your second action would use whatever text was on your clipboard before you ran the action, which could literally be anything. Since the new versions of LCP changed the rules so that variables in chained actions are not resolved until the actions before them have been run, clipboard variables in situations like this will not resolve until after you have saved what you want to the clipboard. In the old version of this guide we used a clipboard hack in order to type text a single time into a prompt box and then use that same text to first send a message and then send an email. Here is the code that used to be required to make that action work:


With the changes to the URL handler, here is how that same action can be produced today:


Direct Import Link for Message Then Email action

As you can see, not only is the action shorter, but it’s also far more readable and easy to understand. This optimization of code for complex URL actions is a hallmark feature of Launch Center Pro 2.3 and 2.3.1. These improvements make many of our old methods for building advanced actions look rudimentary. Most notably, the old way of achieving recursive (looping) actions, which now no longer requires extremely complex clipboard hacks due to the powerful new [action] tag.

The [action:ID] Tag

As of Launch Center Pro 2.3, every action you add to your grid is assigned it’s own individual Action ID. The ID, as far as I can tell, is simply a chronological counter based on how many actions you have. If you have fifty actions and then add a new one, it’s action ID will be “51”. Don’t worry though, you don’t need to memorize how many actions you have and mentally keep counting every time you create another one; you can find the action ID for every action by tapping it in edit mode and scrolling to the very bottom of the options in the Action Editor.

Once you have an action’s ID, you can now call that action from any other action in your grid using the action ID tag. If you wanted to call your fiftieth action, just include [action:50] in whichever action you are calling it from. Action ID tags work just like any other variable in LCP. When the URL handler comes across one, it swaps it out for the entire contents of the action associated with that ID before it ever starts running the action your are using the tag in.

Conceptually, this is similar to how we call other actions in Drafts: Launch Center Pro just uses numerical IDs while Drafts requires you give each action a custom title to call from other actions. That said, there is a big difference to keep in mind from the Drafts implementation which you might be used to. In order to call an action in Drafts, you must always prefix the title of the action you are calling with the base Drafts URL action, something along the lines of drafts://x-callback-url/create?text=[[draft]]&action=. Only after that last equal sign can you put the title of the action you want to run, which itself likely starts with the same base URL. This implementation is fine, it works great, and I’ve never found it to have any notable downsides, but it is certainly a little bit repetitive. Launch Center Pro’s implementation does not require any prefixes, as long as the action is being launched from LCP.

There are a few main uses for the new action tags. The first one is to make your life easier when you use the same action chained across multiple other actions. For instance, I have quite a few actions which use the Fantastical to parse some sort of sentence as either an event or a reminder. All of these actions begin with fantastical2://x-callback-url/parse?sentence=[prompt:Sentence] and then go on to define more parameters individually, such as whether to add the new event immediately and whether to parse it as a reminder. Since all of these actions have common code to begin them, I can make an individual action which only has the code fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]. That action is then given an action ID, which for me happens to be 115. With that done, I can now replace any instances of fantastical2://x-callback-url/parse?sentence=[prompt:Sentence] with the much simpler [action:115]. The way LCP handles action variables means that I can easily add more code after that tag to increase the action’s functionality on an individual basis. [action:115]&add=1 will parse my prompt in Fantastical and add it automatically without me needing to press “add”. [action:115]&reminder=1 will parse the prompt as a reminder instead of an event. [action:115]&reminder=1&add=1&x-success={{launch://}} will parse my prompt as a reminder, automatically add it, and then trigger x-success to return me to Launch Center Pro.

You don’t have to append to your actions to make this useful. If you just want to chain an action to multiple other actions, that works the same way.

Let’s say I want to send an email and then parse an event in Fantastical (useful, for instance, if the email is to a coworker informing them of a meeting of some sort, as I could then immediately add that meeting as an event after I send the email). I could do it like so: launch://x-callback-url/email?subject=[prompt:Subject]&body=[prompt:Body]&x-success=[action:115]. I can treat [action:115] as the exact same thing as I would otherwise treat the text fantastical2://x-callback-url/parse?sentence=[prompt:Sentence] because as far as Launch Center Pro is concerned, those two strings mean exactly the same thing. The one slight difference is that, since the action tag version is a variable, LCP will encode it automatically. Thus, you don’t need to enclose it in curly brackets like you would if you used the text version. That said, if you chain that action but also add to it like we did before, the part that you add on does need to be enclosed in curly brackets. So it might look something like this: launch://x-callback-url/email?subject=[prompt:Subject]&body=[prompt:Body]&x-success=[action:115]{{&reminder=1&add=1}}. Just don’t forget that if you are putting an action ID tag in an x-success variable then you need to manually encode any part of the action which is added around the tag, because those pieces are not automatically encoded.

Using code snippets like we did with the Fantastical action above has one more notable advantage, as well as a notable disadvantage. The advantage is that if you ever need to change a piece of the code in those snippets, you can now do it a single time and see that change reflected across all of your actions which use it. For instance, if I had had this functionality and been using that Fantastical snippet when Fantastical 2 was released, I could have simply changed the single action with ID 115 to start with fantastical2:// instead of the depricated fantastical://. Instead I had to go through many different actions and individually add a “2” to each one. If I forgot to change one then when I ran the action it would fail because I had uninstalled Fantastical 1.

The notable disadvantage is that your actions can now become more confusing to read. If I use [action:115] in a different action and then come back to edit that action later, I may have forgotten what [action:115] actually is. There is no easy way to tell either, because that number only represents the order in which I created the action, not the group or grid position it is located in, so it could be anywhere. I personally solve this problem by keeping a group inside my grid which is specifically designated to storing code snippets which I reuse in different actions. Opening the group, every action inside it is titled with the action number followed by a simple description (e.g., 115: Fantastical Base) so that I can quickly remember what action ID is what. This mostly solves the problem for me, but I still think Contrast should improve this somehow. Perhaps allowing us to add a title to the action tags as a kind of metadata which doesn’t affect the code at all (e.g., [action:115=Fantastical Base Action], or even providing a chronological list of all our actions (sorted by their IDs) which we could find in settings.

Using [action:ID] for Recursion

By far the most powerful use of the new action ID tags are the new possibilities they create for recursive actions. A recursive action is one that calls itself in the x-success parameter, and thus can create an infinite loop until you cut it off by (generally) hitting cancel on a prompt. Before action ID tags the only way we could achieve recursion in Launch Center Pro was by using an overly complex clipboard hack which multiple levels of encoding. The whole process was a mess, but the end results were worth it. Now we can get those same results without the mess.

Recursion in Launch Center Pro 2.3 is incredibly simple. Just get the action ID of the action you want to loop, and use that ID in the action’s own code. One of the most useful actions I’ve made with recursion is a recursive Fantastical action which allows you to import an infinite number of events in a row right from Launch Center Pro prompt boxes. Using an action ID tag to build this (let’s assume the action’s own ID is “50”), the code would look like this:


The first action in the chain is a simple Fantastical action to parse a new event from a sentence you type into a prompt. The event is added automatically, and once that has successfully occurred, the second action is called: launch://?url=[action:50]. Remember that when this action is launched you are still in Fantastical. That means that the only tools you have are those of Fantastical’s URL handler, which in fact has no special tools except to simply run the URL action. To Fantastical, [action:50] means nothing, because that is a special identifier unique to Launch Center Pro. If we want our action to work, we need to be back inside of LCP so that it can swap our variable for an actual URL. The way we do this is by using a trick offered in the Launch Center Pro URL scheme.

launch://?url= is a simple URL which will make sure that you are in Launch Center Pro and then to run whatever action is placed in the url parameter. This trick used to be a huge necessity in a lot of complex actions, but with the improvements from LCP 2.3, just about the only remaining reason to use it is to get us back into Launch Center Pro in order to run an action with LCP specific variables.

Returning to our Fantastical action, we call launch://?url=[action:50] which jumps us out of Fantastical and into Launch Center Pro before running the URL [action:50]. Since we are now running it from within LCP, as we should be, it can be expanded to the contents of our fiftieth action, which in this case is fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://?url=}}[action:50]. So the original action is run again and the whole process starts over. This loop will continue until we hit “Cancel” on one of our prompt boxes.

Earlier we talked about “action menus”, a method of using LCP lists to have a single action which, when run, will bring up a list menu on which every item is a different action. These are powerful on their own, but we can make them even better for certain situations by building recursive action menus. I didn’t even include recursive action menus in the first version of this guide because, while possible, their code was so convoluted that I hardly knew where to begin to explain it. Thankfully, action ID tags have made recursive action menus much more accessible.

The basic idea of a recursive action menu is that once you have chosen and successfully run an action from the list, the action will chain and return to Launch Center Pro and recall the action menu itself. This allows you to continue picking different options instead of going with a single action and looping only that action again and again. My favorite recursive action menu is for Fantastical. It consists of five different actions: Parse Event and Recall Menu, Parse Reminder and Recall Menu, Parse Single Event, Parse Single Reminder, and Launch Fantastical. As always, there is also the sixth option of “Cancel” which will end the loop no matter what.

Within this action menu only two of the actions are actually recursive. This is one of the great things about recursive action menus: you can combine different actions so some can be recursive by recalling the whole menu, some can be recursive by recalling only themselves over and over again, and others can not be recursive at all. In my menu, if you run one of the first two actions then you will get a prompt and then be sent to Fantastical to parse it as either a reminder or an event. When that has successfully been completed, you are returned to Launch Center Pro and the whole menu is brought back up so you can choose to parse another reminder or event, switch to parsing events if you had been parsing a reminder (or vice versa), parse a single event or reminder more and then not recall the menu, or simply Launch Fantastical to take a look at your calendar.

Coding this menu is easy now. First, add the new action and get its action ID. Mine is 102, but yours will be different. Next tap the URL text box in the Action Editor to start typing your action. Choose the first option on the extended keyboard and pick “List” to bring up the new List Builder dialogue. Now give the list a title, I used “Fantastical Action Menu”. Below the title box is a section labeled “LIST ITEMS” with one box already present. Add as many as you are going to have actions, in this case five, and then start filling in the information for each. The Title for each list item will be the title for that action which you want to see pop up in your recursive action menu. The Value for each list item will be the code for each action. Our five actions will have the following titles and code:

  • Parse Event and Recall Menu: fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://?url=[action:102]}}
  • Parse Reminder and Recall Menu: fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&reminder=1&add=1&x-success={{launch://?url=[action:102]}}
  • Parse Single Event: fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://}}
  • Parse Single Reminder: fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&reminder=1&add=1&x-success={{launch://}}
  • Launch Fantastical: fantastical2://

Once you’ve typed them into the list builder, it will itself look something like this:

The one problem with the list builder is that it cannot be recalled after you have tapped “Done”. Thus, while building action menus in the list builder is the simplest method, it doesn’t allow you to copy and paste from other actions because that would require you to close the list builder. I hope Contrast will find a clever way to allow us to recall the list builder after initially pressing Done, but in the mean time I’ve found it’s pretty easy to get around by testing all the actions I want in my menu first, then pasting them into Drafts and swapping back and forth between Drafts and LCP to paste each action into the list builder. Alternatively, you could write the entire menu by hand, but either way the final product will look like this:

[list:Fantastical Action Menu|Parse Event and Recall Menu=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://?url=[action:102]}}|Parse Reminder and Recall Menu=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&reminder=1&add=1&x-success={{launch://?url=[action:102]}}|Parse Single Event=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://}}|Parse Single Reminder=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&reminder=1&add=1&x-success={{launch://}}|Launch Fantastical=fantastical2://]

Compare that to the code which was necessary to make this exact same menu function in pre-2.3 Launch Center Pro:


That comparison is the perfect embodiment of just how huge the improvements Contrast has made are.

The final piece of the puzzle for my Fantastical action menu is adding an lc-icon parameter onto the end of the code so that it uses Fantastical’s icon instead of Launch Center Pro’s. This is another small but useful feature added in LCP 2.3. Just add &lc-icon=AppName onto the end of any of your URL actions and the icon for that action will be changed to the icon of the app you specify. It finds apps based on their URL schemes, but you don’t need a ://. Thus, to use Fantastical’s icon for the action menu, add &lc-icon=fantastical2 onto the end of the code. The completed action looks like this:

[list:Fantastical Action Menu|Parse Event and Recall Menu=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://?url=[action:102]}}|Parse Reminder and Recall Menu=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&reminder=1&add=1&x-success={{launch://?url=[action:102]}}|Parse Single Event=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&add=1&x-success={{launch://}}|Parse Single Reminder=fantastical2://x-callback-url/parse?sentence=[prompt:Sentence]&reminder=1&add=1&x-success={{launch://}}|Launch Fantastical=fantastical2://]&lc-icon=fantastical2

Direct Import Link for Fantastical Action Menu action (Remember that if you want the recursion to work properly you need to change the action ID tags to match the ID given to your own instance of the action, which will be assigned when you import it.)

You can make an action menu with any series of actions by using the same methods. Any time you want the menu to be recalled upon completion of an action, just put the menu’s action ID into the x-success parameter. This works great in many situations, but what about for apps which do not support x-callback-url? Turns Out™ Contrast has found a way to enable chained actions in those cases as well: LC-Callbacks.


Launch Center Pro 2.3 brought a new concept for chaining actions together, the lc-callback parameter. LC-Callback is a bit of a hack, as it’s not the same sort of seamless automation which we’ve grown used to with x-callback-url chains. That said, it’s a fantastic workaround for apps which annoyingly do not support x-callback-url, and creates a world of new possibilities.

LC-Callback works by saving whatever action is placed in the lc-callback parameter of an action which launches another app. The next time you open the multitasking interface and return to Launch Center Pro, it will immediately run the LC-Callback action. If you were to run the action drafts://?lc-callback={{tweetbot://}} from Launch Center Pro, your device would launch Drafts and then stop. As far as your device knows, that’s the end of the action and nothing more is going to happen. However, when you ran that action, Launch Center Pro stripped the LC-Callback parameters and held them, so now if you open your multitasking menu from Drafts and choose to reopen Launch Center Pro, it will then immediately trigger your LC-Callback action. Since that action is tweetbot://, LCP will automatically launch you into Tweetbot. Since LC-Callback is handled completely within Launch Center Pro, no external support is necessary, meaning you can chain any two actions that exist and can be run on your device, as long as you return to Launch Center Pro between the actions.

LCP supports LC-Callback on its own actions as well. Obviously if you are adding an LC-Callback action onto a Launch Center Pro action you won’t need to return to the app since you’ll already be in it. Thus, when you do make an action like that, LC-Callback acts exactly the same as x-success would: as soon as the first action is complete, LCP will launch the LC-Callback one. This means that, if you wanted to, you could just use LC-Callback instead of x-callback-url on all of your Launch Center Pro actions and avoid having to add /x-callback-url into the code for all of them, but I would just stick with x-callback-url where possible simply because it’s a more mature standard, and more people understand it if you share your actions. One thing the new LC-Callback options do enable in LCP is the ability to chain actions which do not support x-callback-url.

In the first version of this guide I expressed annoyance at the fact that a few LCP system actions did not support x-callback-url for no particular reason. Most notably, the Tweet and Share Sheet actions. While Contrast still didn’t add x-callback-url support to those actions, you can now just put an LC-Callback parameter after them in order to chain other actions to them.

Here’s an LC-Callback action which will copy text from a prompt to your clipboard and then use the clipboard to first post that text to Twitter and then post it to Facebook.


You can chain LC-Callbacks together too, just like you can with x-callback-url actions. If you wanted to only use LC-Callback for the previous action, you could do so by tweaking the code to look like this:


You may notice that the first LC-Callback has an “&” before it while the second has a “?”. This is simply the way that parameters work for URL schemes: the first parameter in a URL action will have a question mark before it, but all other parameters following that one will begin with ampersand symbols. In the action above, the first action has a first parameter of text, so we use a question mark for that one. The LC-Callback is the second parameter in the first action, so we prefix lc-callback with an ampersand. In the chained action, clipboard is used as part of the action’s path instead of being set as a parameter. Thus, since lc-callback is that action’s first parameter, we prefix it with a question mark.

LC-Callbacks enable a world of action chains which have never been possible. You can use them to make a recursive OmniFocus action:


Direct Import Link for Add New Tasks in OmniFocus action

Or to search 1Password for your Glassboard account info, copy the password there, then activate the LC-Callback to automatically open the Glassboard login page in Safari:


Direct Import Link for Get GB Password & Open Site action

LC-Callbacks do not run until you manually switch back into Launch Center Pro. Most of the time it’s nicer to use x-callback-url when possible because it takes care of the chaining automatically, but sometimes you may want to actually spend some time in the other app before the next action in your chain is launched. LC-Callback allows you to control exactly when you launch the next action instead of that being controlled by the URL handler of whatever app you are chaining with.

Another thing to keep in mind with LC-Callbacks is that they eventually expire. Launch Center Pro can only hold the callback while the app is still in memory, and that puts it at them mercy of iOS, which automatically kills apps that have not been used in about 15 minutes. Thus, if whatever you are doing between launching the first action in your chain and returning to Launch Center Pro to activate the callback takes more than 15 minutes, nothing is going to happen when you return. Thankfully, most use cases will not require such a long gap between returning. However, there’s another danger lurking to deny your action chain it’s rightful callback: iOS 7’s still remaining bugs with multitasking. This doesn’t happen very often anymore, but every once in a while when I try to open the multitasking interface on my iPad, the system freezes up and crashes after a few seconds, causing a restart. That restart closes all of my apps, and thus flushes my waiting callback action from LCP’s memory. I rarely see crashes like this on my iPhone anymore, but I often see the system freeze for four or five seconds before finally managing to get that interface open, which is still extremely annoying even if it doesn’t actually break my callback.

Hopefully iOS 8 will take care of those problems, but for the meantime make sure to keep them in mind and be prepared for the possibility that your chained action may never come if you have an unfortunately timed crash.


Launch Center Pro 2.3 also added support for the popular automation service IFTTT. LCP is now an officially supported channel on IFTTT, allowing us to trigger IFTTT actions via Launch Center Pro URL actions, or to have another IFTTT channel be the trigger and Launch Center Pro the action. This creates another wide variety of options for Launch Center Pro power users.

Before we go any further, you should download the IFTTT app on your iOS devices. It’s free, and necessary for most of the recipes we’ll be putting together.

Using Launch Center Pro as the trigger for an IFTTT recipe requires you to add an action into your LCP grid using the new LCP URL scheme for IFTTT. This scheme will look something like this:

launch://ifttt/trigger?name={{TITLE}}&value1={{VALUE 1}}&value2={{VALUE 2}}

You can have any amount of value parameters, as many as you want or as few as zero, depending on what kind of action you want to trigger. Since this is an LCP URL action, you can of course use all the standard prompts, lists, and other input tags in place of any hard coded parameters to make your recipes more variable.

I haven’t come up with many useful recipes which use LCP as a trigger because most of those that would be useful can already be done in the app without using IFTTT (appending to Dropbox files, tweeting or posting to Facebook, sending emails to yourself, etc.). There are a few tasks which could already be done by jumping to Drafts and running an action from there (namely, appending to Evernote notes and adding reminders in the official Reminders app) which can now be sent to IFTTT to be handled so that you don’t need to leave LCP. For Evernote actions however, I find I still like using Drafts’ Evernote support more because the custom Evernote actions are more powerful and easier to edit and understand. As for Reminders, I don’t use the official Reminders app, but if you do then it’s quite easy to make an IFTTT recipe to handle adding new reminders to particular lists.

Before you can make that recipe, you need to log in or make an account on Launch Center Connect. You can do this by going to settings in Launch Center Pro, choosing the “Launch Center Connect” option, and then going through the steps to either create an account or connect using Twitter or Facebook. Launch Center Connect, not surprisingly, connects you to third party services that want to access LCP on your device externally. Currently IFTTT is the only service supported, and by logging into your Launch Center Connect account on all of your devices (and logging into it on IFTTT as well) you allow IFTTT to trigger notifications on your device from Launch Center Pro, as well as allowing Launch Center Pro to trigger actions on IFTTT.

Once you’ve logged into Launch Center Connect on your devices and on IFTTT, you can start making recipes. Add a new recipe in your IFTTT app which uses Launch Center Pro as a trigger (if you haven’t logged into Launch Center Connect yet when you try to add LCP as a trigger, it will prompt you to do so at that time and then you can continue). Name it whatever you want, but I named mine “Add Reminder” and if you choose something else you will need to change the code for the LCP action to match your name. For the action part of your recipe, select iOS Reminders, and use the only option: Add reminder to list. If you haven’t accessed Reminders from IFTTT before, it will prompt you to give the app access to your Reminders. Now tap Finish. At this point the IFTTT recipe is ready, but I tend to want to tweak it a bit from the default. Make sure that the switch at the top right of your screen (on iPad) is set to “Manage”. If it instead says “Browse”, tap it so that you see the manage interface, which should have a list of all of your IFTTT recipes on the right-hand side. On iPhone there will be a round icon in the top right corner which you can tap to slide the main window over and see all of your recipes. Your Reminders recipe should be the newest, and thus at the top of the list. Tap it and then choose edit in the ensuing window. This edit interface is where you will go to tweak your recipe and get it just how you like it. Here you can change the description of the Trigger Name for your action, but the important part is in the “Action” section. Here you will see two text boxes, “Reminder” and “List Name”. Reminder is populated by default with “Value1 via Launch Center”. The text in that box is what will appear in your Reminder when you run this recipe. Value1 will be replaced by the value parameter that you send in your LCP action. If you tap in that text box you can delete the “via Launch Center” so that that isn’t tacked onto the back of every reminder you make using LCP. Now if you only want to add reminders into your default list in the Reminders app, leave the “List Name” option blank. However, if you want to be able to choose from LCP which list to add to, you should type “{{Value2}}” into the List Name box. This doesn’t mean you will have to manually type the list name every time you run your LCP action, but simply gives you the control to pick what list your reminder is added to via your URL actions instead of IFTTT. If you still want to specify a particular list and never change it then you will just hard code the list name into your LCP action instead of using some sort of variable for it. Once you’ve fixed your Reminder and List Name values the way you want them, tap “Update”.

With your recipe prepped in IFTTT, you just need to build the trigger action. Jump back over to Launch Center Pro and add a new action somewhere in your grid. Open the Action Composer, go to System Actions, then to “IFTTT Trigger”. Choose “Trigger Recipe with Values”. This will open an interface where you can enter all the pertinent information to make your IFTTT action run the way it is supposed to. The first option, “Name” will be the name of your action in your grid, and can be anything. The second option however, “Trigger Name”, must be exactly the name that you gave to your trigger in IFTTT. As I stated earlier, mine is “Add Reminder”. The next five options are all value parameters. There are five, but our action only had two. Fill in Value 1 with [prompt:Reminder] so that LCP will give you a prompt box for you to type in your reminder each time. For Value 2, input the title of the list you want this action to add reminders to. With that finished, tap Done, and you should end up with something like this:

launch://ifttt/trigger?name={{Add Reminder}}&value1=[prompt:Reminder]&value2={{Reminders}}

Running that action will tell LCP to trigger the IFTTT recipe titled “Add Reminder” and pass it whatever you type into your prompt box for the Value1 parameter and “Reminders” for the Value2 parameter. Assuming you followed all the steps correctly, IFTTT will then launch the Add Reminder action and add the text from your prompt box as a reminder in the list “Reminders”. The new reminder should show up in your official Reminders app shortly.

You can find the Add Reminder IFTTT recipe here, and here’s the Direct Import Link for the Add Reminder LCP action (which will trigger the IFTTT recipe once you’ve installed it).

Another IFTTT action I like is one to update my Twitter bio from LCP. Not something I use regularly, but every once in a while it will come in handy. This recipe uses LCP as the Trigger (with my chosen title of “Update Twitter Bio”) and Twitter as the action. It has a single value parameter which is the text for the bio. The resulting code for the LCP action:

launch://ifttt/trigger?name={{Update Twitter Bio}}&value1=[prompt-return:Bio]

Get the Update Twitter Bio IFTTT Recipe here, and here’s the Direct Import Link for the Update Twitter Bio LCP action.

LCP can be used as an action in IFTTT as well as a trigger. There are two options for using it as an action: sending an iOS notification or sending a custom URL action. The URL action comes in the form of a notification sent to your iOS devices as well, but swiping/tapping this notification will actually launch a custom URL action chosen by you.

Recipes where LCP is the action instead of the trigger do not require any URL action to be in your grid, you just need to have your device hooked up to Launch Center Connect. In IFTTT, you pick the trigger for your recipe, then add LCP as the action and select the option to send a URL action rather than a standard notification. Oddly, you can’t actually type the URL until after you have finished creating the recipe. Then you have to go back to your list of recipes and choose to edit the new one. Now in the Action section will be a few options: Which Device, Custom URL, and Sound. Which device allows you to pick the devices on which the notification will go off. You can choose all devices or a specific one. Remember that your devices will only show up if they are logged into Launch Center Connect. If you’ve already logged in and the devices still aren’t there, try logging out and back in on each device and it should solve the issue.

The Custom URL section is where you actually place your URL. IFTTT generally has prepopulated the text box with a bunch of weird defaults that will not actually result in any sort of action running, so delete everything they have in there and type your action as you would in Launch Center Pro. You can even use LCP variable tags because every action will divert you to LCP before launching (since LCP is the app the notification is coming from). IFTTT provides some variables that you can use as well, which will draw data from the trigger you chose, so you can make use of those in your actions too if need be.

There are a variety of triggers supported by IFTTT, but I have yet to find any groundbreaking workflows based on the service. I think the biggest advantage brought to the table by IFTTT/LCP integration is the ability to call actions in native apps based on events occurring outside of your device. Most times these situations are taken care of by push notifications. For instance, when you get a like on a photo on Instagram, you get a notification, and tapping that notification takes you directly to that photo in your native Instagram app. Push notifications are generally limited to only a few particular events though, and IFTTT can help extend those limitations if the event you’re looking for is supported as an IFTTT trigger.

For instance, IFTTT has support for Instagram as a trigger, but this can be triggered for more events than just one of your photos being liked or you being tagged in someone else’s. If you have a child, significant other, or just a friend who takes great pictures all the time and whose posts you want to see right away, you can set up an IFTTT recipe to trigger each time a certain user posts to the photo service at all. The notification which then pops up on your iPhone (I disable it for iPad in this case since there is somehow still no Instagram app for the iPad) can be swiped to launch you directly into Instagram where their post should be waiting at the top of your feed. For my recipe I use the simple instagram:// for the URL action, but you can set yours up to launch directly into your person’s profile too if you prefer that approach.

You can find that recipe here, and it requires no LCP companion action.

Mac OS X has a feature which allows websites to send native notifications each time they post a new article. Tapping the notification will automatically open the article in Safari. It may be possible to get this functionality in certain iOS RSS reader apps, but I’ve never gotten into using RSS readers, I prefer reading articles in their native interfaces through Safari or another web browser. I was able to create an IFTTT recipe which hooks into RSS feeds in order to mimic the OS X notification behavior on iOS. Each time the website I’ve set the trigger up with adds a new item to its RSS feed, LCP notifies me on my iOS devices and with one swipe the new post is opened in Safari for me to read. The custom URL for this action is simply the URL from the post on the feed because http:// (and https://) is registered as the Safari URL scheme on iOS.

Here is a version of that recipe which will give you a push notification each time there’s a new post on MacStories. Following the notification will launch the article in Safari.

IFTTT has some other interesting integrations as well. You can use adding a reminder to a particular list from any of your devices act as a trigger, as well as taking a photo, saving a new contact, or entering a particular location. The location based triggers are fairly pointless since LCP can handle location based actions natively, and I haven’t yet thought of any particularly good use cases for the other native iOS triggers, but perhaps you will be able to for your own workflows.

I tried using the Reminders integration to get a Siri hack working. For example, you ask Siri to “add Twitter to 1Password list” which places the word “Twitter” in your Reminders list titled “1Password”. That would then trigger IFTTT to send a notification to launch the action onepassword://search/Twitter from LCP. Although the phrasing for things would be weird and you would need a different list for every type of action, the idea was that it would at least allow some way to launch actions for third party apps from Siri. The process did actually work exactly as I had hoped, but the problem was that IFTTT triggers from new Reminders are incredibly slow. Sometimes the notification wouldn’t actually come for a few minutes or more, which pretty much ruined the point.

Even though my experiment with Siri failed, hopefully you can start to see the possible implications of IFTTT triggers for LCP actions. Most are quicker than the native Reminders notifications, plus most workflows won’t require such immediate feedback anyway. I encourage you to scan through all of the services which offer support for IFTTT and look for any which you use. You might have no idea that a service you use constantly has an IFTTT channel, and one of its triggers may well be a great fit for you to pair with an LCP action.

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. While LCP 2.3 made that approach possible with action ID tags, it also made the process of just chaining them together manually far easier, and building bigger chains in that manner also creates much more shareable actions.

With 2.3’s encoding improvements, no matter how large your chain may be you should very rarely, if ever, need to manually encode any of it. You do need to correctly manage your encoding helpers though. While that is really just a matter of counting and knowing what needs to be encoded and by how many levels, managing multitudes of brackets has always been a problem in writing code, and you need to be careful not to mess it up or you will break your action. That said, figuring out how many brackets you need and where you need them is an order of magnitude simpler than searching for a bug in code which has been encoded three or more times.

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. 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:

  • launch://x-callback-url/dropbox/addphoto?attach=lastphoto&path={{/Photos}}&getlink=1&x-success=
  • launch://x-callback-url/messaging?body=[prompt-return:Body]%0A[clipboard]&x-success
  • 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. Thankfully we can now do all of this with curly bracket encoders instead of manual encoding. Any text wrapped in multiple pairs of encoders will be encoded multiple times, so we can easily get the proper level of encoding by adding one pair of open curly brackets after every &x-success=, and placing a pair of closing curly brackets at the very end of the code for each pair of opening ones. Thus, the final result (before removing those newlines) will look like this:

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

The first set of encoders will encode the entirety of the last two actions one time. The second set of encoders will encode only the last action one time. Since the first set also encompasses the last action, the end result will leave it encoded two times, as it needs to be. Now that all of the encoders are positioned properly, we can get rid of the newlines and see our final action:


For one more reminder of just how much these encoding helpers are doing, here’s what that same action looked like before LCP 2.3:


Even though building chains is so much simpler post-2.3, laying out your actions before encoding each line makes the process of building bigger chains a lot easier.

Here’s the Direct Import link for the action, which will upload the last photo on your Camera Roll to Dropbox and then present you with prompt boxes to fill in and send first a message and then an email with the link.

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 show even 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, Pythonista, and Editorial

Drafts, Pythonista, and Editorial 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.

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, and any action which uses Evernote.

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, and Editorial workflows with the Editorial 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 or workflows you build for them from your Launch Center Pro action grid. You can utilize the LCP input prompts to send any necessary text to Editorial or Pythonista as well.

Using Drafts, Pythonista, or Editorial alongside Launch Center Pro lets you utilize the best aspects of all four iOS automation titans. Launch Center Pro has unarguably the best UI for launching actions, but the other three 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 iPad (sold separately).

  1. The old Fleksy keyboard option was removed in LCP 2.3 due to changes in the Fleksy SDK. If you really enjoyed that option, I wouldn’t worry too much. When iOS 8 comes out later this year you’ll be able to make Fleksy your system keyboard and use it anywhere. ↩︎
  2. To enable this functionality, you first have to connect your Dropbox account with Launch Center Pro in settings. ↩︎
  3. 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. ↩︎
  4. Tweet and Facebook actions only support attaching photos, not GIFs. However, in Twitter’s case, direct links to GIFs will actually give the exact same functionality as attaching photos, allowing your GIF to appear inline and be viewable without opening a browser in most major Twitter clients. ↩︎

Unlock More with Club MacStories

Founded in 2015, Club MacStories has delivered exclusive content every week for over six years.

In that time, members have enjoyed nearly 400 weekly and monthly newsletters packed with more of your favorite MacStories writing as well as Club-only podcasts, eBooks, discounts on apps, icons, and services. Join today, and you’ll get everything new that we publish every week, plus access to our entire archive of back issues and downloadable perks.

The Club expanded in 2021 with Club MacStories+ and Club Premier. Club MacStories+ members enjoy even more exclusive stories, a vibrant Discord community, a rotating roster of app discounts, and more. And, with Club Premier, you get everything we offer at every Club level plus an extended, ad-free version of our podcast AppStories that is delivered early each week in high-bitrate audio.

Choose the Club plan that’s right for you:

  • Club MacStories: Weekly and monthly newsletters via email and the web that are brimming with app collections, tips, automation workflows, longform writing, a Club-only podcast, periodic giveaways, and more;
  • Club MacStories+: Everything that Club MacStories offers, plus exclusive content like Federico’s Automation Academy and John’s Macintosh Desktop Experience, a powerful web app for searching and exploring over 6 years of content and creating custom RSS feeds of Club content, an active Discord community, and a rotating collection of discounts, and more;
  • Club Premier: Everything in from our other plans and AppStories+, an extended version of our flagship podcast that’s delivered early, ad-free, and in high-bitrate audio.