I have to use a Mac at work, so I have been slowly replicating my i3 workflows on macOS using a combination of tools such as yabai, skhdc, Karabiner-Elements.

The latest addition to my toolbox is a macOS/yabai version of my dmenu-based window switcher, which I previously wrote about. I particularly felt the need for this when I had many instances of my editor open in a single workspace in the stacked layout. On i3, the presence of a title bar simplifies window navigation in the stacked mode:

i3 stack navigation

However, yabai’s stacked layout lacks title bars or any indicators. I first tried to find a replacement and that led me to a Hammerspoon plugin called stackline. Unfortunately, it was buggy, slow, and is no longer maintained. So Instead I came up with the simple script below:

#!/usr/bin/env bash

windows=$(yabai -m query --windows)
idx=$(echo "$windows" | jq -r '.[] | "\(.app): \(.title)"' | dmenu -i)

if [[ $idx -ge 0 ]]; then
    echo "$windows" | jq ".[$idx].id" | xargs yabai -m window --focus
fi

This script pipes the list of open windows names and titles into dmenu for interactive selection. Notably, dmenu is not available on macOS, so in this case, it is a placeholder to make sure my various scripts work across Linux and macOS. Under the hood, it is a shell script that passes stdin to choose, a dmenu-like application on macOS:

choose -u -b fabd2f -c 427b58 -s 14 -n 15 "$@" <&0

choose is nowhere near as fast or elegant as dmenu, or rofi, but it gets the job done:

yabai stack navigation

The only dependency (besides investing in yabai) is jq for parsing JSON outputs.