pseudoyu

pseudoyu

Blockchain | Programming | Photography | Boyi
github
twitter
telegram
mastodon
bilibili
jike

Automate window management with a macOS window management system based on yabai+skhd

Introduction#

Since I saved up to buy my first MacBook Pro during the summer of 2017, I have been using macOS for five years. As my work and study needs grew, I gradually started using a multi-screen workflow. Because I often need to open many windows, such as IDEs, text editors, terminals, IM software, email clients, etc., it can get messy quickly if I'm not careful, and I have to keep switching to find the window I need, which is quite inconvenient. Thus, I began my exploration of window management solutions.

Window Management Requirements#

First, I sorted out my window management needs and listed the following core points:

  1. Automatically perform intelligent split-screen on the current desktop after opening a new window, such as full screen for a single window, half for two windows, and so on.
  2. Adjust or restore the split-screen layout using keyboard shortcuts.
  3. Jump between different windows using keyboard shortcuts.
  4. Move/swap different window positions using keyboard shortcuts.
  5. Easily perform some operations on the current window using keyboard shortcuts, such as full screen, centering, sending to a specific desktop, etc.
  6. Fast switching speed.

Based on these requirements, I started researching several popular window management tools.

Window Management Tools#

There are already many relatively mature window management tool solutions on the market, such as Magnet and the window snapping feature of BetterTouchTool. I have purchased and used them, but overall, I still feel they are not quite suitable for my workflow.

Magnet mainly relies on keyboard shortcuts. Although you can customize shortcuts to fit your habits, the memory cost is high, and if you have multiple devices, you need to download and reconfigure it with your account, which is inconvenient.

magnet_keyshotcuts

BetterTouchTool relies on moving the mouse to various trigger corners of the window. Its advantage is that you don't need to set your own shortcuts; just move the mouse to the window edge to achieve split-screen. However, like Magnet, it has the same drawback: after opening a new window, you still need to manually implement the split-screen, which can often be forgotten when busy or with many windows, making it inconvenient to manage.

bettertouchtool_setting

Since existing software could not fully meet my needs, as a tinkerer programmer, I turned my attention to some highly customizable solutions in the open-source community.

Open Source Solutions#

Hammerspoon#

Hammerspoon is a powerful macOS automation tool that allows you to implement window management functions by writing some lua scripts and customizing keyboard shortcuts. In addition to window management, it can also implement various features such as sleep control and clipboard tools. After using it for a while, I found that, similar to Magnet, it could not effectively achieve intelligent split-screen (perhaps there are pre-written scripts, but they require individual configuration for many software, which is quite troublesome), so I abandoned it.

yabai + skhd#

After some research, I found a solution from YouTuber Josh Medeski in his video <Blazing Fast Window Management on macOS>. It is open-source, free, and highly customizable, requiring only a configuration file to perfectly meet all my needs.

yabai#

yabai is an open-source extension of macOS's built-in window management tool that allows free control of windows and multiple displays through command-line tools. Its main feature is using the binary space partitioning algorithm to automatically modify window layouts, allowing us to focus on window content without needing to manage them actively; just open the corresponding software window, and it will automatically arrange itself, without disrupting the workflow.

skhd#

skhd is a macOS shortcut management tool that can call and bind other programs/commands, such as yabai's window management commands, through a configuration file, achieving highly customizable window operations. skhd emphasizes performance and has a fast response speed.

My Window Management Configuration#

yabai#

Installation and Basic Configuration#

Installing yabai is straightforward; just follow the instructions in its official wiki.

I personally recommend installing it via brew. If you haven't installed brew, you can first install it using the official one-click script.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After installing brew, you can continue with the installation and basic configuration. Open the terminal and enter the following command:

brew install koekeishiya/formulae/yabai

Install the script plugin:

sudo yabai --install-sa
sudo yabai --load-sa

Start the yabai service:

brew services start yabai

Note: If you are using macOS Big Sur or Monterey, you need to configure root permissions and startup on boot to call the script via API injection. The official documentation provides detailed instructions:

Edit the /private/etc/sudoers.d/yabai file:

sudo visudo -f /private/etc/sudoers.d/yabai

Add the following content to the opened file:

<user> ALL = (root) NOPASSWD: <path> --load-sa

The user and path within <> can be obtained using the whoami and which yabai commands.

see_user_and_config_yabai_sudo

