Skip to content

Instantly share code, notes, and snippets.

@muness
Last active November 27, 2025 17:21
Show Gist options
  • Select an option

  • Save muness/b3a6cbd556c41e26ff02585adb2ffe03 to your computer and use it in GitHub Desktop.

Select an option

Save muness/b3a6cbd556c41e26ff02585adb2ffe03 to your computer and use it in GitHub Desktop.
macos tiling window manager cheatsheet

Notes

I've wanted a clean tiling WM setup on my mac for years. This finally works for me:

  • Yabai for tiling
  • Ghostty for a fast terminal
  • Zellij for panes and tabs
  • JankyBorders for a clear focus highlight
  • A Raycast extension for quick layout toggles and restarts
  • skhd-zig for simple hotkeys

Zellij

Modern tmux alternative with easier defaults. Install: brew install zellij Start: zellij inside Ghostty.

Raycast + Yabai

Install the Yabai extension in Raycast. Useful for:

  • Switching layouts
  • Restarting Yabai after editing configs

Multiple displays

Works fine with this setup.

Spaces

I've been using mac Spaces. They seem to require yabai restarts on creating new desktops.

#~/.config/ghostty/config
# Treat option as alt so Zellij keybinds work
macos-option-as-alt = true
# Remove internal padding so Zellij touches tile edges
window-padding-x = 0
window-padding-y = 0
#~/.config/skhd/skhdrc
# Alt + Enter to toggle fullscreen
alt - return : yabai -m window --toggle zoom-fullscreen
# Use a fast shell for commands
.shell "/bin/dash"
# --------------------------------------------------------
# Groups and reusable commands
# --------------------------------------------------------
# Example process groups if you later want app specific behavior
.define terminal_apps ["kitty", "wezterm", "terminal", "iterm2"]
.define browser_apps ["chrome", "google chrome", "safari", "firefox", "arc"]
# Reusable yabai commands
.define yabai_focus : yabai -m window --focus {{1}} || yabai -m display --focus {{1}}
.define yabai_swap : yabai -m window --swap {{1}} || (yabai -m window --display {{1}} && yabai -m display --focus {{1}})
.define yabai_resize : yabai -m window --resize {{1}}:{{2}}:{{3}}
# Nice to have for toggling apps or scratchpads later (not heavily used below,
# but leaving here for you)
.define toggle_app : open -a "{{1}}" || osascript -e 'tell app "{{1}}" to quit'
.define toggle_scratchpad : yabai -m window --toggle {{1}} || open -a "{{2}}"
# --------------------------------------------------------
# Core window
# Using: alt + h/j/k/l as the "window nav" cluster
# --------------------------------------------------------
# Focus windows in BSP directions
alt - h : @yabai_focus("west")
alt - j : @yabai_focus("south")
alt - k : @yabai_focus("north")
alt - l : @yabai_focus("east")
# Swap current window with neighbor (rearrange layout)
alt + shift - h : @yabai_swap("west")
alt + shift - j : @yabai_swap("south")
alt + shift - k : @yabai_swap("north")
alt + shift - l : @yabai_swap("east")
# Resize current split a bit each time
# left/right shrink/expand horizontally, up/down vertically
alt + ctrl - h : @yabai_resize("left", "-20", "0")
alt + ctrl - l : @yabai_resize("right", "20", "0")
alt + ctrl - k : @yabai_resize("top", "0", "-20")
alt + ctrl - j : @yabai_resize("bottom","0", "20")
# --------------------------------------------------------
# Space and display navigation
# --------------------------------------------------------
# Focus spaces
alt - 1 : yabai -m space --focus 1
alt - 2 : yabai -m space --focus 2
alt - 3 : yabai -m space --focus 3
alt - 4 : yabai -m space --focus 4
# Move window to space but stay focused on it
alt + shift - 1 : yabai -m window --space 1; yabai -m space --focus 1
alt + shift - 2 : yabai -m window --space 2; yabai -m space --focus 2
alt + shift - 3 : yabai -m window --space 3; yabai -m space --focus 3
alt + shift - 4 : yabai -m window --space 4; yabai -m space --focus 4
# Cycle displays with the current window
alt - d : yabai -m window --display next; yabai -m window --focus recent
# --------------------------------------------------------
# yabai layout helpers
# --------------------------------------------------------
# Toggle floating / tiling for current window
alt - f : yabai -m window --toggle float
# Re-balance the current space (fix weird ratios)
alt - b : yabai -m space --balance
# Make current window "primary" on this space
alt - m : yabai -m window --swap biggest
# Rotate layout 90 degrees
alt - r : yabai -m space --rotate 90
# --------------------------------------------------------
# Optional: simple app toggles (comment out if you do not want them)
# --------------------------------------------------------
# Example: quickly toggle a couple of frequent apps
# alt - t : @toggle_app("Terminal")
# alt - c : @toggle_app("Visual Studio Code")
alt - o : @toggle_app("Obsidian")
#~/.yabairc
#!/usr/bin/env sh
# ---------- Process Management ----------
# Kill instances of borders to prevent duplicates on config reload
killall borders 2>/dev/null
# ---------- Core tiling ----------
yabai -m config layout bsp
yabai -m config split_type auto
yabai -m config auto_balance on
yabai -m config window_placement second_child
# ---------- Look and feel ----------
yabai -m config top_padding 10
yabai -m config bottom_padding 10
yabai -m config left_padding 10
yabai -m config right_padding 10
yabai -m config window_gap 10
# Disable macOS window shadows (cleaner look with borders)
yabai -m config window_shadow off
# ---------- Ghostty Compatibility ----------
# Force a layout refresh when Ghostty windows/tabs are created or destroyed
# This prevents "ghost" tiles when using native macOS tabs (Cmd+T) inside Ghostty
yabai -m signal --add app='^Ghostty$' event=window_created action='yabai -m space --layout bsp'
yabai -m signal --add app='^Ghostty$' event=window_destroyed action='yabai -m space --layout bsp'
# ---------- Mouse driven control ----------
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
yabai -m config focus_follows_mouse off
yabai -m config mouse_follows_focus off
# ---------- Float some apps ----------
# Standard system apps that break when tiled
yabai -m rule --add app="^System Settings$" manage=off
yabai -m rule --add app="^App Store$" manage=off
yabai -m rule --add app="^Finder$" manage=off
yabai -m rule --add app="^Messages$" manage=off
yabai -m rule --add app="^Calendar$" manage=off
yabai -m rule --add app="^Calculator$" manage=off
yabai -m rule --add app="^Raycast$" manage=off
# ---------- Start External Tools ----------
# JankyBorders configuration
# Note: Ensure you have JankyBorders installed via brew
borders active_color="gradient(top_right=0xfffab387,bottom_left=0xfff38ba8)" \
inactive_color=0xff494d64 \
width=6.0 &
echo "yabai configuration loaded"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment