Start Screen Sharing or Apple Remote Desktop Sessions with Spotlight

Screen Sharing is a really useful tool in Mac OS X. Most people use it locally and select the Computer from the Sharing area in the Finder sidebar. You can also connect Screen Sharing to a remote host. In Finder select “Connect to Server” from the “Go” menu and enter


which will connect Screen Sharing to the address.1

You could add the vnc URI to the favorites in the “Connect to Server” dialog, but there is a better way: Screen Sharing remembers the last connections in ~/Library/Application Support/Screen Sharing/. There you will find the hosts you have connected to as .vncloc files. Find the host(s) you use most frequently and copy them to the Desktop or your Documents folder.2 Then rename them to just the hostname or another descriptor. You can now double-click to initiate the Screen Sharing connection. But even better: you can invoke Spotlight, start typing the hostname and the vncloc file should be right there. No matter what you are doing the remote session is just a few keystrokes away.

However, if you prefer to use Apple Remote Desktop over Screen Sharing, this will not work. ARD does not open vncloc files. However, ARD is scriptable, so we can build a workaround. Even better ARD supports Automator, so we don’t even need to write code.

  • open Automator. From the template chooser, select “Application.”
  • add the action “Choose Remote Computer” and select a computer to connect to.3
  • add the “Observe Computers” action next.4
  • you’re done. Save this Automator applet and give it the name of the computer.
  • you can start this applet by starting to type the computer’s name in Spotlight and you will a remote observe session in Remote Desktop.

Create more applets for each host you frequently use. if you select multiple computers in the first action, you will get the nice “multi observe” window in Remote Desktop. Or you can replace the “Choose Remote Computers” action with a “Choose Computer Lists” action.

  1. It will use VNC on TCP port 5900 in case you have connection issues.
  2. anywhere Spotlight will index
  3. The computer has to be already known to the local Remote Desktop to appear in this list.
  4. curiously enough there is no “Control Computers” action, but switching from observe to control is only a single click. This may be so you cannot accidentally invoke a remote control session.

Speak Instapaper Posts — Part 1

I saw this in my Twitter stream the other day:

You know what I want? A text-to-speech plugin for @instapaper so, while commuting to/from work, I can listen to the stuff I find at work.

— @seankaiser

That shouldn’t be too hard, shouldn’t it?

First we have to get the unread articles from Instapaper. If you go instapaper, log in, and go to your unread articles, you can see the RSS button in the URL field in Safari. To get to the RSS feed in Automator, do the following:

  • Open Automator, create a new Workflow
  • Open in Safari and drag the link from the URL bar to the empty Automator Workflow window. Automator will create an new “Get Specified URLs” action with the Instapaper URL unread in it
  • Add a “Get Feeds from URLs” action next
  • Add a “Get Link URLs from Articles” action. Unselect the “only in the same domain” option
  • Finally add the “New Safari Documents” action.
  • The workflow already does something useful. Save as “Open unread Instapaper articles”

If you ares anything like me this workflow will open quite a large number of pages. I think Instapaper limits the RSS feed to 25. That’s still a lot of new Safari tabs/windows you are opening there. We want to add an action that restricts the number of items passed through it. Surprisingly there is none in the default actions, but this is fairly easy to add. Insert a new “Run AppleScript” action before the “New Safari Documents” action and replace the default code with the following:

on run {input, parameters}
	set maxNum to 3
	-- filters all but the first maxNum items from the articles, change as appropriate
	-- enter '-1' or remove this action entirely to get all urls
	if (count of input) > maxNum then
		set output to items 1 through maxNum of input
		set output to input
	end if
	return output
end run

This will only pass through the first maxNum of items passed into it, regardless of type. You can change maxNum to fit your taste and/or needs. You can also set maxNum to -1 if you want to pass all items without removing the AppleScript action.

Save again and try running it. The next step will be to filter the actual text out of the web page which will be a little tougher and the main topic of Part 2.

Dropbox Now Syncs Extended Attributes