After completing the above configuration, add the following two lines to the .yabairc configuration file of yabai:

sudo yabai --load-sa
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"

Custom Configuration#

The configuration file for yabai is managed by the user in the .yabairc file located in the $HOME directory, which can be edited using a text editor or command-line tool:

vi ~/.yabairc

Here is my personal configuration, which you can copy and customize. I have placed my personal configuration on GitHub, and you can click here to view it.

# !/usr/bin/env sh

sudo yabai --load-sa
yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"

# Global configuration
yabai -m config mouse_follows_focus          off
yabai -m config focus_follows_mouse          off
yabai -m config window_origin_display        default
yabai -m config window_placement             second_child
yabai -m config window_topmost               off
yabai -m config window_shadow                on
yabai -m config window_opacity               off
yabai -m config active_window_opacity        1.0
yabai -m config normal_window_opacity        0.90
yabai -m config window_border                off
yabai -m config window_border_width          6
yabai -m config active_window_border_color   0xff775759
yabai -m config normal_window_border_color   0xff555555
yabai -m config insert_feedback_color        0xffd75f5f
yabai -m config split_ratio                  0.50
yabai -m config auto_balance                 off
yabai -m config mouse_modifier               fn
yabai -m config mouse_action1                move
yabai -m config mouse_action2                resize
yabai -m config mouse_drop_action            swap

# Space configuration
yabai -m config layout                       bsp
yabai -m config top_padding                  15
yabai -m config bottom_padding               15
yabai -m config left_padding                 15
yabai -m config right_padding                15
yabai -m config window_gap                   15

# Ignored apps
yabai -m rule --add app="^System Preferences$" manage=off
yabai -m rule --add app="^Archive Utility$" manage=off
yabai -m rule --add app="^Logi Options+$" manage=off
yabai -m rule --add app="^Alfred Preferences$" manage=off

My configuration is mostly based on the official examples with some modifications, using the bsp algorithm for intelligent split-screen and adjusting the space to 15 for a more comfortable gap.

I also added some custom rules to ignore applications like system preferences and extraction tools that cannot customize their windows.

The overall presentation is as follows (the following effect shows the automatic arrangement of the algorithm after opening application windows, and new windows will automatically rearrange):

my_layout_1

skhd#

After configuring yabai, we have achieved intelligent split-screen, but sometimes the window positions provided by the algorithm do not meet our needs, or we need to frequently switch/adjust between various windows. In that case, we need to use the skhd tool to customize some shortcut configurations.

Installation#

skhd can also be installed conveniently using the brew package management tool:

brew install koekeishiya/formulae/skhd

After installation, just start it:

brew services start skhd

Custom Configuration#

Similar to yabai, skhd's configuration is managed through the $HOME/.skhdrc configuration file, which can be edited using a text editor or command-line tool.

vi ~/.skhdrc

Here is my personal configuration, which you can copy and customize. I have placed my personal configuration on GitHub, and you can click here to view it.

# Window focus
alt - h : yabai -m window --focus west
alt - j : yabai -m window --focus south
alt - k : yabai -m window --focus north
alt - l : yabai -m window --focus east

# Swap windows
shift + alt - h : yabai -m window --swap west
shift + alt - j : yabai -m window --swap south
shift + alt - k : yabai -m window --swap north
shift + alt - l : yabai -m window --swap east

# Move windows
shift + alt + ctrl - h : yabai -m window --warp west
shift + alt + ctrl - j : yabai -m window --warp south
shift + alt + ctrl - k : yabai -m window --warp north
shift + alt + ctrl - l : yabai -m window --warp east

# Rotate window layout
alt - r : yabai -m space --rotate 90

# Full screen
alt - f : yabai -m window --toggle zoom-fullscreen

# Set/Unset window space
alt - g : yabai -m space --toggle padding; yabai -m space --toggle gap

# Float window to center screen/Unset float window
alt - t : yabai -m window --toggle float;\
          yabai -m window --grid 4:4:1:1:2:2

# Change window split mode
alt - e : yabai -m window --toggle split

# Reset window layout
shift + alt - 0 : yabai -m space --balance

