How to deploy iOS apps to the iPhone via the command line

In a productive development environment it's usually a good idea to think about the automation of recurring processes like compiling, testing and deploying development code to test devices. For iOS apps this becomes a pain as soon as you develop outside Xcode:

That's why this article explains how to deploy your iOS applications to usb-connected iOS devices without using Xcode - directly from the command line.

Advance Notice: The approach described in this article will work on OSX only. I assume it requires heavy tinkering to make this work on a linux-based system and is most likely completely impossible on Windows.

Meet the transporter chief

In the course of our Starling-on-iOS endeavors we created a small Ruby script we call the Transporter Chief: The transporter chief helps us deploy our apps directly to the device in an automated way. For example, calling the transporter chief with the following line...

./transporter_chief.rb /path/to/my-app.ipa

...makes him deploy my-app.ipa to the first usb-connected iOS device. The chief supports both .ipa iPhone applications, which you get when you compile a Starling game with the AIR compiler, as well as .app application bundle directories. Nice, eh?

Before you get to download the chief, however, we need to check if your setup is ready for excessive beaming:

Prerequisites

The transporter chief requires you the have the following things available on your ship:

ruby

git command line tools (git pull, ...)

make

Ruby should be available on your machine already - at least it did come with our Snow Leopard and Lion machines. However, depending on your setup make and git may need to be installed to make this work. Fortunately it's a pretty easy task to do just that. First, we need to check if either one is missing: Call the following two statements in a terminal to see if they are available.

make --helpgit --help

If they respond with nice help messages we are ready to go to warp and you can skip the rest of the prerequisites, otherwise it's time to do some installing:

I recommend you use homebrew to install these kinds of things: It's super comfortable and does not mess with your setup as other repository installers for OSX might. To install homebrew, make and git paste the following to your terminal:

What just happened: The first line installs homebrew as recommended in the official homebrew installation guide. The second line installs git using the previously installed homebrew. Since installing homebrew and git requires make, that one is now installed too. Check again if make and git are installed.

Meet fruitstrap

To put the transporter chief to work we make use of Greg Hughes' fruitstrap library. Fruitstrap calls one of Apple's private APIs to deploy to the iPhone. This means that this API is subject to unannounced changes and may break at some time in the future: This is the time when transporter accidents may accumulate.

However, it seems as if Greg is updating his github repository quite regularly. If you run into any troubles while deploying your app you can command the transporter chief to update his version of fruitstrap by calling:

ruby transporter_chief.rb --update

He will then pull the latest fruitstrap version from github and compile/make it subsequently. If you furthermore append the path to your app to the above call the chief will deploy it using the new fruitstrap version.

Update (June 2013): Unfortunately, fruitstrap is no longer maintained. We're now using the fork iOS-Deploy which is maintained by the PhoneGap team.

Get the ship's logs

Finally, if you run into any other problems you can command the transporter chief to redirect the ship's logs to your console with:

ruby transporter_chief.rb --verbose

Don't blame the chief

Sometimes the chief will not be able to convince fruitstrap to deploy to your device. That's when you should pull the device's plug and reconnect it. This usually solves the problem.

We are using the chief on a daily basis and there have not been any other problems: You too can use the chief as you like, but please don't blame him if something went wrong with your setup. After all, he's just a script.

Update

The chief now supports an additional optional parameter that allows you to specify a device identifier as a deployment target. This helps with setups when more than one device is connected to your machine:

./transporter_chief.rb --device <device_identifier>

You'll find device identifiers in iTunes or the Xcode Organizer. If you are working with a single connected device only, you can safely ignore this option.