Extended Attribute Sync – Syncing resource forks have historically been a pain for Mac users. In case you don’t know, resource forks are a secret area of a file that certain applications like Quicken, Quark, and OmniGraffle use to store important data. Most sync programs today completely ignore these forks, which results in a corrupted file on the other end. But worry not! Resource forks and other extended attributes now work great with Dropbox. Hooray!

via The Dropbox Blog » Blog Archive » Dropbox hits 1.0!.

This is great news. I use Dropbox to sync my ~/Library/Scripts and ~/Library/Services folder across multiple computers.1

While AppleScript files usually work, some Automator Workflow files store extra information in extended attributes and those would break when syncing. Now with the latest version of Dropbox things work fine.

If you don’t use Dropbox yet, you should try it. You can support a little by signing up to Dropbox through this link, then both you and me will get some extra free storage space.

  1. the way I do that is to move all scripts and/or workflows I want to sync to ~/Dropbox/Scripts or ~/Dropbox/Services and replace the actual folder in ~/Library with a symlink: ln -s ~/Dropbox/Scripts ~/Library/Scripts

Shell Loop Interaction with SSH

If you have a bash script with a while loop that reads from stdin and uses ssh inside that loop, the ssh command will drain all remaining data from stdin1. This means that only the first line of data will be processed.

I encountered this issue yesterday2. This website explains why the behavior occurs and how to avoid it.

A flawed method to run commands on multiple systems entails a shell while loop over hostnames, and a Secure Shell SSH connection to each system. However, the default standard input handling of ssh drains the remaining hosts from the while loop

from Shell Loop Interaction with SSH.

  1. This is not only true for ssh but for any command in the loop that reads from stdin by default
  2. I won’t go into details here, since it is for a very specialized purpose. I will say that it involved jot, ssh, an aging Solaris based network appliance, and some new fangly XML/Web 2.0

Automatically connect to Airfoil Speakers

Update: In one of those embarrassing “You know there is a checkbox for that!?” moments, @rogueamoeba points out there is in fact a checkbox for this under Preferences “Automatically Transmit To:”

Airfoil from Rogue Amoeba is a wonderful application that allows you to stream audio from your computer to any device that will receive Airplay audio or run the Airfoil Speaker application. This includes all iOS devices. I use it stream audio to any room I may be in where I just hook an iPod touch or the iPhone up to the stereo.

The one drawback is the UI, which only allows to the devices to stream to on the Mac that is streaming. So I’ll be in the kitchen, where a 1G iPod touch is permanently hooked up to some speakers, turn on the iPod touch, start the Airfoil speakers app, then walk to the Mac in the living room, select the iPod touch in the Kitchen and walk back to enjoy the music. Wouldn’t it be great if Airfoil automatically picked up the iPod when it appears in the list?

Luckily Airfoil has AppleScript support. It is actually very easy. I have named all my iOS device to start with either “iPhone”, “iPad” or “iPod touch” so I can make Airfoil connect to all devices that are running the Airfoil app with

tell application "Airfoil"
    connect to every speaker whose name starts with "iP"

Now we need to keep running this command periodically in the background. I could setup a launchd plist for that, but AppleScript provides a simpler solution. Scripts that are saved as “Stay Open Applications” have an idle handler that is called after a certain number of seconds. See the details at the AppleScript Language Guide here.

So we wrap the command in an idle handler and add some checking to see if Airfoil is running so we don’t force launch Airfoil:

property idleTime : 30 -- in seconds

on run
	idle -- call idle on launch
end run

on idle
	tell application "System Events"
		if exists application process "Airfoil" then -- check if Airfoil is running
			tell application "Airfoil"
				connect to (every speaker whose name starts with "iP" and connected is false)
			end tell
		else -- if Airfoil is not running script can quit, too
			tell me to quit
		end if
	end tell
	return idleTime
end idle

The value returned from the idle handler is the time (in seconds) until it gets called again. This will leave other speakers (that don’t start with “iP”) such as the local speakers and any Airport Express speakers unaffected.

Save this as an application and make sure to select the “Stay Open” option. Then find the application and double click to launch. Start and quit Airfoil speakers app on your iOS devices and listen to Airfoil connect automatically.