Keyboard Maestro, Shortcuts and the Services menu

Published on by Geoff Taylor

I’ve used Shortcuts on iOS since the Workflow days, but I haven’t been motivated to explore Shortcuts on macOS. For Mac automations, I rely mainly on Keyboard Maestro. Recently, I was sitting in front of my Mac when I had an idea for an iPhone shortcut, so I decided to go ahead and build it in the Shortcuts app for Mac. That’s when I discovered a fantastic feature of Shortcuts on macOS: You can add a shortcut to the Services menu. A shortcut can run Keyboard Maestro macros, so this is roundabout way of adding Keyboard Maestro macros to the Services menu.

At work, I’m often logged into our SaaS application in different browsers using different accounts. When I’m testing email notifications and the email contains a link, I need to be sure to open the link in the right browser. My previous solution to this was a set of Keyboard Maestro macros, each one set up to open a copied link in a specific browser. If I needed to open a link in a browser that wasn’t my default, I would copy the link and press the hotkey for that browser’s macro.

If you right-click a link and select a shortcut from the Services menu, the shortcut receives the link as input. I updated my macros to use the shortcut input (accessible in Keyboard Maestro as %TriggerValue%) instead of the clipboard. Since Chrome is my default browser at work, I have shortcuts for Safari, Firefox and a Chrome incognito window. The shortcut naively checks that the input is a valid URL (it just has to start with “http”), and then calls the corresponding macro, passing the URL to it. Now all I have to do is right-click the link and select the appropriate shortcut to open the link in a specific browser.

To make these shortcuts useful to a wider audience, I also made versions that don’t rely on Keyboard Maestro. The non-Keyboard Maestro version of the Safari shortcut uses the Open URLs action in Shortcuts. The shortcuts for the other browsers use AppleScript. Even though I don’t need a shortcut for Chrome, I created one to share here. You can download the shortcuts and macros at the bottom of this post. (Although I thought I had tested it successfully, the non-Keyboard Maestro version of the Chrome incognito shortcut doesn’t work. Shortcuts apparently isn’t allowed to send keystrokes via AppleScript, so there’s no way that I know of to open a Chrome incognito window via Shortcuts.)

The first time you run one of the shortcuts, you’ll see a popup asking for permission to open the URL using the shortcut. Click Always Allow to permit the shortcut to open any URL in the future.

Shortcuts privacy popup
Shortcuts privacy popup
Shortcuts in the Services menu
Shortcuts in the Services menu
Shortcut to open a URL in Safari using the Open URLs action
Shortcut to open a URL in Safari using the Open URLs action
Shortcut to open a URL in Safari using Keyboard Maestro
Shortcut to open a URL in Safari using Keyboard Maestro
Keyboard Maestro macro to open a URL in Safari
Keyboard Maestro macro to open a URL in Safari
Shortcut to open a URL in Chrome using AppleScript
Shortcut to open a URL in Chrome using AppleScript

Downloads

Shortcuts

Keyboard Maestro macros

Bunch, AppleScript and Excel

Published on by Geoff Taylor

I work in a professional services job, and most of my time is billable to client projects. Our web-based time tracking software is a little bit inconvenient to use, so I track my time in an Excel spreadsheet throughout the day and enter it in my timesheet at the end of the day. (And since Excel is doing the math, I know I have an accurate accounting of my time, free of the inevitable calculation errors I would make.) The spreadsheet looks like this:

I keep one spreadsheet for each week in a folder structure like this: ~/Documents/Time/<Year>/<Month>.

The nature of time tracking, at least in my case, is that it’s necessary but tedious work with little opportunity for automation. However, I saw a couple of obvious opportunities for automation in this system: creating the weekly spreadsheet and opening it to the correct worksheet every day. I use Bunch to open my usual apps and perform some other setup tasks when I log in to my MacBook in the morning, so I just added this to the same Bunch file.

Step 1: Create the weekly file if it doesn’t exist

I keep a template in ~/Documents/Time/Time.xlsx, so each week I just need to copy that file to the appropriate directory and give it the correct name. This is easily accomplished with a shell script that I named time.sh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/bin/zsh

TIME_DIR="$HOME/Documents/Time"
EXCEL_TEMPLATE="$TIME_DIR/Time.xlsx" # Template for the weekly Excel file

# Get the year and month of the most recent Monday (the Monday of the current week).
# This will be the directory where the current week's file is stored.
YEAR_MONTH=$(date -v -Mon "+%Y/%m")

