Xcode vs. Gatekeeper

Have you noticed how launching a new beta version of Xcode seems to take forever the first time you do it?

There’s a reason for that and its name is Gatekeeper. When you double-click on that shiny new icon, you’re asking your Mac to compute a checksum on tens of thousands of files using over 5 GB of space. That’s going to take awhile.

If you trust the source of the file, there’s no harm in removing the flag that causes Gatekeeper to perform this check:

$ cd /Applications
$ xattr -d com.apple.quarantine Xcode6-Beta7.app

Now, when you launch that new version it will open up immediately and won’t annoy you with the dialog asking if it’s OK. How many collective developer hours will this little trick save?

For more info on xattr, check this out.

Updated September 9th, 2014: As Greg Parker points out “trusting the source” means that you’re absolutely sure that both the DNS and network between you and Apple hasn’t been compromised. My personal opinion is that if those things happen, I have a much bigger problem than an Xcode download (e.g. someone can watch all my transactions with iTunes.) Your mileage may vary.

The Terminal

I’ve been using the Unix command line since 1983 and like most software developers, the Terminal app is a permanent fixture in my Dock. Over the years I’ve learned a lot of things that make working in this environment more productive, but even old dogs like me are constantly learning new tricks.

As much as I love them, these long “trick lists” on Stack Overflow have a problem: they’re poorly organized with little narrative describing why you’d want to use a technique. This long homage to the command line is my attempt to remedy that situation.

Note: I originally learned the shell using the newfangled csh (which was a huge improvement over the original sh.) When I first started using Mac OS X, I tweaked it to use tcsh because that’s what I knew and loved. Over time, I gave up using these tweaks and started using the default shell: bash. The following examples assume that you’re doing the same.

Editing Keys

My most recent discovery, and the one that made me realize a post like this would be helpful to a lot of fellow developers, was the revelation that an option-click in the Terminal window emulates arrow keys.

Say you’re entering the following in the command line:

$ echo "this is a test"

Oops! You left out “awesome” and now find yourself tapping the left arrow a bunch of times before entering the missing word. The pain increases linearly with the length of the command line you screwed up. If your Mac keyboard is anything like mine, the arrow keys are shiny from constant wear and tear.

Luckily, you can give those keys a bit of a rest with this simple trick: try Option-clicking on the first letter in “test”. The cursor is just where you want it and you haven’t touched the arrow keys!

To get a better idea about how this works, try this:

$ cat -v

