How to create simple Mac apps from shell scripts
Basically, a Mac application has a .app extension, but it’s not really a file — it’s a package. You can view the application’s contents by navigating to it in the Finder, right-clicking it and then choosing “Show Package Contents”.

The internal folder structure may vary between apps, but you can be sure that every Mac app will have a Contents folder with a MacOS subfolder in it. Inside the MacOS directory, there’s an extension-less file with the exact same name as the app itself. This file can be anything really, but in its simplest form it’s a shell script. As it turns out, this folder/file structure is all it takes to create a functional app!
Enter appify
After this discovery, Thomas Aylott came up with a clever “appify” script that allows you to easily create Mac apps from shell scripts. The code looks like this:
#!/bin/bash
APPNAME=${2:-$(basename "$1" ".sh")}
DIR="$APPNAME.app/Contents/MacOS"
if [ -a "$APPNAME.app" ]; then
echo "$PWD/$APPNAME.app already exists :("
exit 1
fi
mkdir -p "$DIR"
cp "$1" "$DIR/$APPNAME"
chmod +x "$DIR/$APPNAME"
echo "$PWD/$APPNAME.app"
Installing and using appify is pretty straightforward if you’re used to working with UNIX. (I’m not, so I had to figure this out.) Here’s how to install it:
- Save the script to a directory in your
PATHand name itappify(no extension). I chose to put it in/usr/local/bin, which requires root privileges. - Fire up Terminal.app and enter
sudo chmod +x /usr/local/bin/appifyto make appify executable without root privileges.
After that, you can create apps based on any shell script simply by launching Terminal.app and entering something like this:
$ appify your-shell-script.sh "Your App Name"
Obviously, this would create a stand-alone application named Your App Name.app that executes the your-shell-script.sh script.
After that, you can very easily add a custom icon to the app if you want to.
Adding a custom app icon
- Create an
.icnsfile or a 512×512 PNG image with the icon you want, and copy it to the clipboard (⌘ + C). (Alternatively, copy it from an existing app as described in steps 2 and 3.) - Right-click the
.appfile of which you want to change the icon and select “Get Info” (or select the file and press ⌘ + I). - Select the app icon in the top left corner by clicking it once. It will get a subtle blue outline if you did it right.
- Now hit ⌘ + V (paste) to overwrite the default icon with the new one.
Note that this will work for any file or folder, not just .app files.
Examples
Chrome/Chromium bootstrappers
I like to run Chrome/Chromium with some command-line switches or flags enabled. On Windows, you can create a shortcut and set the parameters you want in its properties; on a Mac, you’ll need to launch it from the command line every time. Well, not anymore :)
#!
/Applications/Chromium.app/Contents/MacOS/Chromium --enable-benchmarking --enable-extension-timeline-api&
The & at the end is not a typo; it is there to make sure Chromium is launched in a separate thread. Without the &, Chromium would exit as soon as you quit Terminal.app.
Launch a local web server from a directory
Say you’re working on a project and you want to debug it from a web server. The following shell script will use Python to launch a local web server from a specific directory and open the index page in your default browser of choice. After appifying it, you won’t even need to open the terminal for it anymore.
#!
cd ~/Projects/Foo/
python -m SimpleHTTPServer 8080 &> /dev/null &
open http://localhost:8080/
More?
Needless to say, the possibilities are endless. Just to give another example, you could very easily create an app that minifies all JavaScript and CSS files in a specific folder. Got any nice ideas? Let me know by leaving a comment!
Comments
Thomas Aylott wrote on :
Nice examples.
I’d love to see what else people can come up with. What’d be slick is a droplet that lets you drag a folder into the app to serve that path. Maybe use AppleScript via
osascriptto give it a simple UI or something.Fun Times™
Mathias wrote on :
Someone just pointed me to DropScript, which pretty much does the same thing appify does, except it’s an actual OS X application.
John Lannon wrote on :
Not sure if it's actively maintained, but Platypus accomplishes is another similar utility. Like DropScript, it's an actual OS X app.
Thomas Aylott wrote on :
Platypus actually does something different. It sets the executable to some sort of binary and the includes the script as a resource. It's much slower to load than just a script file in 3 folders.
richtaur wrote on :
Sweet, I might see if I can make some games with this :D
Mathias wrote on :
If you’ve been looking for an easy, automated way to update to the latest Chromium nightly build, look no more!
I just found this script, saved it as
chromium-updater.sh, then entered the following command:Et voilà! Now, all it takes for me to update Chromium is a single click.
Of course, this app won’t be able to give any real visual feedback as to what it’s doing, but if it exits almost immediately it means you already have the latest version installed. If it takes more than a few seconds, you probably don’t and the app is downloading the latest version for ya. (That, or you have a very slow connection, or chromium.org is down.)
If you’re too lazy to build it yourself, you can just download the Chromium Updater app here, complete with a nice icon and everything.
Kevin Grant wrote on :
There is a simpler way to make scripts openable in the Finder, which is to give them the
.commandextension (.toolalso works, I think). This automatically makes them open in a terminal window, which is both more and less convenient, depending on whether or not the script fails. :)Manuel Villegas wrote on :
Hi, I was pretty seduced by the idea of making Apps out of X11 applications like
xdvi, then associating them with.dvifiles in Finder. But I somehow can not make it work. My simple write is:…which works when typed in Terminal, but once the app is created, it does nothing. Can somebody help me out? I also downloaded GIMP in the X11 frame, and I don’t get it to have it as a standalone app. I know, for this there is already a Mac Bundle. But for the other X11 applications?
Mathias wrote on :
Manuel: You may wanna try DropScript or Platypus, which are both suggestions from previous comments.
shardbearer wrote on :
I tried this, it opened, didn’t do anything, and immediately stopped responding. Eventually used Automator.
Mathias wrote on :
shardbearer: What was the script that you appified doing exactly? Share your code!
Hawk wrote on :
I tried this, installed it as instructed. But when I did
appify test.shit said “mkdir— permission denied”. So I did it withsudo, but it didn’t create a.apppackage. I tried again, but this time it said “test.appalready exists”… :( What’s going on? Can’t figure it out.brontosaurusrex wrote on :
Would an app like that take dropped files as arguments for embedded sh/bash script?
Would an app like that auto-launch Terminal to see what’s going on or not?
Ken wrote on :
This appears to be broken. Maybe it doesn’t work with OSX Lion?
In fact, it looks like none of these work anymore… Platypus, Dropscript, Appify… I think Lion broke them all. Even the
.commandtrick no longer works, all that does is open the Terminal without actually running the script.Mathias wrote on :
Thomas created an updated version of Appify that adds OS X 10.7 Lion support by also creating an
Info.plistfile: https://github.com/subtleGradient/tilde-bin/blob/master/appifyThere’s a UI for Appify, too: https://github.com/subtleGradient/Appify-UI
Romeo wrote on :
Since I use Vim for almost all my files, this kind of approach is quite nice. Is there a method that also assigns icons to the files? Different icons for different extensions would be great. I don’t like it when all the files have the generic white-sheet-of-paper icon.
Mathias wrote on :
Romeo: See the “Adding a custom app icon” section of the post. I don’t know of a way to automate this, though.
Eric Larour wrote on :
I’ve been trying the new Appify from Thomas to add Lion support. I’m running on Mac OS X 10.7.2.
My script is a simple:
When I appify it,
I get the following:
I get nothing from the
system.log. Sounds like Mac did something else in the newer versions that breaks the script.Any feedback welcome,
Eric L.
Hawk wrote on :
I can’t do this. I did
mkdir -p ~/Desktop/MyTest.app/Contents/MacOSand saved aMyTestbash script into that folder usingnano. Thenchmod +xon both the script and the.appdirectory. The icon is that “invalid app” icon and when I try to launch it, Finder tells me:And then, a split second later:
(No quotation marks, and “it is” instead of “it’s”.)
I’m using OS X 10.6.8.
Don wrote on :
I appreciate the ability to copy & paste a custom icon into the selected icon in the new application’s “Get Info” dialog box. But for deployment reasons, I would like to add a
.icnsicon to the package, and know that it’s there by seeing it in the application’s Resources folder and see an entry for it in the application’sContents/Info.plistfile. I’ve tried adding lines like:…after the last CFBundle statement in
Info.plistfile, whereiconfileis the name of the.icnsicon residing in the Resources folder that I created after theappify.bashrun, and into which I copied the.icnsicon file. Yet I just don’t seem to be able to make this icon show up in the folder-browser displaying the new application that the newest rev ofapplify.bashhad created. The app runs correctly, but the icon is wrong. I’ve tried copying the application to a new folder, and in this new folder, the displayed icon is still wrong in the folder browser. The icon itself seems to be in good shape; it has all lower-case letters in its name, and the reference for it inInfo.plistis thought to be correct. I’ve also tested specifying the filename with or without the icon’s.icnsextension.At this point, I’m out of ideas. I’m probably missing something obvious, but I don’t know what. How does one add a nice
.icnsicon to a package that the newest rev ofapplify.bashhas just created? Is there some place to look for error messages regarding problems in reading theInfo.plistfile?Thanks in advance for your help!
Daniel wrote on :
It appears that the script needs to end in
.commandto work in Lion. This removes the “You can’t open… type of Mac” errors.Anonymous wrote on :
After following this post, I was unable to run the .app after using the command
appify your-shell-script.sh "Your App Name"in Terminal, using:I receive a prompt saying it was damaged or incomplete.
Mathias wrote on :
Anonymous: See comment 15.
asdf wrote on :
How do you stop it from bouncing? I have a command that just starts an SSH tunnel and keeps it up. When I start it, it keeps bouncing for like 30 seconds, then when I Ctrl-click it says “Program not responding” and lets me “force quit”. I’d like to tell OS X that it has started up fine, and it can kill it in the normal way if it wants to.