“Where is the ‘any’ key?” — Homer Simpson, in response to the message, “Press any key”
Tell me and I forget; teach me and I remember; involve me and I learn, Ben Franklin.
Window managers are responsible for the placement, arrangement and appearance of all your windows. They can help you to make the most of your display's screen real estate and improve your multitasking experience. Some examples are: FancyZones (Windows), Amethyst (macOS), i3, Awesome WM, and XMonad.
To know the basic about virtual desktops (Windows)/spaces(macOS), read our article How to use virtual desktops and keyboard shortcuts
FancyZones is a window manager utility for arranging and snapping windows into efficient layouts to improve the speed of your workflow. When you drag a window into a zone or enter the associated keyboard shortcut, the window is resized and repositioned to fill that zone.




Rectangle is a free and simple macOS window manager app. It lets you move and resize windows in macOS using sensible, out of the box keyboard shortcuts or snap areas.
Installation: brew cask install rectangle or you can download it from its website, drag the application into the Application folder, and authorize Rectangle. Navigate through System Preferences, Security & Privacy, Accessibility, and check Rectangle.
To arrange two windows side-by-side is very easy, just move each window to the left, right, top or bottom of your monitor or use the shortcuts: Left Half (Option/Alt ⌥ + Command ⌘ + ←), Right Half (Option/Alt ⌥ + Command ⌘ + →), Top Half (Option/Alt ⌥ + Command ⌘ + ↑), Down Half (Option/Alt ⌥ + Command ⌘ + ↓). To maximize/center a window, press Option/Alt ⌥ + Command ⌘ + F/C.
Learning the shortcuts and using them is a huge performance multiplier because this skill can be applied to all of your applications and speed up your daily workflow. You can get a keyboard shortcuts reference by clicking on the Rectangle icon in the top menu bar. Besides, you can move a window to another monitor: Control ⌃ + Option ⌥ + Command ⌘ + →/←- Rectangle
AeroSpace is a fast, keyboard-driven, i3-inspired tiling window manager for macOS that organizes your screen using a hierarchical tree of containers.
AeroSpace organizes every workspace as a hierarchical tree structure, a model directly borrowed from the i3 window manager.
When you “split” or “stack” windows, you are essentially changing the layout and orientation of the parent container. AeroSpace provides four primary layouts:
As you work, AeroSpace builds and modifies this tree dynamically based on your keyboard commands:
In AeroSpace, workspaces (often called “Spaces” in native macOS) function like virtual desktops. Think of each workspace as an independent, named container for your tree of windows. You can assign specific apps to specific workspaces (e.g., Workspace C for coding, Workspace W for web brosers, Workspace C for coding). You switch between them instantly using keyboard shortcuts, and each workspace maintains its own unique tiling tree layout.
Dedicate one workspace to a single primary application (or a tightly related group of applications) is considered the “gold standard” for power users of tiling window managers like AeroSpace, i3, or Sway. Why?
brew install --cask nikitabobko/tap/aerospace
# If you use GNU Stow to manage dotfiles:
brew install stow
# Put the file in your dotfiles repo like this:
dotfiles/
└── aerospace/
└── .config/
└── aerospace/
└── aerospace.toml
cd ~/dotfiles
stow aerospace # links to ~/.config/aerospace/aerospace.toml
rm -f ~/.aerospace.toml # AeroSpace errors if both locations exist
open -a AeroSpace
Accessibility permission: grant it to AeroSpace in System Settings, Privacy & Security, Device Control and Data Access. Then, disable “Displays have separate Spaces” in System Settings, Desktop & Dock, log out, and back in. The AeroSpace docs recommend this for stability.
# =============================================================================
# AeroSpace config
# Stow path : /aerospace/.config/aerospace/aerospace.toml
# Linked to : ~/.config/aerospace/aerospace.toml
# Do NOT also keep ~/.aerospace.toml.
# AeroSpace reports an error when the config exists in both places.
# Reload : alt-shift-; then Esc (or: aerospace reload-config)
# Find IDs : aerospace list-apps (shows bundle IDs of running apps)
# =============================================================================
# Opt in to the newest config format. Required to set persistent-workspaces.
config-version = 2
# Launch AeroSpace automatically when you log in to macOS.
start-at-login = true
# Re-read this file whenever it is saved. Reload manually once after enabling.
auto-reload-config = true
# -----------------------------------------------------------------------------
# AUTO-START APPS (runs once, every time AeroSpace starts)
# -----------------------------------------------------------------------------
# Each app is opened, then the on-window-detected rules below send its window
# to the right workspace. `open -a` takes the app name as shown in /Applications.
# If an app is already running, `open -a` just activates it.
after-startup-command = [
'exec-and-forget open -a "Ghostty"',
'exec-and-forget open -a "Obsidian"',
'exec-and-forget open -a "Zen"',
'exec-and-forget open -a "Visual Studio Code"',
'exec-and-forget open -a "Deskflow"',
# Finder has no window by default, so open one on your home folder.
'exec-and-forget open -a "Finder" ~',
# After the apps had time to appear, land on the terminal workspace.
'exec-and-forget sleep 6; aerospace workspace T',
]
# -----------------------------------------------------------------------------
# WORKSPACES
# -----------------------------------------------------------------------------
# Keep these workspaces alive even when empty, so they always exist and the
# keyboard shortcuts work immediately.
# T = Terminal (Ghostty) N = Notes (Obsidian) W = Web (Zen)
# C = Code (VS Code) D = Deskflow F = Finder
persistent-workspaces = ["T", "N", "W", "C", "D", "F"]
# -----------------------------------------------------------------------------
# LAYOUT: "maximized app per workspace"
# -----------------------------------------------------------------------------
# With ONE window per workspace and zero gaps, the window fills the screen.
# This is AeroSpace's version of fullscreen. It does not use macOS native
# fullscreen, which creates a separate macOS Space that AeroSpace can't manage.
default-root-container-layout = 'tiles'
default-root-container-orientation = 'auto'
# Gaps between windows (inner) and screen edges (outer). 0 = edge to edge.
# Raise them, e.g. 8, if you want a floating-card look.
gaps.inner.horizontal = 0
gaps.inner.vertical = 0
gaps.outer.left = 0
gaps.outer.bottom = 0
gaps.outer.top = 0
gaps.outer.right = 0
# Keep the tree tidy (recommended defaults).
enable-normalization-flatten-containers = true
enable-normalization-opposite-orientation-for-nested-containers = true
# Padding shown for stacked windows in accordion layout.
accordion-padding = 30
# Focus changes only with the keyboard, not by hovering the mouse.
focus-follows-mouse.enabled = false
# When the focused monitor changes, move the mouse pointer to its center.
on-focused-monitor-changed = ['move-mouse monitor-lazy-center']
# Disable macOS "Hide app" (Cmd+H): hidden apps are brought back automatically,
# because hiding confuses a tiling manager.
automatically-unhide-macos-hidden-apps = true
# Keyboard layout used to interpret the key names below.
key-mapping.preset = 'qwerty'
# -----------------------------------------------------------------------------
# AUTO-ASSIGN APPS TO WORKSPACES
# -----------------------------------------------------------------------------
# Whenever a new window appears, the first matching rule runs.
# `if` uses the app's bundle ID. Check yours with `aerospace list-apps`.
# `run` moves the window to the workspace.
on-window-detected = [
{ if = 'test %{app-bundle-id} = com.mitchellh.ghostty', run = 'move-node-to-workspace T' },
{ if = 'test %{app-bundle-id} = md.obsidian', run = 'move-node-to-workspace N' },
{ if = 'test %{app-bundle-id} = app.zen-browser.zen', run = 'move-node-to-workspace W' },
{ if = 'test %{app-bundle-id} = com.microsoft.VSCode', run = 'move-node-to-workspace C' },
{ if = 'test %{app-bundle-id} = org.deskflow.deskflow', run = 'move-node-to-workspace D' },
{ if = 'test %{app-bundle-id} = com.apple.finder', run = 'move-node-to-workspace F' },
]
# -----------------------------------------------------------------------------
# KEYBINDINGS (main mode)
# -----------------------------------------------------------------------------
# alt = the Option key. Trade-off: Option+letter no longer types special
# characters (like † on Option+t) in any app, because AeroSpace grabs them globally.
[mode.main.binding]
# Jump to a workspace
alt-t = 'workspace T'
alt-n = 'workspace N'
alt-w = 'workspace W'
alt-c = 'workspace C'
alt-d = 'workspace D'
alt-f = 'workspace F'
# Send the focused window to a workspace.
# The window moves; your current focus stays where it is.
alt-shift-t = 'move-node-to-workspace T'
alt-shift-n = 'move-node-to-workspace N'
alt-shift-w = 'move-node-to-workspace W'
alt-shift-c = 'move-node-to-workspace C'
alt-shift-d = 'move-node-to-workspace D'
alt-shift-f = 'move-node-to-workspace F'
# Previous / next workspace (wraps around), Alt -> and Alt <-
# Go to System Settings → Keyboard → Keyboard Shortcuts...
# In the left sidebar, select Mission Control.
# Look for and uncheck any shortcuts using the Option key with the Left or Right arrow,
# such as "Move left a space" or "Move right a space".
# After that, reload your AeroSpace config (alt-shift-; then Esc),
# and your new arrow key bindings should work as expected.
# Otherwise, use alt-leftSquareBracket ([) and alt-rightSquareBracket (])
alt-left = 'workspace --wrap-around prev'
alt-right = 'workspace --wrap-around next'
# Toggle between the current and the previous workspace
alt-tab = 'workspace-back-and-forth'
# AeroSpace fullscreen for the focused window (fills the screen, no gaps).
# Press again to restore. Independent of macOS native fullscreen.
alt-enter = 'fullscreen'
# Only needed when a workspace holds several windows, e.g. two Finder windows.
alt-h = 'focus left'
alt-j = 'focus down'
alt-k = 'focus up'
alt-l = 'focus right'
alt-shift-h = 'move left'
alt-shift-j = 'move down'
alt-shift-k = 'move up'
alt-shift-l = 'move right'
# Switch the layout of the current workspace: tiles <-> stacked accordion
alt-slash = 'layout tiles horizontal vertical'
alt-comma = 'layout accordion horizontal vertical'
# Resize tiles
alt-minus = 'resize smart -50'
alt-equal = 'resize smart +50'
# Enter service mode (reload, reset, float toggle)
alt-shift-semicolon = 'mode service'
Understanding AeroSpace Service Mode. Most of the time, AeroSpace is in what’s called main mode. In main mode, every key you press (alt-t, alt-w, alt-enter, etc.) triggers a workspace switch, a window move, or some other everyday action.
But you don’t want every action bound to a direct alt-… shortcut — that would be dozens of hotkeys to memorize, and some would inevitably clash with your apps. So AeroSpace lets you define extra modes: a temporary state where a different set of keys is active. You enter the mode with one hotkey, press a single key to do something, and then you're back to normal.
Service mode is exactly that: a small “command menu” for rare maintenance actions (reload config, reset layout, toggle floating, close other windows). You don’t use these often, so they don’t deserve a permanent alt-… shortcut. They live behind one entry key instead.
# How you get in and out Service mode
# In main mode, pressing alt-shift-; runs the command mode service.
# That switches AeroSpace into service mode — nothing else happens.
# No window moves, no workspace changes. You're just "inside" the service menu now.
# Now the only keys that do anything are the ones listed under [mode.service.binding].
[mode.main.binding]
alt-shift-semicolon = 'mode service'
# -----------------------------------------------------------------------------
# SERVICE MODE (alt-shift-; then one key, automatically returns to main)
# -----------------------------------------------------------------------------
[mode.service.binding]
# Press Esc while in service mode:
# Every one of those bindings ends with 'mode main', so after running the command,
# AeroSpace immediately returns to main mode.
# You don't have to press Esc separately — the mode is one-shot by design.
# 'reload-config' Reload this config (aerospace.toml) and 'mode main' go back to main mode
esc = ['reload-config', 'mode main']
# Press r:
# flatten-workspace-tree — resets the layout of the current workspace back to a single flat row of tiles.
# AeroSpace builds a tree of containers as you split and stack windows;
# this command collapses that tree so you get one clean horizontal row again.
# mode main — return to normal.
# Why you'd use it: you've been splitting and nesting windows and the layout has become tangled;
# r is the "start over" button for the current workspace.
r = ['flatten-workspace-tree', 'mode main']
# Press f:
# layout floating tiling — toggles the focused window between two states:
# tiling: managed by AeroSpace, snapped into the grid (the normal state).
# floating: behaves like a regular macOS window — you can drag it anywhere,
# resize it freely, and it sits on top of the tiled windows.
# Useful for dialogs, picture-in-picture, quick reference windows.
f = ['layout floating tiling', 'mode main']
# Press Backspace:
# close-all-windows-but-current — closes every window on the current workspace
# except the one that's focused. Despite the name, it's workspace-scoped:
# it doesn't touch windows on other workspaces.
backspace = ['close-all-windows-but-current', 'mode main']
Amethyst is a tiling window manager for macOS.