# Year and month subdirectory, e.g., $HOME/Documents/Time/2022/01
MONTH_DIR="$TIME_DIR/$YEAR_MONTH"

# Get the month and day of the most recent Monday (the Monday of the current week)
# and construct the file name of the weekly file.
WEEKLY_FILE=$(date -v -Mon "+Week of %m-%d.xlsx")

if [ ! -d "$MONTH_DIR" ]; then
   # Create $MONTH_DIR if it doesn't exist.
   mkdir -p "$MONTH_DIR"

   # If $MONTH_DIR doesn't exist, we know the file for this week doesn't 
exist,
   # so we need to create it by copying $EXCEL_TEMPLATE.
   cp "$EXCEL_TEMPLATE" "$MONTH_DIR/$WEEKLY_FILE"
else
   # $MONTH_DIR exists. # Create $WEEKLY_FILE if it doesn't exist.
   if [ ! -f "$MONTH_DIR/$WEEKLY_FILE" ]; then
     cp "$EXCEL_TEMPLATE" "$MONTH_DIR/$WEEKLY_FILE"
   fi
fi

# Run AppleScript script to open the file to today's worksheet.
/usr/bin/osascript "$HOME/Documents/Bunches/OpenTimeSheet.scpt" "$MONTH_DIR/$WEEKLY_FILE"

exit

The line YEAR_MONTH=$(date -v -Mon "+%Y/%m") gets the year and month of the most recent Monday in the format YYYY/MM. The $MONTH_DIR variable is then set to the current month’s directory, for example ~/Documents/Time/2022/02. (It’s really the month of the most recent Monday, which could be the previous month when a week crosses a month boundary.) Then the $WEEKLY_FILE variable is set to the string Week of MM-DD.xlsx, where MM and DD are the month and day of the most recent Monday.

Next the script checks for $MONTH_DIR and creates it if it doesn’t exist. If $MONTH_DIR does exist, the script checks for $WEEKLY_FILE and creates it if it doesn’t exist.

Step 2: Open the file to today’s worksheet

As the final step, the shell script runs an AppleScript script that opens the file and activates today’s worksheet:

/usr/bin/osascript "$HOME/Documents/Bunches/OpenTimeSheet.scpt" "$MONTH_DIR/$WEEKLY_FILE"

This is the AppleScript script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
on run argv
	set inputPath to item 1 of argv
	set filePath to POSIX file inputPath
	set currentDate to (current date)
	set today to (weekday of currentDate) as string
	
	if (today  "Saturday") and (today  "Sunday") then
		tell application "Microsoft Excel"
			open filePath
			set ws to worksheet today
			activate object ws
		end tell
	end if
end run

This script takes the path to this week’s spreadsheet as input. The shell passes the path to AppleScript ($MONTH_DIR/$WEEKLY_FILE). AppleScript gets the path (line 2) and converts it to a POSIX file object (line 3). (The input is the path as a string, which AppleScript can’t work with unless it’s converted to a file object.) Next it gets the weekday of the current date (lines 4 and 5). Then it tells Excel to open the file (line 9) and activate the worksheet with the same name as the current day (lines 10 and 11). (Since the file doesn’t normally contain worksheets for Saturday and Sunday, I added the check in line 7 just in case I log in to my work laptop on the weekend.)

All of this could’ve been done in AppleScript, but the shell is much more efficient at working with files and folders, so I decided to let the shell handle everything except opening the Excel file to the correct worksheet (which only AppleScript can do).

Step 3: Automate it with Bunch

I have a bunch called main.bunch that performs my daily setup, so I added this to that file:

1
2
# Open weekly time file in Excel.
$ time.sh

This just runs time.sh every time the bunch runs.

Sidecar script updated for Monterey

Published on by Geoff Taylor

I updated my Sidecar script for macOS Monterey. You can find the latest release on GitHub.

Update to Sidecar script

Published on by Geoff Taylor

I updated the Big Sur version of my Sidecar script so that it correctly toggles Sidecar. If Sidecar isn’t connected, running the script will connect it. If it’s connected, running the script will disconnect Sidecar. This was working in the original Catalina version, but for some reason I omitted it when I updated the script for Big Sur.

Since I’ll probably have to update the script for each new macOS version, I moved it to a GitHub repository, where you’ll find the source and downloadable zip files.

Playlist backup script updated for Big Sur

Published on by Geoff Taylor

I updated my script to backup Music playlists for Big Sur. There are two versions now: one for Catalina and one for Big Sur. Both versions are available in the GitHub repo.