I am currently in the midst of radically changing the OS X experience at my company. Users will be going from monolithic/unmanaged to a self-service/managed model. This could be jarring for them and without proper user training, they could easily miss some of the key features we would like them to know about.

Enter Yo. Written by Craig Shea and utilizing Swift, it allows you to target Notification Center.

By utilizing Outset, Luggage, and Yo, we can create a user login condition that will notify the user of available documentation.

Yo Screenshot

Let’s begin…

On a test machine, install the latest versions of Luggage, Outset and Yo. It will help to have Pages, Xcode and the Xcode command line tools as well.

Create a working directory. When playing with things like this, I prefer the desktop. Let’s open terminal.

mkdir -p ~/Desktop/YoExample

If you have Pages, go ahead and make a document, export as a PDF and save it to our working directory. In this example, let’s use yo.pdf.

Pages Screenshot

Outset is a powerful tool that allows you to run packages/scripts at various stages. Let’s create a script and save it in our working directory. Outset requires that your scripts contain the proper extension, so don’t forget it.

Once again in terminal:

cd ~/Desktop/YoExample
nano yo.sh

This will bring up a command line editor called nano. Nano is a replacement for pico and recommended by Apple for modifying configuration files.

Inside nano let’s copy/paste the following:

	-t "Yo is awesome" \
	-s "To view the document" \
	-n "Please click on Open PDF" \
	-b "Open PDF" \
	-a "/Library/Documentation/Yo.pdf" \
	-p \
	-z "sms_alert_note"

Once entered, press ctrl+o to write the file. It will confirm the name you previously entered - hit enter to save. If done correctly, you should now have a bash script file located in your working directory.

Craig has some great documentation. Let’s look at the values we have setup.

-t, --title:
Title for notification. REQUIRED.
-s, --subtitle:
Subtitle for notification.
-n, --info:
Informative text.
-b, --action-btn:
Include an action button, with the button label text supplied to this argument.
-p, --poofs-on-cancel:
Set to make your notification 'poof' when the cancel button is hit.
-a, --action-path:
Application to open if user selects the action button. Provide the full path as the argument. 
This option only does something if -b/--action-btn is also specified. Defaults to opening nothing.
-z, --delivery-sound:
The name of the sound to play when delivering. Usually this is the filename of a system sound minus the 
extension. See the README for more info.

We are going to have a title, subtitle and informative text. For a little flair, we will have the notification “poof” if a user hits cancel. By pointing to a private framework sound, we can also use the same alert that a user will hear when receiving an iMessage (located at /System/Library/PrivateFrameworks/ToneLibrary.framework/Versions/A/Resources/AlertTones/Modern/). The action path itself can point to anything and invokes the open command. The options are endless.

If you are paying attention, you’ll notice this script is pointing to /Library/Documentation/yo.pdf. How might one get this file to this location? You could manually move it for this test or build a pkg with Packages, but let’s take a slightly different approach.


Enter Luggage, a great tool that doesn’t seem to get a lot of blog posts. For this post we won’t go too in depth, but let’s do a quick overview.

Luggage allows you to easily create a package, based on a set of parameters through the use of a Makefile.

Let’s use nano once again to make our file.

cd ~/Desktop/YoExample
nano Makefile

Copy/paste the following code and save it.

include /usr/local/share/luggage/luggage.make
		pack-usr-local-outset-login-once-yo.sh \

l_usr_local_outset_login_once: l_usr_local
	@sudo mkdir -p ${WORK_D}/usr/local/outset/login-once
	@sudo chown -R root:wheel ${WORK_D}/usr/local/outset/login-once
	@sudo chmod -R 755 ${WORK_D}/usr/local/outset/login-once

pack-usr-local-outset-login-once-%: % l_usr_local_outset_login_once
	@sudo ${INSTALL} -m 755 -g wheel -o root "${<}" ${WORK_D}/usr/local/outset/login-once

l_Library_Documentation: l_Library
	@sudo mkdir -p ${WORK_D}/Library/Documentation
	@sudo chown root:admin ${WORK_D}/Library/Documentation
	@sudo chmod 775 ${WORK_D}/Library/Documentation

pack-Library-Documentation-%: % l_Library_Documentation
	@sudo ${INSTALL} -m 644 -g admin -o root "${<}" ${WORK_D}/Library/Documentation

Let’s briefly discuss what we are doing here. l_usr_local_outset_login_once tells Luggage to make the directories for Outset (if they don’t already exist) and ensure proper permissions. l_Library_Documentation does the same thing for our Documentation folder.

pack-usr-local-outset-login-once tells Luggage to install our script into the correct Outset folder (calling the l_usr_local_outset_login_once) and pack-Library-Documentation installs our PDF.

With our Makefile in hand, let’s generate our pkg file.

In terminal type:

make pkg

Luggage will ask you for your password. If everything goes right, a package will be generated in your working folder called YoDocumentationExample-1.0.pkg and terminal will look something like this.

Please note that Luggage is very particular with tab spacing and it is possible that wordpress will strip them. See the bottom of the post for the actual files.

Luggage Screenshot

With your package in tow, install it, reboot (or logout) and log back in to see your notification appear.

Yo Example

If you click on Open PDF, you should see something like this:

Yo Example2

Great! You have a fully functioning setup for all users, and a deployable package. You can stop here but what if you want more?

What if you want to change the icon on the alert? For this, we will need to download the source files and modify them in Xcode. Back in terminal let’s use git to clone Craig’s github repository. Make sure you have already installed Xcode and the command line tools prior to running this command or it will fail.

cd ~/Desktop/YoExample
git clone https://github.com/sheagcraig/yo.git

Browse to your YoExample folder, and a new folder called yo will now exist. Double click on yo.xcodeproj to open the project in Xcode.

Expand the root yo folder, the sub folder called yo and the Supporting Files folder. Click on Images.xcassets and then click on AppIcon. Drag and drop any PNG image (size 128x128) into the Mac 128pt 1x area and replace the original icon. Here is a great icon you could use.


Xcode 1

Now that we’ve replaced the icon, let’s change the BundleIdentifier to ensure our new icon will take effect. Click on Info.plist and change the bundle identifier to something you see fit. In this example let’s use com.github.erikng.

Xcode 2

With our changes made, let’s save the project (CMD +S) and build our project (CMD+B).

By default Xcode saves projects to ~/Library/Developer/Xcode/DerivedData. Once there, you should find a folder called yo-xxxxxxxxx. Expand that folder and continue down the rabbit hole. ~/Library/Developer/Xcode/DerivedData/yo-xxxxxxxxx/Build/Products/Debug

You should see an application bundle with your new (awesome) icon. Copy this bundle to our original working folder ~/Desktop/YoExample.

Have I told you how awesome Luggage is? It’s awesome. Let’s change the payload section of our Makefile. Using nano or your favorite text editor, change the payload section to the following:

		pack-usr-local-outset-login-once-yo.sh \
		pack-Library-Documentation-yo.pdf \

Once again in terminal browse to your working directory and make pkg.

cd ~/Desktop/YoExample
nano Makefile

Your package will regenerate and now include your customized application. Install the new package, log out and log back in and your notification should re-appear, but look different.

Yo Notification

Congrats! You now have a customized notification that will appear for all of your users and a package you can deploy out with your favorite deployment tool.

If you’d like to use my own example go here for all the necessary files.

Table Of Contents