# Move window to specific desktop
shift + alt - 1 : yabai -m window --space 1; yabai -m space --focus 1
shift + alt - 2 : yabai -m window --space 2; yabai -m space --focus 2
shift + alt - 3 : yabai -m window --space 3; yabai -m space --focus 3
shift + alt - 4 : yabai -m window --space 4; yabai -m space --focus 4
shift + alt - 5 : yabai -m window --space 5; yabai -m space --focus 5
shift + alt - 6 : yabai -m window --space 6; yabai -m space --focus 6
shift + alt - 7 : yabai -m window --space 7; yabai -m space --focus 7
shift + alt - 8 : yabai -m window --space 8; yabai -m space --focus 8
shift + alt - 9 : yabai -m window --space 9; yabai -m space --focus 9

# Increase window size
shift + alt - w : yabai -m window --resize top:0:-20
shift + alt - d : yabai -m window --resize left:-20:0

# Decrease window size
shift + alt - s : yabai -m window --resize bottom:0:-20
shift + alt - a : yabai -m window --resize top:0:20

In simple terms, I configured a setup similar to the vim shortcut logic, achieving the following common functions:

  • <Option> + hjkl to focus between different windows
  • <Option> + <Shift> + hjkl to swap different windows
  • <Option> + <Shift> + 0 to reset window layout
  • <Option> + <Shift> + <1~9> to quickly move the current window to a specific desktop
  • <Option> + f for full screen
  • <Option> + t to float window to center screen/Unset float window
  • <Option> + g to set/Unset window space
  • <Option> + r to rotate window layout
  • <Option> + e to change window split mode

Here, hjkl are commonly used operations in the vim editor, and you can modify them to other keys you prefer.

After completing the above configuration, we have achieved intelligent window management with yabai and can perform window operations through simple shortcuts. Next, let's configure the macOS system to optimize our window management system.

macOS Desktop Management#

macOS provides powerful multi-desktop management capabilities, where each desktop area can be understood as a workspace that can independently arrange different windows, as shown in the image below:

macos_desktop_management

We can use desktops to differentiate our workspaces, such as using Desktop 1 for development IDEs and terminals, Desktop 2 for browsers and document writing, Desktop 3 for handling communication tools like WeChat and email, and Desktop 4 for leisure and video playback. This way, we only need to switch between a few desktops to implement our workflow logic without worrying about window focus issues.

To further optimize and quickly switch between desktops, we can use launchers like Alfred or Raycast to quickly launch/focus applications, and we can also use window switching software like AltTab or Manico to provide shortcuts for quickly switching between opened applications.

Additionally, the macOS system settings also provide custom shortcut options for switching. I modified <Option> + <1~9> to correspond to specific desktops, so when working, I can quickly switch to the corresponding workspace by pressing the corresponding shortcut key, which quickly forms muscle memory.

Open System Preferences - Keyboard - Shortcuts - Mission Control, and we can set corresponding shortcuts for different desktops. If they do not appear, you can first open 9 empty desktops for configuration, and the settings will remain even after closing the desktops.

keyboardshortcut_to_change_desktop

Additionally, there is a small setting I like: open System Preferences - Accessibility - Display - Display - Reduce Motion. This will reduce the animation effects when switching between different desktops, improving switching speed. Combined with our automatic split-screen and shortcuts, it achieves fast and powerful multi-workspace switching. I prioritize speed and efficiency, so those who enjoy macOS animations can skip this setting.

reduce_display_effect

Conclusion#

This is my current macOS window management solution. I am someone who loves tinkering with software and various configurations, often spending several days on a small requirement, always pursuing my best practices.

Perhaps many configurations do not save me a lot of time in my subsequent work; window organization and switching only make a few seconds of difference. However, when I use the system that I spent a lot of effort researching and optimizing in my daily work and study, or when an unexpected requirement uses a software/configuration I previously tinkered with, I feel inexplicably happy and accomplished. This is probably the meaning of tinkering, and I hope everyone can enjoy such joy.

I maintain a toolbox project on GitHub, 『GitHub - pseudoyu/yu-tools』, which documents many other software and hardware choices and is continuously updated and optimized. If you are interested, feel free to communicate, and I will gradually release corresponding configuration/use tutorials.

Note: This article is authorized for first publication on 『少数派』, and the original address is: 『Automating Window Management: A macOS Window Management System Based on yabai+skhd』.

References#

  1. Blazing Fast Window Management on macOS
  2. yabai project address
  3. skhd project address
  4. pseudoyu/yu-tools personal toolbox project address
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.