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

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.