Duplicating Safari browsing sessions between Macs

Hey, you’re just in time for another “stupid trick of the day” script. I have good reason for this one, and it only took me about 8 minutes to set up. It will take me longer to write about it than it’s probably worth, but it might be of use to anyone in a similar situation. Here’s the scenario:

I bought a MacBook Air recently. I have never been this happy with an Apple hardware purchase before. Not to gush, but I’ve bought and loved a lot of Macs and this one takes the cake. I’m doing more and more of my everyday work and writing on it, but I still like to sit down at the dual-monitor setup of my Mac Pro fairly regularly. When I do that, the Air becomes an auxiliary machine and I offload most of my chat and social apps to it. The annoying side of this setup is that I end up with Safari tabs piling up on both Macs, and half of them really make more sense on the other machine.

I wrote a pair of scripts that execute over SSH to pull in all of the browser tabs from the front window of Safari on the other Mac into new tabs on the one calling the script. They’re designed to run on Macs on the same network, though they’d work remotely if you could think of a reason to do it. I run it in both directions, and call it with a simple do shell script AppleScript in ~/Library/Scripts/Applications/Safari so it’s in my menubar when I’m browsing.

Just a few prerequisites:

  1. You need keyless ssh set up between the two (or more) Macs. If you want a two-way sync, you need keys in both directions. This article has everything you need.
  2. To keep things simple, set up a ~/.ssh/config file on each machine you want to pull tabs to. Create the file if you don’t have one, or add this at the bottom of an existing one, modifying it for your setup:

host air
  HostName computername.local
  User remoteusername

Now you can just install the scripts, edit one line on each and start pulling tabs back and forth between computers.

remotetabs.rb

This goes on the machine you want to pull from. If you’re going both directions, you’ll want both scripts on both machines. Easy enough, right? Save this one as remotetabs.rb in ~/scripts/ and run chmod a+x ~/scripts/remotetabs.rb. Note that it doesn’t attempt to do any error reporting, it just fails silently or times out if there’s a problem. You’ll know something went wrong, you just won’t know what. It’s mysterious, enjoy it.

Because I often run Webkit, and because Webkit demands that it be addressed separately from Safari, there’s a quick check in here to see which one is running at the time.


#!/usr/bin/ruby

def app_running?(app)
  not `ps ax|grep -i "#{app}.app"|grep -v grep`.empty?
end

def webkit_running?
  return false if `ps ax|grep -i "Safari.app"|grep -v grep`.empty?
  not `ps ax|grep -i "/Applications/Webkit.app"|grep -v grep`.empty?
end

if app_running?("Safari")
  browser = webkit_running? ? "Webkit" : "Safari"
  urllist = %x{osascript <<-APPLESCRIPT
               tell application "#{browser}"
               set _tabs to every tab of window 1
               set _urls to {}
               repeat with _tab in _tabs
               set end of _urls to URL of _tab
               end repeat
               set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, " "}
               set output to _urls as text
               set AppleScript's text item delimiters to astid
               return output
               end tell
               APPLESCRIPT }.chomp
  puts urllist
end

getremotetabs.rb

This goes on the machine that’s doing the “pulling.” Save it as getremotetabs.rb in ~/scripts/ and run chmod a+x ~/scripts/getremotetabs.rb. You need to edit the remote_host variable in this script on each machine to match the hostname you set up in your ~/.ssh/config file for the ‘other’ Mac.


#!/usr/bin/ruby
# retrieves a list of urls from the front Safari window running on a remote machine

remote_host = 'air' # as set up in ~/.ssh/config with nick and keyless login

%x{ssh #{remote_host} ~/scripts/remotetabs.rb}.chomp.split(' ').each { |url|
  %x{osascript -e 'tell application "Safari" to open location "#{url}"'}
}

That’s it. You can save an AppleScript with do shell script "/Users/username/scripts/getremotetabs.rb" anywhere you want to, or just call the script from the command line. Also, stop making fun of my OSD. I mean it.

Brett Terpstra

Brett is a writer and developer living in Minnesota, USA. You can follow him as ttscoff on Twitter, GitHub, and Mastodon. Keep up with this blog by subscribing in your favorite news reader.

This content is supported by readers like you.

Join the conversation