Now, press the arrow keys. The terminal emulator sends an escape (^[) followed by an open bracket and then A for up, B for down, C for right, and D for left. Now hold down the Option key and click with the mouse: the Terminal app just emits arrow keys to move the cursor block between the source and destination locations. This means it also works in tools like vi or even the Xcode debugging panel: a huge time saver just got even better!

(Use Control-C to get out of this echo mode and back to your shell prompt.)

While we're on the Option key, you can also hold it down while using the left and right arrows to move the command line cursor by a full word instead of a character. Which is exactly what you need when your editing a path with a missing directory name.

The command line also responds to control keys. The ones I use the most are Control-A and Control-E to move to the beginning and end of the line. Control-U and Control-K are also useful to delete text from the cursor to the beginning and end of the line buffer. I've heard that these are standard emacs key bindings, but can't confirm this since I'm a vi LOVER NOT A LOSER

Note that the Control and Option keys also work in standard Cocoa controls. In a Finder window, you can use Command-Shift-G to change the folder path and then use same muscle memory that you've acquired in the shell.

For those really long commands, you'll probably want to get into a more comfortable editing environment. Just use Control-X followed by Control-E to open the command buffer in your EDITOR. (More about setting up the EDITOR in just a bit.)

Another great key to know about is Tab. Try entering this:

$ ls /Vol

Press Tab once and it completes "/Vol" to "/Volumes". Press Tab twice and you'll see a list of all mounted volumes. Welcome to the Lazy Typist Club™.

Shell Setup

As I mentioned earlier, I no longer configure which shell I use on a new OS X install. I do however, change the bash configuration on every Mac I touch.

Every time a new Terminal window is opened a shell process is created with your current login. As the shell is initialized, the .profile file in your home folder is used to initialize the interactive shell. Basically, you can think of .profile as a bunch of typing you don't have to do each time a new Terminal window is created.

(The name .profile dates back to the original sh. See "man bash" for a ton of more info and options.)

Here's my .profile. I like to keep it fairly simple:

alias ll="ls -lahL"
alias con="tail -40 -f /var/log/system.log"

bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

export EDITOR="vi"
export CLICOLOR=1
export XCODE="`xcode-select --print-path`"
export PATH="/Users/CHOCK/bin:$XCODE/Tools:$PATH\

Let's take a look at each group of settings.


Aliases let you define command shortcuts. Since I'm old and forgetful, there aren't many. I used to have a lot of aliases, but found myself constantly using the alias command to list them out and find the right one. Which, of course, defeats the entire purpose of a shortcut.

The alias ll lets me list files in a format that is more readable, especially with the large files. I like using con instead of firing up the Console app (which is total overkill for most situations.) It should be pretty obvious how to create your own aliases. A lot of the command tricks you'll learn below will be good candidates if you use them often enough.

Search Setup

By default, the shell allows you to use Control-R to search previous commands. After typing the control sequence, your command history is searched for each letter that you type. Cool idea, but in my opinion, it's a terrible user experience. The reason is that my history is filled with entries that are very similar. If you have both "ssh CHOCKMASTER@domain1“ and "ssh CHOCKMASTER@domain2“, there's just too much typing to get the right match.

The next two lines in my .profile solve this problem: the bind command tells the shell to do a history search when the up and down arrow keys are used. When the shell is in this mode, you can just type "ssh" and then use the arrows to select the command you want to run again. This fits my needs much better and feels more consistent with the shell's default ability to move through the history with the up and down arrow keys if you haven't entered any text into the edit buffer.

Environment Variables

Finally, there are the environment variables. Again, i've whittled it down to the bare essentials. The EDITOR variable is used by Control-X, Control-E in the shell and lots of other tools. You can change it to emacs, but then I'd laugh at you.

The CLICOLOR variable is used by the ls command to show files and folders with color coding. You can change the colors using the LSCOLORS environment variable, but the configuration string is just too damn arcane for me, so I skip it and go with the defaults. See the man page for ls to learn more about the color coding and the options.

Finally, there's the PATH environment variable. The items, separated by a colon, are directories in the file system that contain the commands I use. By default, these paths are "/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin".

I have a bunch of command line tools and scripts that I've accumulated over the years and they are all in the bin directory of my user folder. I also use MacPorts, so the /opt binaries get added to the end of my path.

Note: I've added a backslash to the end of the first line that contains the PATH definition. This is the "line continuation character" and can be used to break up lines that are too long for your editor, terminal or the narrow column of this web page :-)

If you use Xcode, you might find it handy to put the /Tools folder in your PATH. If you want command line access to the same versions of gcc, git, svn and other tools that Xcode uses, you can substitute /Tools with /usr/bin. Since I prefer to use MacPorts to get specific versions of the tools I use, I generally don't need access to Xcode's binaries. If I do, it's easy enough to do this:

$ $XCODE/usr/bin/gcc --version

Note that since the .profile is only read when the shell starts, the XCODE environment variable won't be correct if you run xcode-select after the shell is started. This is usually only a problem if you're juggling multiple versions of Xcode and can easily be solved by closing the Terminal window and opening another.

Shell Scripts

As I said before, I populate my ~/bin directory with a bunch of useful tools that I've developed over the years.

Two of my favorites scripts in that repository are psc and opensim.


The first script is an oldie but a goodie (note the shebangtcsh!). I named it psc:

set cmd = 'ps axo pid,ppid,user,command'
if ("$1" == "") then
  $cmd | grep "$1" | grep -v "grep $1" | grep -v "bin/psc"

It's a wrapper for ps that shows all of the process' command and can target it for a specific app. For example:

$ psc Xcode
15401   150 CHOCK  … Xcode -psn_0_26982842
15476 15401 CHOCK  … XcodeDeviceMonitor --bonjour _15401

Now you'll see all of the processes that have "Xcode" in the command. The process ids are also shown, so you can kill them, of course.

I also find that seeing the parent process id, which is shown in the second column, is important in these days where everything seems to be a child of launchd. It's also helpful for finding things like XPC processes and other items that get executed from an app's bundle.


If you're an iOS developer, the opensim script is very helpful for finding your app's sandbox folder in the Simulator. Here's the script:


if [ -z "$1" ]; then
  echo “usage: $0  [ Preferences |  ]”
  base=~/Library/Application\ Support/iPhone\ Simulator/
  app=`ls -1td “$base/”*”/$apps/”*”/$1.app” | head -1`
  if [ -n "$app" ]; then
    dir=`dirname “$app”`
    if [ "$2" = "Preferences" ]; then
      open “$dir/Library/Preferences”
      open “$dir/Documents/$2″

And here's how to use it.

Version Control

Most of the other stuff in my ~/bin directory are utilities that help with my own workflow (managing servers, testing, backups, etc.)

One of the reasons I prefer to keep these kinds of tools in separate files (as opposed to aliases) is that they're easier to manage from a version control repository. When I set up a new machine, I just go to the User's home folder and checkout my bin directory. Fin.

Another reason that I use files instead of aliases is that they're easier to search. For example, if I'm looking for a script that I wrote three years ago and I know it uses ssh, I just do this to jog my memory:

$ grep -li "ssh" ~/bin/*

Shell Tricks

Once you get your shell setup, it's time to learn some of its most useful tricks.


The shell remembers everything you type. With a few simple characters, you can avoid retyping. The first two are !! which repeats the last command entered. I'm ashamed to admit that I do this every time I edit my /etc/hosts file:

$ vi /etc/hosts

"Oh crap, it's read only."

$ sudo !!

If you just want to reuse the last item in the command, which is typically a file name, then you can use !$:

$ cat TODO.txt
$ rm !$

Merlin has Inbox Zero. I HAVE TODO LIST ZERO

The history command will give you a list of the last 500 things you've typed:

$ history

That's a lot of stuff, huh?

If you want to execute one of those commands again, just use an exclamation point followed by the sequence number. For example:

$ !100

Because the history list is so long, there are a couple of strategies for dealing with its size. The first is to do a simple search:

$ history | grep “BLOW”

Alternatively, you can use use less to search the list interactively:

$ history | less

There are a few other ways to reuse your shell history: do a search for "Event Designators" in the bash manual page.

Command Substitution

Another powerful feature of the shell is command substitution. When you place back ticks around a command, the results are used in the current command. For example:

$ xcode-select --print-path

$ cd `xcode-select --print-path`

$ pwd

Not only does this save typing, but it makes sure that you're in the right place if you have multiple versions of Xcode installed. Bring on the beta releases!

Note: This is essentially how I setup the $XCODE environment variable in my .profile earlier.

Command substitution isn't limited to just paths, either. Try this:

$ `which svn` --version

Desktop Integration

As software developers, we live in two worlds: the command line and the desktop. Not surprisingly, Apple has provided several tools that helps you unite these two worlds. The following are some of my favorites.


The first tool is called open. Both the name and a manual page that says "opens files and directories" belie its true power.

For example, say you want to open the shell's current directory in a Finder folder. It's this easy:

$ open .

If you want to reveal the enclosing folder for a directory or file, then just add the -R parameter:

$ open -R .

The default is to open a file item in the Finder, but you can also specify and application using the -a parameter. Here are a few examples:

$ open -a Terminal /Users/CHOCK/DOT_PRON

$ open -a Preview Default.png 

$ open -a TextEdit README.txt


Since this is a Unix tool, you can open the standard input in an application using the -f parameter:

$ cal | open -a TextEdit -f

The open command assumes that text will be used for standard input, so if you want to use it with other file types, you'll need to use a temporary file. For example:

$ temp="/tmp/CHOCKIFY.HTML"; \
    curl -s http://iconfactory.com/ | \
    tr "[a-z]" "[A-Z]" > $temp; \
    open -a Safari $temp

And since URLs are just another kind of file in OS X, you can use open to download them:

$ open http://files.iconfactory.net/downloads/miscellaneous/xScope_Presskit.zip

Or open your favorite network share points:

$ open afp://datacenter.nsa.gov/CHOCK/UNDIES

You can also include a "username:password@" before the host name, but I recommend that you just let the Finder prompt you for the login information. Remember that your shell history contains the last 500 things you've typed, so protect yourself from some smart-ass like me that sits down in front of your Terminal and does this:

$ history | grep -e "ssh" -e "afp"

Drag & Drop

As you can see, there are many different ways to go from the command line to the desktop. Conversely, going from the desktop to the command line is remarkably simple: you can drag any file or folder from a Finder window into the Terminal window and you get it's path.



As developers, we live and die by our clipboard. Code and data moves between different contexts all day long thanks to Cocoa's NSPasteboard. It should not be surprising that pbcopy and pbpaste are simple and powerful integration points at the command line.

Want to see the contents of your clipboard or put it in a file? Here you go:

$ echo `pbpaste`

$ pbpaste > /tmp/ELMERS.TXT

Going the other direction, you can copy the current month's calendar to the clipboard and then paste it into another app:

$ cal | pbcopy



Most apps have preferences that are managed by NSUserDefaults. You can easily view or modify these settings from the command line using the defaults command.

Let's start by looking at all the preferences for Xcode:

$ defaults read com.apple.dt.Xcode

Looks more like a database than preferences, right? Every setting is shown with its key and associated value.

If you're interested in a single key, you can use it to limit the output. Say you want to get the information of every iOS device you've used in the Xcode Device Manager:

$ defaults read com.apple.dt.Xcode DVTSavediPhoneDevices

You can also specify a new value after the key. Set the one true tab width using:

$ defaults write com.apple.dt.Xcode DVTTextIndentTabWidth 4

Sometimes settings are used to persist data across launches. There are often cases where you want to get rid of things without wiping out the entire database. Here's an example of removing the recent text completions in Xcode:

$ defaults delete com.apple.dt.Xcode \

Note that using the defaults command is much safer than editing a .plist file in ~/Library/Preferences by hand. Beginning in Mavericks, there is a cfprefsd daemon that manages and caches updates to these files. If you use a text editor to modify the file directly, both you and your app will get confused when the changes don't propagate through the cache managed by the daemon.


You know your Mac has pretty great speech synthesis built-in. But did you know is available from the command line as well? Say hello to:

$ say hello

Do you ever find yourself with a process that takes a really long time to run? Something like realigning the cores on Marco's new Mac Pro:

$ ./realign_core_processing_units ; say "cores realigned"

When the script finishes running after a few hours, you'll hear "cores realigned". Even if you’re not looking at the Terminal window, you’ll immediately know why everything feels so much snappier.

Now imagine the fun you can have when you ssh into a designer’s Mac with an open Skype microphone nearby:

$ say “I’m getting a tingling sensation in my hard drive.”

Hugs and kisses, Louie.


Speaking of designers, one of the best ways to communicate with them is through pictures. The screencapture tool let's you do some things you can't do using the Command-Shift-3 and Command-Shift-4 keys in the Finder.

If you need to take a screenshot of the entire screen and want to put it in a new email message, just do this:

$ screencapture -C -M /tmp/image.png

Sometimes you need to get things setup before taking the screenshot (opening menus, for example.) So just tell screencapture to wait ten seconds:

$ screencapture -T 10 -P /tmp/image.png

The -P option tells the tool to open the captured image in the Preview app, too. That's often helpful to make sure you got everything you wanted in the shot.

If you're going to paste the image into an image editor, use the -c option to put the shot on the clipboard:

$ screencapture -c

If you're interested in getting just a portion of the screen, use the -s to select a portion using the mouse. You can also specify different output formats with -t option:

$ screencapture -s -t pdf /tmp/image.pdf

As you've seen, this tool has a lot of options, so I usually refresh my memory with the built-in help:

$ screencapture -h

mdls and mdfind

Spotlight search on the Desktop has become an essential tool for developers. We find code, documentation, messages and all kinds of information that's related to our projects using Command-space and a simple text field. Would it surprise you to know that you can do more complex searches of the same dataset using the command line?

To give you and idea of how much searchable data is available for Spotlight, use the following command on one of your Mac's hard drives:

$ sudo du -sh /Volumes/ELEVEN/.Spotlight-V100
1.6G	/Volumes/ELEVEN/.Spotlight-V100

The Spotlight index on my MacBook Air's 256 GB drive is a whopping 1.6 GB.

So how do we dig around in this huge database? The first step is to get an idea of what the key/value pairs in the index look like. The mdls tool is the way to do this:

$ mdls ~/Documents

Try this command on a few document files as well (folders and files have different metadata.) The keys usually start with "kMD”. For example, an item’s name in the filesystem is stored with the kMDItemFSName key. The values are everything after the equal sign.

Now that you've got an idea of what keys and values can be used, let's do some searching!

At its simplest, mdfind is a command line version of the Spotlight search in the upper-right corner of your menubar:

$ mdfind -interpret "BOOGIE WOOGIE"


This facility starts to get more powerful when you start using keys and values in the query. For example, this is a simple query that lists all items, both files and folders, that have a custom icon:

$ mdfind "kMDItemFSHasCustomIcon == 1"

(Remember this command when we start digging around in resource forks below.)

These queries can be combined with || or && to form more expressive searches. Here's how you'd find all Photoshop files that have a layer named "Layer 1":

$ mdfind "kMDItemLayerNames == 'Layer 1' \
    && kMDItemContentType == 'com.adobe.photoshop-image'"

I found out that PSD files have a kMDItemLayerNames key by using mdls on a sample file. This is generally faster than Reading The Fine Manual.

The search through the metadata can also be limited to items that are in a specific folder. For example, here's how you'd find all the items in a Project folder that have been localized in Japanese:

$ mdfind "kMDItemLanguages == 'Japanese'" \
    -onlyin ~/Projects

Another great feature of mdfind is that you can pipe it's output to xargs to run other shell commands on the results. For example, the following command will find all apps that are PowerPC-only and send them to xargs (note the usage of -0 in both commands to delimit the listed items.) In turn, xargs will use du to show how much space each app uses and a grand total at the end:

$ mdfind "kMDItemExecutableArchitectures == 'ppc' \
    && kMDItemExecutableArchitectures != i386 \
    && kMDItemExecutableArchitectures != x86_64" -0 \
    | xargs -0 du -sh -c

If you're like me and have been migrating your Applications folder for years, there are a surprisingly large number of items that are wasting space. Doing the actual work of removing these items is left an exercise for the reader.

(Hint: rm is a shell command just like du. Be careful and backup first.)

Application Integration

It's incredibly handy to control your desktop apps using the shell. Since AppleScript has always been the best way to control apps, it makes sense that there would be a command line tool. The osascript tool is one the Swiss Army would love.

Want to change the volume of your speakers with a shell script? Go for it:

$ osascript -e 'set volume output muted true'
$ sudo osascript -e 'set volume 10'

You can also tell the Finder to do common chores:

$ osascript -e 'tell application "Finder" to empty trash'

It's the end of a long work day and you have a script that needs to run for a few hours. It would be really nice to sleep your Mac after that job is finished, wouldn't it?

$ ./realign_core_processing_units; \
    osascript -e 'tell application "Finder" to sleep'

It's kind of a shame that Marco won't be there to see how snappy the realigned cores are, but hey, whatever.

AppleScript from your shell can also relieve frustration:

$ osascript -e 'tell application "Messages" to quit'

Note that this is a more friendly way to do it than killall Messages since the "quit" Apple Event gives the app a chance to shutdown gracefully. Not that Messages would really notice.

If you want to switch from the Terminal to another application, use this:

$ osascript -e 'tell app "Safari" to activate'

You can also use AppleScript to get information about apps:

$ osascript -e 'id of app "Xcode"'

$ defaults read `osascript -e 'id of app "Xcode"'`

Or get the properties of any file or folder:

$ osascript -s s -e 'tell application "Finder" ¬
    to get properties of item POSIX file ¬
    "/tmp/HOTT.png"' > /tmp/HOTTNESS.txt

$ cat /tmp/HOTTNESS.txt 
{class:document file, name:"HOTT.png", index:2, displayed name:"HOTT.png", name extension:"png", extension hidden:false, container:folder "tmp" of item "private" of startup disk of application "Finder", disk:startup disk of application "Finder", position:{-1, -1}, desktop position:missing value, bounds:{-33, -33, 31, 31}, kind:"Portable Network Graphics image", label index:0, locked:false, description:missing value, comment:"", size:49547, physical size:53248, creation date:date "Saturday, July 5, 2014 12:01:52 PM", modification date:date "Saturday, July 5, 2014 12:01:52 PM", icon:missing value, URL:"file://localhost/private/tmp/HOTT.png", owner:"CHOCK", group:"root", owner privileges:read write, group privileges:read only, everyones privileges:read only, file type:missing value, creator type:missing value, stationery:false, product version:"", version:""}

Note the use of ¬ as AppleScript's line continuation character. You can get this character into your editor by using Option-L on your keyboard.

File Tools

We're developers. We love files. In more ways than ls, cat, and rm can ever know.

Let's meet some new friends...


How often have you opened a Get Info window in the Finder just to know the dimensions of an image or other basic information about a file in a project? The Finder is fine, but you're already at the command line, so just use file instead:

$ file Default.png
Default.png: PNG image data, 640 x 1136, 8-bit/color RGB, non-interlaced

Getting the file information from the command line is often faster if you're dealing with a lot of different resources. For example, when your designer gives you a bunch of PNG files and you need to set sizes for them in code, here's how you get all the non-2x dimensions:

$ cd Images
$ file *[^2][^x].png

Much quicker! And file can tell you things that the Finder can't. Like the architectures supported in a binary:

$ cd /Applications/iTunes.app/Contents/MacOS
$ file iTunes
iTunes: Mach-O universal binary with 2 architectures
iTunes (for architecture i386): Mach-O executable i386
iTunes (for architecture x86_64): Mach-O 64-bit executable x86_64

This is particularly helpful when you're getting link errors for a .dylib library that's in your project: file will probably tell you that an architecture you need is missing.

You can throw pretty much anything at file:

$ file Notes.rtf 
Notes.rtf: Rich Text Format data, version 1, ANSI

$ file Wallpaper.psd 
Wallpaper.psd: Adobe Photoshop Image, 744 x 1392, RGB, 3x 8-bit channels

$ file Rubylith.qtz 
Rubylith.qtz: Apple binary property list

$ file Colors.pdf 
Colors.pdf: PDF document, version 1.1

$ file xScope.entitlements 
xScope.entitlements: XML  document text

Note that it doesn't know that .entitlements is an XML plist. But we've still got less to figure that out.

It's amazing how many different types of files can be examined using this simple command. To get an idea:

$ ls /usr/share/file/magic

$ less /usr/share/file/magic/apple

If you ever run across a Newton package or some Applesoft BASIC, file has you covered.

Quick Look

As its name implies, Quick Look is an extremely fast way to check the contents of a project asset. Want to make sure your iOS app's launch images are correct without leaving the command line?

$ qlmanage -p Default*.png

The arrow keys let you scroll through the images and a tap on the space bar gets you back at a command prompt. This is a much quicker and easier way than viewing the images with Preview or an open command—your hands never need to leave the keyboard!

To make this even easier, I have a short shell script named ql:

qlmanage -p "$@" 

I use it every day to check one or more files:

$ ql single.png multiple/*.{png,jpg}

Extended Attributes

While Spotlight’s index is an external source of metadata about files, the OS X file systems also support extended attributes. Like Spotlight’s metadata, these can be thought of as key/value pairs that are attached to any regular file or directory.

To view these attributes, you use the xattr utility:

$ xattr ~/Downloads/tweets.zip 

Another way to get the same information is to use the -l@ option with ls.

The tweets.zip file that was downloaded has three extended attributes. But what’s in these attributes?

The simple answer is that you don’t know: the use of reverse domain names is the first hint that the data is application-specific. Apple clearly uses these attributes for their own internal needs. Additionally, any application can attach its own information to a file using this mechanism.

In practice though, you can usually figure out what’s being stored there using the -p and -lp options. For example, after you look at the contents of the attribute, it’s a pretty safe bet that com.apple.quarantine is used to mark files that have just been downloaded:

$ xattr -p com.apple.quarantine ~/Downloads/tweets.zip 

In fact, if you want to skip the warnings from the Finder about the dangers of opening files, you can remove the quarantine attribute:

$ xattr -d com.apple.quarantine ~/Downloads/tweets.zip 

Since any data can be attached to the named attribute, sometimes you’ll see a bunch of hex values instead of text:

$ xattr -p com.apple.metadata:kMDItemDownloadedDate \
62 70 6C 69 73 74 30 30 A1 01 33 41 B6 86 3B 6D
B2 87 5D 08 0A 00 00 00 00 00 00 01 01 00 00 00
00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 13

If that happens, just use the -lp option instead:

$ xattr -lp com.apple.metadata:kMDItemDownloadedDate \
00000000  62 70 6C 69 … B6 86 3B 6D  |bplist00..3A..;m|
00000010  B2 87 5D 08 … 01 00 00 00  |..].............|
00000020  00 00 00 00 … 00 00 00 00  |................|
00000030  00 00 00 00 …              |.....|

That “bplist” looks like a hint to the contents of the data. More about that in just a bit.

Extended attributes are pervasive: you’ll find that they’re working quietly behind the scenes to enable a lot of functionality we take for granted. For example, have you ever wondered why Xcode build folders never get backed up by Time Machine? Here’s your answer:

$ cd ~/Projects/CHOCKINATOR/build
$ xattr .

Resource Forks

If you’re a long-time Mac developer, you’ll remember the days of resource forks. They were kind of like the extended attributes shown above, but the attribute names were limited to four characters and the data being stored was only accessible on a Mac.

Some things never die: Mac files can still have a resource fork. These days, they’re mostly used to store custom icons that have been attached to a file or folder.

To access the resource fork of a file, just append “..namedfork/rsrc” to the path. For example:

$ ls -oh FERRET
-rw-r--r--@ 1 CHOCK     0B Apr 19  2010 FERRET
$ ls -oh FERRET/..namedfork/rsrc
-rw-r--r--  1 CHOCK   155K Apr 19  2010 FERRET/..namedfork/rsrc

The file has zero bytes of data, but the resource fork uses 155 KB. Let’s throw it at file and see what happens:

$ file FERRET/..namedfork/rsrc
FERRET/..namedfork/rsrc: MS Windows icon resource

Close. It’s actually a Mac ICNS resource. I'm pretty sure this is the first and only time I've seen file get it wrong.

If you’ve ever noticed a zero length file named “Icon?” in a folder that has a custom icon, it’s the same thing:

$ file Icon^M/..namedfork/rsrc
/..namedfork/rsrc: MS Windows icon resource

Note: to get the ^M in the name, type Control-V followed by Control-M. You can do this to get any control character into the shell’s edit buffer.

Internally, the resource forks are stored as extended attributes using com.apple.ResourceFork. If you try to access it with xattr you’ll get an “operation not permitted” error.

Finder Info

Another extended attribute that can contain useful information is com.apple.FinderInfo. This chunk of data contains, well, information for the Finder:

$ xattr HOTT.png
$ xattr -p com.apple.FinderInfo HOTT.png
00 00 00 00 43 48 4F 4B 00 50 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Unless you're me, you don't recognize the extreme importance of 0x43, 0x48, 0x4F, and 0x4B. Luckily, there are some helpful tools in your Xcode Developer Tools folder. The first is GetFileInfo:

$ GetFileInfo HOTT.png 
file: "/private/tmp/HOTT.png"
type: "\0\0\0\0"
creator: "CHOK"
attributes: avbstclinMEdz
created: 01/21/2014 10:31:53
modified: 01/21/2014 10:31:53

The man page for GetFileInfo explains the attributes. The creator, and source of those four hex bytes mentioned above, needs no explanation.

To change the file info, you'd use SetFile. That being said, it's probably easier to do it in the Finder's Get Info panel:

$ osascript -e 'tell application "Finder" to ¬
    open information window ¬
    of item POSIX file "/tmp/HOTT.png"'

Fun Fact: These tools have been around since the days of MPW. If you don't know what MPW means, consider yourself lucky. In fact, pretty much everything in $XCODE/Tools is a trip back in time. Do this if you remember them as the "good ol' days":

$ man Rez

Examining Binaries

A lot of the files we deal with are executable. Even if symbols have been stripped from the app, you can still infer a lot of information by looking at the null terminated strings present in the data:

$ cd /Applications/TextEdit.app/Contents/MacOS
$ strings TextEdit

Better yet, take it a step further and look at the information the Objective-C runtime uses in the Mach-O binary:

$ class-dump TextEdit

I think it's safe to say that the iOS Jailbreak community would not formed as quickly as it did without this tool. It's that important for figuring out what another developer did in their Objective-C code.

If you don't have class-dump installed on your development machine, fix that right now. And while you're there, don't be a tightwad: put some money in Steve Nygard's tip jar. He's been supporting and maintaining this free tool for years.

Test and Debug

So far we've pretty much treated the shell as a static environment. But we all know there are lots of gears and levers moving behind the scenes. The shell is a great place to watch that activity.


When I'm in a shell and want to see the overall activity on a system, this is the first tool that I turn to:

$ top -d -u -s 10

The -d option shows deltas for network and paging activity (which is much more useful than total counts.) I typically run this command when some process is running amok: -u sorts the list by CPU usage. Using -s 10 updates the output every 10 seconds, minimizing the sampling affecting in the results. A longer sampling period also helps keep the listed processes from jumping around too much.

On the desktop, I always run the first Cocoa app I ever wrote: iPulse presents this information (and more!) in an interface that's easy to read at a glance.


Have you ever tried to eject a disk and had the Finder tell you it can't because there are still files still open? You've probably seen lsof used as a way to tell you what those files are:

$ lsof +d /Volumes/KILO

But as with most great Unix tools, lsof is not a one-trick pony.

For example, you can use lsof to see all the files an app has open. Let's look at everything the Finder has open using the -c option:

$ lsof -c Finder

Yeah, that's a lot of files. So use grep to narrow down the search:

$ lsof -c Finder | grep PrivateFrameworks

Hmmm… the large ArtFile.bin file in CoreUI.framework sure looks interesting.

And remember that Unix sockets are just another kind of file. So in addition to checking what normal files a process has open:

$ lsof -c Dropbox | grep "/Users/CHOCK"

You can also check what kind of network connections it has open and the state of those connections:

$ lsof -c Dropbox | grep "TCP"
$ lsof -c Dropbox | grep "LISTEN"

Taking the network theme a bit further, the -i parameter lets you see which processes have open connections on specific ports:

$ lsof -i :80
$ lsof -i :22

Want to see all the processes that are listening on a socket? Here you go:

$ lsof -i | grep LISTEN

Or ones that have established connections:

$ lsof -i | grep ESTABLISHED

Remember that sockets are often used for interprocess communication, so just because there's a connection, it doesn't mean that packets are leaving your Mac.

In general, lsof is a great tool for investigate processes that are unknown, poorly documented, or you're just curious about:

$ psc securityd
   18     1 root           /usr/sbin/securityd -i
$ sudo lsof -p 18 | grep "/Applications"

You probably didn't realize it at first, but you just got a list of all applications that are using the Keychain. Note that sudo is required because the securityd process runs with elevated privileges.

As you can see, there are a lot of options and parameters, so make sure to take a look at the lsof man page.


If you're developing for Mac or iOS, you already know how damn useful Instruments is for tracking application behavior. DTrace is the framework that makes all that possible. Well, take a look at all the stuff in the shell that "uses DTrace":

$ man -k dtrace

Whoa. That's a lot of stuff. A shorter and more useful list can be had by just showing the "snoop" tools:

$ man -k snoop

As you saw above, lsof gives you a snapshot of the current state of processes and the files they have open. The "snoop" tools, on the other hand, show you the system as it changes state. For example, let's use opensnoop to watch the system logging process as it opens files:

$ sudo opensnoop -p `cat /var/run/syslog.pid`

Every command that uses DTrace requires elevated permissions to retrieve the buffered data from the kernel. Get used to typing sudo.

Now, in another Terminal window, send something to the system log:

$ sudo syslog -s "CHOCK ME BABY"

The window running open snoop should show something like this:

  UID    PID COMM          FD PATH                 
    0     23 syslogd       15 /var/log/system.log  

Have you ever wondered how crackers find the super secret file you use to store serial numbers? Use the -n to specify a process by name:

$ sudo opensnoop -n Uncrackable.app

There you go. Good luck trying to outsmart the kernel with your "uncrackable" protection scheme.

If you're interested in seeing which processes open a specific file, use -f to specify a path:

$ cd ~/Library/Keychains
$ sudo opensnoop -f CHOCK.keychain

You can also track file or disk activity with rwsnoop and iosnoop:

$ sudo rwsnoop -n Safari
$ sudo iosnoop -n Safari

As you saw with that long list of DTrace shell commands, there's a lot more you can do with this facility. In fact, you can actually write code that gets compiled and run. Here's a one-liner that shows when processes are spawned and exec'ed:

$ sudo dtrace -n 'proc:::exec-success { \
    printf("%d %s", timestamp, curpsinfo->pr_psargs); \

In fact, those "snoop" tools you just ran are just script wrappers around code written in the D language:

$ less `which opensnoop`

For more information and tips about using DTrace on Mac OS X, check out the DTrace site.


Another tool to watch what's going on in the filesystem is fs_usage. This tool reports any activity for calls to like fopen(), fwrite(), getattrlist(), fsync(), etc.

For example, if you want to watch the Finder manipulate files:

$ sudo fs_usage Finder

When using this tool, remember that a "file system" doesn't necessarily mean a disk is involved. The -f option lets you filter out network related events:

$ sudo fs_usage -f network Safari


If there was an award for the crappiest OS X man page, I'd have to award it to tccutil:

$ man tccutil

Only one service is listed in the man page: "AddressBook". There are others, and now that you know how to poke around in binary files, you can find them:

$ strings /System/Library/PrivateFrameworks/TCC.framework/TCC \
    | grep kTCCService 

If you're testing an app that requests for a user's calendar information, you can reset the authorization by removing the "kTCCService" prefix from the list above:

$ sudo tccutil reset Calendar

Be careful when you're using this tool: you're resetting all apps in each service category, not just your own. I do not recommend running this command on a machine where you have apps already registered in System Preferences > Security & Privacy > Privacy. Use a test machine or a clean VM image before you start blasting away at security settings.

It's also worth noting that Accessibility is a special case. There is a SQLite database that contains the bundle ids for the applications that have been granted access. And you can modify that database:

$ sudo sqlite3 \
    /Library/Application\ Support/com.apple.TCC/TCC.db
sqlite> .schema access
sqlite> select * from access;
sqlite> delete from access where client like '%Xcode';

Note that these commands have no effect on whether you see the authorization prompts the first time a user accesses the service from your app. After a new app been presented with the alert dialog, an entry is added to the com.apple.universalaccessAuthWarning defaults:

$ defaults read com.apple.universalaccessAuthWarning

You can hunt for specific paths and bundle IDs, or just use the nuclear option:

$ defaults delete com.apple.universalaccessAuthWarning

After clearing the warnings, you'll need to restart your Mac and run the app again. Again, this is much more palatable if you're working in a test environment on a dedicated machine or VM.

When your working with the above commands, remember that as far as security is concerned, you'll be getting a bundle ID for Xcode when running under the debugger. In many cases, you want to get rid of settings for com.apple.dt.Xcode as well as ones for your own app.

The Internet

True story: the Internet existed on the command line before the Tim Berners-Lee ever thought about making a browser in the early '90's. First there was Telnet in 1969, then FTP in 1971, followed by Finger in 1977, and so on.

I think it's pretty safe to say the command line will never die, but the best part is that your Terminal continues to be a tool that works great in our networked world.


Every time I upload a new version of our software, I check it using curl:

$ curl --head http://iconfactory.com/assets/software/xscope/xScope-4.0.zip

This lets me see that a "200 OK" response is returned and that the number of bytes match my local copy.

Another great use for curl is to watch all data that gets transferred over a HTTP connection. And I mean ALL the data:

$ curl -v http://CHOCKLOCK.COM

The title of curl's man page is "transfer a URL." That all encompassing description should be your first hint that the tool does a lot. And I mean a lot—it supports the DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET and TFTP protocols.

If you use URLs in your work, do yourself a favor and check out the man page.


Did you know that you can write code that runs in the OS X kernel and looks at every network packet at the data link layer? And that you can do it from the command line?

The tcpdump command is a user interface for Berkeley Packet Filters. This powerful tool can show you anything that's happening on your network.

A simple example is to watch what's happening when you access a web resource. Say you want to see all the HTTP data that passes on the network when you load Gruber's latest post in your browser:

$ sudo tcpdump -s 0 -A \
    port 80 and host daringfireball.net 

The -s parameter sets the amount of data you see in each packet: when it's set to zero, you get everything. The -A parameter specifies that the data should be displayed in ASCII. You need to use sudo with tcpdump because you're accessing the /dev/bpf* devices which have root-only permissions.

In conjunction with Internet Sharing, tcpdump can be a very powerful tool for iOS developers. After setting up Internet Sharing in your Mac's System Preferences, you can then watch traffic that passes between the Ethernet and Wi-Fi interfaces of that shared connection. If your iPhone is connected over Wi-Fi to your Mac using the IP address, the following command will show all the requests it sends to Daring Fireball:

$ sudo tcpdump -s 0 -A port 80 \
    and src \
    and dst daringfireball.net 

If you were interested in packets going the other way, just swap the src and dst. Hopefully, you'll see how this is useful when debugging network traffic between your iOS device and a REST service.

The syntax used to write the packet filter code is defined in the pcap-filter manual page ("pcap" is short for packet capture.) The filtering options in the expression include detecting different network protocols and examining the length and contents of the packets themselves.


Have you ever had a folder full of files that you've wanted to access through a web browser? You could setup Apache to do this by editing the httpd.conf file, or just enter the following command in the folder you want to access:

$ python -m SimpleHTTPServer 8000

Now, when you open http://localhost:8000 in browser, you'll be able to traverse the directory structure. Note that the server runs until you use Control-C to get back to the shell prompt.

This can be a great tool when testing your code: the directory can contain static JSON files that include data for your app. Just update the endpoints in your code to use the localhost and you're set.


Caches are designed to store information that's used repeatedly. But when that data gets stale, you need a way to flush the cache. As developers, we're often faced with DNS or other changes that affect our network stack.

When you find some piece of software misbehaving on the network, it's often caused by the Directory Service cache being out-of-date. Luckily, there's a simple command to flush the cache and get things back in working order:

$ dscacheutil -flushcache

If you're having problems resolving IP addresses from domain names, you can restart the DNS server with:

$ sudo killall -HUP mDNSResponder

A similar command causes statistics and other diagnostic information to be logged to /var/log/system.log:

$ sudo killall -INFO mDNSResponder

Be prepared to sift through a lot of information!


Every Unix system has a simple tab-delimited database of service names and ports. The file is located in /etc/services. If you're wondering what's listening on port 69, do this:

$ grep "\s69/" /etc/services
tftp             69/udp     # Trivial File Transfer
tftp             69/tcp     # Trivial File Transfer

You'll also see that the TFTP service can use both TCP and UDP protocols.

Another handy search is if your looking for the standard ports for a protocol. Say you want to know which ports can be used for IMAP:

$ grep imap /etc/services
imap      143/udp  # Internet Message Access Protocol
imap      143/tcp  # Internet Message Access Protocol
imap3     220/udp  # Interactive Mail Access Protocol v3
imap3     220/tcp  # Interactive Mail Access Protocol v3
imap4-ssl 585/udp  # IMAP4+SSL (use 993 instead)
imap4-ssl 585/tcp  # IMAP4+SSL (use 993 instead)
imaps     993/udp  # imap4 protocol over TLS/SSL
imaps     993/tcp  # imap4 protocol over TLS/SSL

IP address

Need to know the WAN IP address you've been assigned outside your internal LAN?

$ curl -s ifconfig.me

Loading the site in your browser shows a lot of other options. Be aware that information about the HTTP connection and HTML content aren't available from the command line unless you explicitly set them as options for curl.


Data is never in the format you need it, is it? The shell's notion of standard input and output has always made it great for doing data conversion. Here are some tools that you may not know about...


Want to convert text between .txt, .html, .rtf, .rtfd, .doc, .docx, .wordml, .odt and .webarchive formats? Look here:

$ man textutil

It's pretty hard to read a binary property list, so convert it to XML or JSON. Or vice versa:

$ man plutil

Your designer gives you individual PNG files for your app icon, but your project needs an .icns file. Or vice versa:

$ man iconutil

Pretend like you're in The Matrix:

$ hexdump -C Default.png

Or convert between hex and binary formats:

$ man xxd


How many ways do we need to compress data? In the world of the command line, I'm pretty sure the answer to that question is a number that approaches infinity. Regardless, here are a few of the most common formats and the tools used to view and extract the data from the command line.

If you have a ZIP file and you want to quickly view its contents, use the unzip command with the -l option:


Without the option, the ZIP file will be extracted to the current directory:


Similarly, a GZIP compressed TAR archive can be listed with:

$ tar tvfz feather.tgz

And extracted with:

$ tar xvfz feather.tgz

Fun fact: the name tar is short for "tape archive". That gives you an idea of how long this piece of code, and resulting archives, have been around. I think it's pretty cool that an archive you created in the 1970's can still be used forty years later. How much code being written today will be able to say that?

Log files are often compressed with either GZIP or BZIP. A quick way to uncompress these files and view their contents is to use the "cat" variants and pipe the output to less:

$ gzcat les_paul.log.gz | less

$ bzcat /var/log/system.log.0.bz2 | less

Disk Utilities

If you're looking for a disk utility, look no further than diskutil. This is essentially the command line version of the Disk Utility in your Applications > Utilities folder.

The first command I use is list:

$ diskutil list
 #:                  TYPE              SIZE     IDENTIFIER
 0: GUID_partition_scheme             *251.0 GB disk0
 1:                   EFI              209.7 MB disk0s1
 2:             Apple_HFS KITTYS       250.1 GB disk0s2
 3:            Apple_Boot Recovery HD  650.0 MB disk0s3

This gives you the layout of all attached disks. The identifier column is typically used as a parameter for the other commands. For example, if you want to see all the information about your Apple_HFS partition, you'd use the identifier for that partition:

$ diskutil info disk0s2

A similar command gets information about the disk itself. In this case, we're also using grep to quickly get the SMART status for the drive:

$ diskutil info disk0 | grep "SMART"
   SMART Status:             Verified

Some of the commands can use volume names instead of identifiers. For example, to eject a volume, you can use:

$ diskutil eject /Volumes/NOODLE

Be careful with diskutil since it also provides commands like secureErase and partitionDisk—they can quickly and permanently destroy your data. Expert users also use this command to setup and manage software RAID sets.

Another simple disk utility is the df (the short form for "disk free".) To show how much free space you have on your boot volume, use:

$ df -h /


Did you know you can use Unicode in shell commands? Yep:

$ echo $'\xf0\x9f\x8d\x94'

$ date +$'\xe2\x98\x95 %A'
🍔 Tuesday

The sequence of hex values is the UTF-8 representation of code point U+1F354. It's a shame that there is no such sequence for a taco.

If that example doesn't show up correctly in your browser, it's because you're using one that has lousy support for emoji characters *cough* Chrome *cough*. Go ahead and paste the text into the Terminal: it has a much better taste for grilled meat on a soft bun.

A Practical Example

Remember that "bplist" we encountered in the extended attributes for our download? What did those hex values represent? We now have the tools to figure that out!

First start by getting the metadata into a temporary file:

$ cd ~/Downloads
$ xattr -p com.apple.metadata:kMDItemDownloadedDate tweets.zip > /tmp/tweets.xd

$ cat /tmp/tweets.xd 
62 70 6C 69 73 74 30 30 A1 01 33 41 B6 86 3B 6D
B2 87 5D 08 0A 00 00 00 00 00 00 01 01 00 00 00
00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 13

Now, let's convert the hex dump into binary data:

$ xxd -r -p -g 1 -c 16 /tmp/tweets.xd - > /tmp/tweets.plist

And then convert the binary data to XML text:

$ plutil -convert xml1 /tmp/tweets.plist -o -
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Note that the date is in UTC (GMT), so let's figure out the local time:

$ date -ujf "%Y-%m-%d %H:%M:%S" "2012-12-22 19:03:09" +%s

$ date -r 1356202989
Sat Dec 22 11:03:09 PST 2012

Or we could have just gotten that info directly from the same APIs that the Finder uses :-)

$ GetFileInfo tweets.zip
file: "/Users/CHOCK/Downloads/tweets.zip"
type: "\0\0\0\0"
creator: "\0\0\0\0"
attributes: avbstclinmedz
created: 12/22/2012 11:03:09
modified: 12/22/2012 11:03:09

Mastering the shell is not so much a matter of learning individual commands, but rather learning how the tools can be used together to solve a problem.

Of course, the hard part is knowing which commands you have at your disposal. Now that you've made it to the end of this huge post, hopefully you'll have a few new things in your mental tool chest.


This post came to life last February during a five hour layover caused by a cancelled flight. Finishing touches were made on my trip home from WWDC 2014. The fact that I was writing about the terminal while sitting in the terminal was not lost on me.

Writing 9,000+ words on a technical topic takes a long time. These "Siracusian" efforts are all about the details: there is an amazing amount of research involved, even for things you already know well!

In spite of the effort involved, I love writing long-form pieces like this one. The problem is that I also love paying my bills. As a result, what could have been written in a few days takes months to pull together.

This is where you come in: you can help pay for more of my writing by purchasing one of the many products my company offers. Download a free trial of xScope 4, sign up for a free AppViz account, or ask us to do some design work for your project. Besides getting a great product or service, you're also giving me the ability to write about topics that are valuable to you and your fellow developers.

If you have already supported the Iconfactory in one way or another, thank you! You can still help out: take a moment to tell your friends and followers about us on Twitter or Facebook. Word of mouth is our favorite form of marketing and it's up to you to make it happen!

A documentary

For the past few months, I’ve been helping a couple of talented filmmakers with a new project. I’ve been making introductions, reminding busy people to find some time for an interview, and that kind of thing. Today, the result was made public and it’s better than I ever imagined.

I think this project that looks at our past is important for two reasons: our present and future.

It’s no secret that the art and business of software development has changed radically since that day in January 2007. Listening to my colleagues talk about what that moment meant to them is incredibly helpful for putting today’s situation in perspective. You don’t give a shit how big the next iPhone’s screen is going to be when your peers are talking about how these devices have changed their lives.

By funding this project, you’re also giving your future self a rare gift. I was a young developer when the Mac was announced in 1984, and let me assure you that many of the details of that time have been lost over the course of thirty years. You’re going to look back at this time in your career fondly and wish you remembered more about it.

Something like what Andy Hertzfeld has done at Folklore.org has been a godsend to those of us who were around in the early days of the Mac. But I don’t think that approach would work now: the Internet made the iPhone a world-wide phenomenon, not a project limited to the Texaco Towers. (Did you know that the first person to make money from selling apps was a developer in New Zealand?)

This is your chance to create a record of something that has changed so many lives. Please take a moment to look at what Jake and Jed have done and join me in contributing to this Kickstarter.


An anonymous individual is spreading accusations that I’m a patent troll. Hard to believe, huh?

It makes me furious that I have to respond to these claims without knowing my accuser, but here goes:

Yes, we have a patent. Yes, we got a license fee for it. No, it wasn’t unreasonable.

We originally got the patent as protection against a large company, like Adobe, using our innovation. Patents are like trademarks, you have to protect them after you get them (by collecting licensing fees, even if it’s a small one.) The arrangement with Ricci Adams was amicable from the first email to the last.

From a monetary point-of-view, all I’m going to tell you is that the fee we collected from Ricci Adams was less than the amount of time and money spent getting the legal documents in place. We didn’t profit from it, nor did it “stifle competition.” (Pixel Winch is a great product, you should check out the beta. And no, I’m not making any money by saying that.)

We also acquired this patent before our encounter with Lodsys. Our view of patents has obviously changed since then. I can’t go into any specific details there, thanks to the lawyers.

And you want to know the real kicker? After talking about this stuff with my friend Marco Arment, we’re no longer sure that software patents have the same “use it or lose it” conditions as with a trademark. Of course, for a lawyer who’s collecting fees, mentioning this is not in their best interest.

Any further comment on this situation will have to wait until the coward who’s making these claims comes forward.

P.S. Marco, I could use that beer now.


We witnessed something amazing yesterday: a WWDC keynote that will be remembered for a long time. And not for the reason you might expect.

As developers, it’s easy to focus on the fantastic software that was announced: a UI refresh that’s getting a thumbs up from designers and developers alike, great new user-facing features in iOS and OS X, and literally thousands of new APIs that let developers do new and amazing things with their apps. We even got a new programming language!


But that all pales in comparison to the undercurrent for all these changes: Apple has a newfound confidence in itself. It’s at the top of its game, and it knows it.

This is personified by the man who ran the show: Craig Federighi. It was only four years ago that we first saw him on stage at an Apple event. His shaking hand is still painful to watch, especially if you’ve felt that same fear while giving a presentation on stage. Yesterday, we saw a different man, one that owned the stage and the products being presented.

With this confidence, we’re starting to see some important cultural change in the company.

  • Legal agreements that lets developers talk about technologies without breaking confidentiality.
  • Opening up proprietary technologies like iCloud: providing more transparent access, without hiding things through opaque APIs.
  • Improvements to the App Store that give developers better ways to manage and sell their products.

This confidence manifests itself in many ways. When was the last time you heard an Apple executive tout the best product line he’s seen in 25 years?

In short, with confidence comes a new kind of openness. As developers, we’ve always struggled with a company that doesn’t want to give anything away. Yesterday, that started to change.


In just under 12 days, Apple is going to introduce a new look and feel for Mac OS X. This is going to be much more disruptive than it was for iOS 7.

On iOS, an app takes up the entire screen and becomes an extension of the device. It’s also something you’re “in and out” of on a regular basis. It’s not the end of the world if one or more of your apps still looks like iOS 6 because it’s not competing with anything else and the pain is short-lived. Bank of America’s app is still on iOS 6, but I use it infrequently and usually just to deposit checks.

But on the Mac, an app usually shares the display with other apps. And they’re something that you use continuously. If a customer’s Email, Web, Calendar, Contacts and other built-in apps are using a fresh, new look, they’re going to feel put out when they switch to your app and get a legacy appearance.

You will stick out like a sore thumb.

We’ve already started the process on our own apps and are gearing up to help our clients adapt. If you haven’t carved out a large chunk of time this summer to do the same for your own app, do it now.

Get Ready for June 2nd

There’s no doubt in my mind that Apple is going to overhaul the look of Mac OS X in the next version. As more and more apps bridge the gap between the desktop and mobile, the lack of consistent branding and design across platforms is becoming a problem.

I fully expect to see flatter user interfaces, squircle icons, a new Dock, and Helvetica Neue as the system font. We’ve already explored a flattened UI and new icons in xScope, but I was still left wondering what the app would look like with Helvetica Neue as the system font. There’s a lot of custom drawing in xScope and I was pretty sure there would be some areas where sizing and placement would be wrong because the metrics for Lucida Grande were assumed.

So I wrote this.

This category swizzles the NSFont class methods to return a different system font. The instance method to initialize a font from an archive (like a XIB) is also swizzled and the font is replaced if it’s Lucida Grande. The MAC_OS_X_VERSION_NT definition is both an inside joke and a way to make sure your code can adapt to any font.

Here’s what one of the new tools in xScope 4 looked like before using the category:


And here it is with Helvetica Neue as the new system font:


As you can see, there are lots of small misalignments, both in my custom controls and the ones provided by Apple.

Changing the system font will be a bit like the transition to the Retina Display: lots of small tweaks to keep our apps looking perfect. Now would be a good time to start looking for areas where your app is going to need work.


I recently appeared with John Gruber on The Talk Show. During the episode, the following exchange took place:

When it comes to naming characters, the Unicode standard is the bible. And code point U+0040 is named as “COMMERCIAL AT”.

So yeah, we’re “right.”

But then Twitter got ahold of this exchange and I quickly realized something important: we don’t all speak English:

It turns out “arroba” has a very interesting history that originated in Spanish commerce:

“Whatever the origin of the @ symbol, the history of its usage is more well-known: it has long been used in Spanish and Portuguese as an abbreviation of arroba, a unit of weight equivalent to 25 pounds, and derived from the Arabic expression of “a quarter” (الربع pronounced ar-rubʿ)”

As someone who loves iconography, it’s pretty amazing to see @ as a handwritten symbol in 1148:

I also realized that I knew the Italian word for the @ symbol: “chiocciola”. It’s one of the names for a snail (the other being “lumaca” which is commonly used when ordering them in a restaurant.)

And why is this name used?

(It’s fun to say, too. Something like “key-o-cho-la” but with more exotic hand gestures.)

This tweet led to many responses that show how varied the pronunciations are in different languages.

  • Dutch: “apenstaartje” = “monkey tail”
  • Hebrew: “strudel” = shape of the cake
  • Danish/Swedish: “snabel-a” = “with an (elephant) trunk”
  • German: “Klammeraffe” = “spider monkey”
  • Poland: “małpa” = “monkey”
  • Korean: “골뱅이” (gol-baeng-ee) = “a type of sea snail”

Wikipedia has a full list of how @ is used in other languages.

But do you notice the pattern with these pronunciations?

They’re being used as pictograms:

“A pictogram…, is an ideogram that conveys its meaning through its pictorial resemblance to a physical object. Pictographs are often used in writing and graphic systems in which the characters are to a considerable extent pictorial in appearance.”

While pictograms are fairly common in Asian languages, it’s rare to see this kind of usage in the West. Written Kanji characters, such as 木 for “tree”, have been in use since the first century AD. Indeed, these kinds pictures were man’s first form of expression and communication.

But in these writing systems, someone saw a thing with a trunk and leaves growing from the ground and put it on a piece of paper as an 木 symbol. What we’ve seen happen with the @ symbol is the opposite. Many different cultures have seen our “COMMERCIAL AT” symbol and given it a name based on its appearance.

So even though John and I are right about the pronunciation, this is certainly a case where English pales when compared with other languages. I envy my colleagues that get to play with snails and monkeys while coding in Objective-C!

Wearing Apple

Tim Cook has openly stated that Apple is working on “new product” categories. Many people, customers and competitors alike, assume that means some kind of wearable computing device. And of course that means it has to be some kind of “smartwatch”, right?

I don’t think so.

The Market

First, let’s look at the market for quality timepieces; ones that you’d be proud to wear on your wrist. It’s dominated by companies with centuries of experience. It’s also a high-end market: spending a few thousand dollars on a nice watch is chump change. You’re buying a work of art.

Apple certainly has great designers, but they’re going to be competing against craftsmen who’ve been refining their craft since the 15th century.

I realize that this sounds a lot like Ed Colligan talking about mobile phones:

“PC guys are not going to just figure this out. They’re not going to just walk in.”

There’s a big difference here: the companies that dominated the music player and mobile phone markets were making complete crap prior to Apple’s arrival. Granted, there are a lot of cheap and crappy watches on the market, but they’re not remotely interesting to the demographic that buys Apple products. And to many people, a fine timepiece is more about status than technology.

Taking all of this into consideration, watches don’t sound like product category that fits Apple well. One of the many reasons we love their products is because they are best of breed.

The Watch

Now, let’s look at the state of the “smartwatch” market. Smart companies, like Nike and FitBit, are creating products that aren’t really a “watch”. It’s like the “phone” being the least interesting thing on our “smartphone”.

In fact, Tim Cook is already wearing one of these devices:

Walt: Is wearables a thing — is it part of the post-PC era wearables that go beyond fitness devices?

Tim: Yes, I think so. I wear a Fuelband, I think Nike did a great job.

Note: This quote, and others in this piece, were made during Tim Cook’s interview at D11.

However, once manufacturers try to put a lot of smarts in a watch, they end up with a product that’s a bulky mess or ugly as sin. Probably both.

Again, Tim Cook has noticed this same thing:

“There are lots of gadgets in the space. I would say that the ones that are doing more than one thing, there’s nothing great out there that I’ve seen. Nothing that’s going to convince a kid that’s never worn glasses or a band or a watch or whatever to wear one. At least I haven’t seen it. So there’s lots of things to solve in this space.”

We all know that Apple’s designers and developers can solve these problems. But can they do it without making compromises?

“It’s an area that’s ripe for exploration, it’s ripe for us to get excited about. Lots of companies will play in this space.”

That exploration is all about saying no a thousand times. It’s easy to create a great looking concept, but turning that fantasy into a product is where it gets hard and compromises are often made.

It’s my view that the technology needed to make that great product that does everything just isn’t there yet. There are too many compromises.

The New Hub

Let’s assume for a second that you can make a compelling device for a wrist. I’d still be asking myself this question: “Why do I need a computer on my wrist?” I already have one in my pocket.

With the introduction of CarPlay, Apple’s answer to this question is becoming clearer. That device in your pocket is the new hub for your digital data. Ben Thompson calls it Digital Hub 2.0.

You don’t need a computer on your wrist. Apple’s wearable devices will become a part of this circle that surrounds your main device. And as with CarPlay, it’s going to be a two-way street where interactions and information in the player make their way back to the main device.

The Fashion

The development of wearable technology is going to enter a space where most companies in the Silicon Valley have no experience. As a geek, do you know who Anna Wintour is and why she would be important to the success of a wearable device?

Angela Arhendts certainly does…

Put aside your geek sensibilities for a second and think about this device as a piece of fashion instead of a cool gadget. What’s the primary function of fashion?

It’s about expressing a personal style. It’s an extension of your personality and way to show it in a public way.

Look at the huge variety of iPhone cases that are on the market. That’s only 16 examples of 4.7 million search results. Fashion is as diverse as the people who wear it.

An important part of this diversity is customer’s gender: men have different tastes than women. That concept watch mentioned above looks fantastic—if you’re a male. I can’t imagine my wife wearing it.

Then there’s the question of size: as someone who’s 6’7″ tall, I know firsthand that “one size fits all” is the greatest lie ever told by clothing manufacturers. Since everyone’s body is unique, wearable devices must also consider comfort and fit in the design.

Apple may be able to use something like an iPhone case to make a wearable device appeal to both sexes. Or adjustments that make a single device (SKU) adapt to multiple body shapes. But I suspect that it’s going to take more than that to be appealing as a piece of fashion.

The Customer

Now that we’ve looked at the challenges in developing these devices, let’s think about the most important question Apple is asking itself:

Who is going to buy this wearable technology?

Trends are always set by the younger generation. Especially with clothing, jewelry and other items that appeal to a demographic with a lot of expendable income. To me, this quote by Tim Cook is the most telling:

“To convince people they have to wear something, it has to be incredible. If we asked a room of 20-year olds to stand up if they’re wearing a watch, I don’t think anyone would stand up.”

This response to Kara Swisher’s question about Apple’s interests in wearable technology covers all the bases. It includes the target market (“20-year-olds”), product focus (“has to be incredible”), and most importantly, he’s seeing the same thing I am: people don’t need to wear watches because they already have that computer in their pocket.

Note also that in the response he doesn’t say “wear a watch”, it’s “wear something”. It’s implied, but not stated. Remember that he learned from the master of misdirection: Steve Jobs.

The Product

Given everything presented above, it’s pretty clear to me that a “smartwatch” isn’t in Apple’s immediate future. But they’re clearly interested in wearable technology. So what are the alternatives for a product that could be released this year?

The first step is to start looking at things from Apple’s point-of-view. I ask myself, “What problems can a wearable device solve?”

As I think about answers to that question, it leads me to the conclusion that Jony Ive and crew aren’t looking solely at the wrist. Wearable technology could take cues from other kinds of jewelry: rings and necklaces, for example.

What if Apple’s entry into this space is a ring?

  • Limited display — A discreet way to provide notifications—just an LED or two that indicate what’s happening on your iPhone. Maybe even a small, flexible E Ink display for high contrast text.
  • Tactile — A way for your finger to sense a notification. It’s easy to miss audio cues in a noisy room or a vibration in your pocket.
  • Small & light — A hallmark of Apple design. Simplicity in form and function.
  • Customer appeal — Those 20-year-olds don’t wear watches, but jewelry is already a part of their culture. “Bling” came from the world of hip hop.
  • Sensors — Your finger has a pulse and blood pressure for Healthbook.
  • Power — The Lightning connector is small for a reason.
  • Competition — While all its competitors are rushing watches to market, Apple catches them with their pants down.
  • Low cost — How many of these rings could Apple sell if they were priced at $99?

But the biggest feature of all would be that this wearable device could support iBeacon. This technology is based on Bluetooth LE which Apple describes as “a new class of low-powered, low-cost transmitters that can notify nearby iOS 7 devices of their presence.”

Let this sink in for a second: your wearable device is transmitting a signal with a unique identifier that can be picked up by an iOS 7 device. And the proximity detection is sensitive within a few inches. Presumably, this signal could be also be detected on your Mac as well, since they have supported Bluetooth 4.0 since mid-2011.

By wearing this ring on your finger, your devices can know how close you are to them.

This opens up a world of possibilities: imagine the joy we’d all feel when a notification only popped up on the device we’re closest to. Right now my ring finger is hovering over my MacBook Air’s keyboard by 2-3 inches, while the phone in my pocket is over a foot away. Notification Center needs this information.


Predicting Apple’s future is always fraught with difficulties. I may not be right about the end result being something other than a watch, but I’m certain that there are people at Apple thinking about the issues I’ve outlined above.

And I, like many others, am really looking forward to wearing Apple.

Font Points and the Web

When sizing fonts with CSS, there’s a rule of thumb that states:

1em = 12pt = 16px = 100%

There are even handy tools that help you calculate sizes based on this rule.

But this rule of thumb leaves out a very important piece of information. And without that information, you could be left wondering why the size of your type doesn’t look right.

Testing Points and Ems

To illustrate, let’s take a look at some work I’ve been doing recently to measure text accurately on the web. I have a simple test page that displays text in a single font at various sizes:

<!DOCTYPE html>
<html lang="en">
  <meta charset="utf-8" />
  <title>Em Test</title>
  <meta name="generator" content="BBEdit 10.5" />
    body {
      font-family: "Helvetica Neue", sans-serif;
      font-size: 100%;
      line-height: 1;
    p {
      padding: 0;
      margin: 16px 0 16px 0;

<p style="font-size: 2em; background-color: #eee;">MjṎ @ 24pt / 2em</p>


You can view a slightly more complex version of the page here.

The W3C recommends specifying fonts using either ems or pixels. Since high resolution displays are becoming ever more common, that really leaves you with just one choice: the em.

(Note: In the examples that follow, I’m using text set at 2em since it’s easier to see the problem I’m going to describe. The effect, however, will happen with any em setting.)

The body is set in Helvetica Neue at 100% so 1em will be the equivalent of 16px when the user’s browser is using a default zoom setting. The line-height is 1 so there’s no additional padding around the text: the default of “normal” would make the line approximately 20% taller.

When you display the test page, everything looks good because the sizes are all scaled correctly relative to each other. A quick check of the light gray background with xScope shows that the height of the paragraph element is 32 pixels (2 ems):


But then things got confusing.

Points aren’t Points

I had just been measuring some text in TextEdit and noticed something was amiss. Comparing the two “24 point” fonts looked like this:

TextEdit versus Browser

I’m no typography expert, but there’s something clearly wrong here: a 24pt font in TextEdit was noticeably smaller than the same size in my web browser.

I confirmed this behavior in three browsers running on my Mac: Safari/Chrome (rendering with WebKit) and Firefox (rendering with Gecko) displayed the larger version of 24 point text. Why were the sizes different?

After some experimentation, it appeared that rendered glyphs were from a 32pt font:

72 DPI

What the hell?

A Brief History of Type

When confronted with a problem like this, it’s always a good idea to question your assumptions. Was I measuring the right thing? So I started learning more about type…

In general, points are meaningless. It’s a relic of the days of metal type where the size specified the height of the metal, not the mark it made on the page. Many people mistake the size of a glyph (shown below with red bars) with the size of a point (green bars):

Point versus Glyph

(Photo by Daniel Ullrich. Modifications by yours truly.)

Even things like the word “Em” got lost in translation when moving to the web: it originally referred to the width of a typeface at a given point size. This worked in the early days of printing because the metal castings for the letter “M” were square. Thankfully, we’re no longer working in the 16th century.

In modern fonts, like Helvetica Neue, a glyph for a capital “M” may be square, but the flexibility of digital type means that the width and height of a point rarely match.

Thanks Microsoft!

After doing this research, I was sure I was measuring the right thing. The sizes of the glyphs should match, regardless of point size. Something else was clearly in play here.

Let’s just say I spent a lot of quality time with Google before eventually stumbling across a hint on Microsoft’s developer site. The document talks about using a default setting of 96 DPI. I’ve been spending a lot of time lately with the Mac’s text system, so I knew that TextEdit was using 72 DPI to render text.

I quickly opened a new Photoshop document and set the resolution to 96 pixels per inch (DPI). And guess what?

96 DPI

All the text got larger and it matched what I saw in my browser. Mystery solved!

72 DPI on the Mac is 75% smaller than 96 DPI used by the Web. So the 24pt font I was seeing in TextEdit was 75% smaller than the 32pt font used in the browser.

Further research about how 96 DPI is used on the web turned up this Surfin’ Safari post on CSS units written by Dave Hyatt back in 2006:

This is why browsers use the 96 dpi rule when deciding how all of the absolute units relate to the CSS pixel. When evaluating the size of absolute units like pt browsers simply assume that the device is running at 96 CSS pixels per inch. This means that a pt ends up being 1.33 CSS pixels, since 96/72 = 1.33. You can’t actually use the physical DPI of the device because it could make the Web site look horribly wrong.

That’s another way to think about this problem: a single point of text on your Mac will be 1.33 times larger in your browser.

Now What?

Now that we know what caused the problem, how can we avoid it?

The key piece of information that’s missing in the “1em = 12pt = 16px = 100%” rule is resolution. If you’re specifying point sizes without also specifying resolution, you can end up with widely varying results. For example, each of these is “24 points tall”:


If you’re lucky enough to have a Retina Display on your Mac, you’ll be rendering text at 144 DPI (2 × 72 DPI). That’s 20% larger than the last example above (Windows’ 120 DPI setting.) Display resolution is increasing and so are the number of pixels needed to represent “a point”.

Note that you can’t “fix” this problem by specifying sizes in pixels. If you specify a font size of 16px, your browser will still treat that as 12pt and display it accordingly.

As a designer or developer, you’ll want to make sure that any layout you’re doing for the web takes these size differences into account. Some apps, like Photoshop, allow you to specify the resolution of a document (that’s how I performed my sizing tests.) Make sure it’s set to 96 DPI. Resolution may not matter for exporting images from Photoshop, but it will make a difference in the size of the text in your design comps.

Most other Mac apps will rely on Cocoa’s text system to render text, so if there’s no setting to change the document’s resolution, a default of 72 DPI should be assumed.

An alternative that would suck is to start doing your design and development work on Windows where the default is 96 DPI. That setting also explains why web browsers use this resolution: remember when Internet Explorer had huge market share?

And finally, expect some exciting new features for measuring, inspecting and testing text in your favorite tool for design and development. I’m doing all this precise measurement for a reason :-)

Updated February 25, 2014: It turns out Todd Fahrner first identified this problem back in the late 1990′s. His work with the W3C was instrumental in standardizing on 96 DPI. What’s depressing is that I knew about this work: Jeffrey Zeldman and I even developed the Photoshop filters mentioned on his site. Maybe I should send in my AARP membership form now.