The New Adventures of Old AppKiDo

I have been making progress on a reboot of AppKiDo, which is a Mac app that I wrote for browsing the Cocoa documentation that comes with Xcode. AppKiDo stopped working in 2014, during the betas of Xcode 6, because of changes in the structure of Apple's docsets.

I now have it up and running again, in a preliminary but usable form. (The code is in a private repository; I will push it to the public one after ironing some things out. [UPDATE: Eh, why wait? The code is public at Remember, it's very much a work in progress.])

The best news, aside from having it run at all, is that it's launching much more quickly than it used to. There's still a lag, but it's much shorter now, because instead of laboriously parsing all the HTML files, I get almost everything I need from the Core Data store inside the docset.

There are serious limitations in the current version that will take time to address:

  • Still Objective-C API only. For example, if you search for "string" the search results won't include the Swift String class.
  • Xcode must be at /Applications/
  • You have to pick the docset you want to browse at launch time.
  • Window states aren't saved between launches.
  • The "ALL" options are missing (as in "ALL Class Methods", "ALL Instance Methods", etc.).
  • And more.

As I write this, the keynote for WWDC 2016 is hours away. For the first time in a long while I am experiencing an old familiar feeling of suspense. Will there be some change to the docs in Xcode 8 that will upend everything I've been doing?

Quick Explanation of the Term "Application Bundle"

Follow-up to my previous post about receipt files. Again, this is Mac-centric.


"Application bundle" is Cocoa developer terminology for an application as it exists in the file system of your computer. The application consists of a number of files organized in a directory. The directory has special attributes and has a specific subdirectory structure.


You only think you see a regular file. When you see an application icon in the Finder, such as the Safari icon, it looks like any other file icon. However, the Finder is telling at least two and possibly three lies about the application.


On the file system, the name of the application is not actually "Safari" (for example) but "", with a ".app" extension.

You can see all the .app extensions in Terminal:

ls /Applications

You can also see an application's filename in the Finder by selecting the application icon and doing a Get Info. You'll see the ".app" extension. Alternatively, if you go to Preferences > Advanced and turn on "Show all filename extensions", you'll see the .app extensions for all apps.


An application is not a regular file, as it appears to be in the Finder, but a directory with special attributes and specific subdirectory structure. Such a directory is called a "bundle".

You can see the subdirectory structure in Terminal:

ls -l /Applications/
ls -l /Applications/

You can also see the directory structure in the Finder by right-clicking the application icon and selecting "Show Package Contents". You will see there is a subdirectory called "Contents", and within that there is a bunch of other stuff.


Usually the Finder displays the name of the application as the directory name minus the ".app" extension. Thus, "Safari" instead of "", "Contacts" instead of "", etc.

However, it is possible for applications to specify a different name to display in the Finder. The main reason for this is to localize the displayed application name. It is very rare to encounter this "lie" if English is your Mac's primary language.

Search for the term "CFBundleDisplayName" for the nuts and bolts of how developers get their apps to do this.

Quick Explanation of the Receipt File

I was explaining the MAS receipt file to a friend and decided to write a blog post instead of an email, on the principle Scott Hanselman has brilliantly advocated that we should conserve and amplify the limited number of keystrokes we have left in us.

I'm purely a Mac developer at the moment, but as far as I know this high-level explanation applies to iOS as well. No idea about watchOS.


The receipt is a file on your computer used for DRM of purchases from the App Store. There is a separate receipt for each app.

The receipt file contains:

  • Identifying information about the computer on which the app is installed — specifically, the MAC address of the device's primary network interface. Note that "MAC address", with the "MAC" in all caps, is a networking term. Nothing to do with "Mac" as in "Macintosh".

  • Identifying information about the app that the receipt is for — specifically, the app's bundle ID and version number.

  • Purchase history. Information about the app purchase and any subsequent in-app purchases.


The receipt file is located inside the application bundle. On the Mac, it is at Contents/_MASReceipt/receipt. (If you don't know what the application bundle is, I've written another quickie blog post explaining it.)


The system is responsible for creating the receipt. By "system" I mean the OS in conjunction with the App Store. The system code-signs the receipt to prevent tampering. It's the job of Apple's developers to have gotten this right.

The application is responsible for validating the receipt. It's the job of the app developers to get this right.


The receipt gets created on your computer when you download the app from the App Store. The receipt is then updated in the following situations:

  • If a newer version of the app becomes available on the App Store, the receipt is updated when you upgrade to the newer version.

  • If the app supports in-app purchases, the receipt is updated whenever you do an in-app purchase.

  • When you "Restore Purchases", the receipt is updated.

Here's what I mean by "Restore Purchases". Certain types of in-app purchases apply to all computers on which you have installed the app, not just the computer on which you made the purchase. A typical example would be an IAP that unlocks premium features. If you made such a purchase on a different computer, you may need to explicitly "restore" that purchase on the computer you are using. Apple's App Store rules require the app to provide a way for you to do this. Usually the app provides a button or menu item with a name like "Restore Purchases".


The application does two things with the receipt:

  • It validates the file contents to confirm the receipt hasn't been tampered with.

  • It checks in-app purchases to see what enhanced functionality the user has purchased. In-app purchases may include permanent "unlocking" of features, or they may be subscription-based, in which case the app should check the expiration dates of the subscriptions.

Both of these steps are performed by parsing the receipt file, which is a science in itself. There's an excellent article on that explains what is required:

You may wonder why Apple hasn’t provided a simple API to validate the receipt. For the sake of demonstration, imagine that such a method exists (for example, [[NSBundle mainBundle] validateReceipt]). An attacker would simply look for this selector inside the binary and patch the code to skip the call. Since every developer would use the same validation method, hacking would be too easy.

Instead, Apple made the choice to use standard cryptography and encoding techniques, and to provide some help — in the form of documentation and WWDC sessions — for implementing your own receipt validation code. However, this is not an easy process, and it requires a good understanding of cryptography and of a variety of secure coding techniques.

Of course, there are several off-the-shelf implementations available (for example, on GitHub), but they are often just reference implementations and suffer from the same problem outlined above if everybody uses them: it becomes very easy for attackers to crack the validation code. So it’s important to develop a solution that is unique and secure enough to resist common attacks.


Some Ways I Use Keyboard Maestro

Today, thanks to Michael Tsai, I found out there's a major new release of Keyboard Maestro. I use Keyboard Maestro all day long, and look forward to checking out the upgrade when I have time.

Here are some ways Keyboard Maestro makes my day go much more smoothly:

  • I use the palette feature to navigate to frequently used apps and documents in exactly two keystrokes.

  • I have a "Preferred Window Frame" macro that sets the active window's size and position. My preferred frame varies from app to app, and the macro does the right thing depending on which app is active. Just one keystroke to remember. The macro invokes keyboard shortcuts I've configured in Divvy, but I could also have entered window coordinates directly into Keyboard Maestro.

  • I map ^P/^N to UpArrow/DownArrow so I can use those emacs keys to go up and down in lists, menus, and other places outside of text editing. The ^P/^N keys already work in many apps, but not all, and not in all places within the same app. By setting up this global mapping, I don't have to remember where they work and where they don't.

  • You can create text expansion macros. I have macros for inserting date and time, for a few phrases I type on a regular basis, and for emoji characters. I was happy using Keyboard Maestro for all this but recently moved my text expansion macros to aText, a very nice app at a very reasonable price. My reasons for switching were minor and arguably not worth the time when I had a perfectly good solution. I wouldn't and perhaps shouldn't have bothered, except I am such an obsessive yak shaver.

  • I sometimes use Keyboard Maestro instead of System Preferences to provide alternate menu shortcuts. I do this because Keyboard Maestro syncs my macro definitions on Dropbox, which means that when I make a change, all my Macs automatically get it.

  • I open Xcode's Recent Files menu with one keystroke (I use ^R) instead of three (^1, DownArrow, RightArrow).

  • I have a scratch macro named "Pipe Text" that replaces the currently selected text by piping it through a shell script and pasting the result. The macro has an "Execute Shell Script" action that I edit to do what I have in mind, typically a grep.

  • I keep a personal log in the form of daily text files. I have a macro that opens today's log file in BBEdit, after creating the file if necessary. I use this throughout the day whenever I think of something to add to the file.

I'm happy to share how I do any of the above.