See your spaces. Move through them.
A native macOS workspace map for yabai.
Open a floating grid, see what lives where, and go straight there.
Download · Install guide · Use it · Configure it · Build from source
yabai makes moving around a workspace grid fast. Spacemap makes it legible: press one shortcut to see every space, its windows, and the space you are on—then jump, navigate, or drag a window exactly where it belongs.
Note
Spacemap runs as a normal macOS app alongside yabai. It does not require disabling SIP or modifying macOS.
- 2D grid HUD — see spaces as a configurable rows-by-columns map
- Live focus updates — active space changes immediately through yabai signals
- Multi-monitor aware — use one unified grid or a separate HUD per display
- Space names — label spaces like Code, Web, or Music instead of memorising numbers
- Five cell styles — Rectangles, Hybrid, Icons, Thumbnails, or Simple
- Click a cell to focus its space
- Use arrow keys or Vim keys (
hjkl) with grid-aware wrapping - Press Return to focus the selected space; Escape closes the HUD
- Optional number-key jumps support multi-digit space numbers
- Pin a HUD so it stays open while you work
Drag a real window over any HUD cell and drop it there. Spacemap highlights the target, moves the window through yabai, and can focus the destination space when you choose.
- Built-in and file-based themes
- HUD transparency, size, position, shadow, app-icon size, and labels
- Custom normal and pinned hotkeys, including media keys and F13–F20
- Optional menu-bar workspace dots or miniature window-layout previews
- ScreenCaptureKit thumbnails on macOS 14+
- Sparkle updates: automatic, notify-only, or off
Install with Homebrew, or download the DMG from the latest release. The published build is ad-hoc signed and not notarized, so macOS may block it on first open; Control-click the app in Finder and choose Open, or remove the quarantine attribute with xattr -dr com.apple.quarantine /Applications/Spacemap.app.
brew tap wiggly-sheets/homebrew-tap
brew trust wiggly-sheets/homebrew-tap
brew install --cask spacemapUpdate later with:
brew upgrade --cask spacemap- Download the
.dmgfrom the latest release. - Open it and drag Spacemap into Applications.
- Open Spacemap once.
- In System Settings → Privacy & Security → Accessibility, enable Spacemap.
- Start yabai, then press Ctrl + Space.
Tip
Every release includes checksums.txt. To verify a downloaded DMG:
cd ~/Downloads
shasum -a 256 Spacemap*.dmgCompare its hash with the matching line in checksums.txt on the release page.
Warning
If macOS quarantines a manually downloaded build, Control-click the app in Finder and choose Open. As a last resort:
xattr -d com.apple.quarantine /Applications/Spacemap.app- macOS 13 or later; macOS 14+ for thumbnail cells
- yabai running
- Accessibility permission for Spacemap
- Screen Recording permission only when using thumbnail cells
- Automatically rearrange Spaces based on most recent use disabled in System Settings → Desktop & Dock → Mission Control
- Displays have separate Spaces enabled for independent multi-monitor HUDs
Install yabai with Homebrew if needed:
brew install asmvik/formulae/yabaiYou can use skhd or skhd.zig for additional grid-navigation bindings. Spacemap works independently of either.
| Action | Result |
|---|---|
| Ctrl + Space | Toggle HUD |
| Arrow keys / hjkl | Navigate selected cells when enabled |
| Return | Focus selected space |
| Escape | Close HUD |
| Click a cell | Focus that space |
| Drag window onto a cell | Move it to that space |
| ⌘ + , | Open Settings while HUD or menu is open |
| ⌘ + R | Restart from menu bar |
Open Settings from the menu bar or the HUD shortcut. Changes save immediately.
| Section | What it controls |
|---|---|
| Grid | Space limit/layout, display behavior, cell style, labels, icon strip |
| Space Names | Name visibility, per-space names, and named profiles |
| Appearance | Theme, background, opacity, scale, icon size, HUD shadow |
| Behavior | Hotkeys, HUD position, auto-hide, key navigation, drag-drop focus, menu bar, updates |
| Debug/Advanced | Signal socket health, diagnostics, extra window records |
Use these from shortcuts, scripts, Raycast, or other automation:
| URL | Result |
|---|---|
spacemap://toggle-hud |
Toggle HUD |
spacemap://pin-hud |
Show and pin HUD |
spacemap://settings |
Open Settings |
spacemap://menu |
Open menu-bar menu |
spacemap://config |
Open config file |
spacemap://themes |
Open themes folder |
Launching the app from Applications installs spacemap and its manual page when permission allows. You can also run make install-cli from a checkout.
spacemap --version # print version
spacemap --trigger # toggle HUD
spacemap --space next # focus next space, then show HUD
spacemap --space 4 # focus space 4, then show HUD
spacemap --space web # focus yabai space label "web"
spacemap --settings # open Settings
spacemap --config # open config file--space accepts 1–16, prev, next, first, last, recent, mouse, or a yabai space label.
# Example skhd bindings
ctrl - right : spacemap --space next
ctrl - left : spacemap --space prevRead the installed manual with man spacemap.
Spacemap stores configuration in:
~/.config/spacemap/config.toml
Settings is best for day-to-day changes. The TOML file is useful for dotfiles and automation. Missing or invalid fields repair individually; the prior file is saved as config.toml.bak.
[grid]
cols = 8
rows = 2
maxSpaces = 16
cellStyle = "rects" # rects, hybrid, icons, thumbnails, simple
multiMonitorHUDMode = "unified" # unified or separate
showSpaceNumbers = true
showSpaceLayout = false # layout letter next to index: float="f", stack="s", bsp="b" (strip uses bare for bsp); needs showSpaceNumbers
showIconStrip = true
[appearance]
theme = "default"
uiScale = 0.5
backgroundAlpha = 0.3
hudShadow = true
[behavior]
autoHideTimeout = 5
useArrowKeys = false
useVimKeys = false
jumpToSpaceEnabled = false
[behavior.hotkey]
keyKind = "keyCode"
keyCode = 49
modifiers = ["ctrl"]
[glyphStrip]
enabled = false
maxIconsPerSpace = 8 # 0 = unlimited
leftClickAction = "focusSpace"
rightClickAction = "destroySpace"
middleClickAction = "none"
position = "leftOfNotch"Glyph strip reference — every key with its default:
[glyphStrip]
enabled = false # master toggle; legacy bare `glyphStrip = true` still reads
showSpaceNumbers = true # draw the space index digit
showLayoutSuffix = true # layout letter: bsp="", float="f", stack="s"
showAppIcons = true # draw sketchybar-app-font glyphs
dedupeAppsPerSpace = true # one glyph per app per space; false = one per window
maxIconsPerSpace = 8 # glyph cap per space, then "+N"; 0 = unlimited
iconSize = 11.0 # glyph point size, clamped 6...24
indexSize = 11.0 # space-number point size, clamped 6...24
highlightCurrentSpace = true
backgroundMaterial = "none" # none | solid | liquidGlass
glassAmount = 0.5 # liquidGlass tint 0...1; 0 clear, 0.5 default, 1 tinted
# (Settings slider shown only while Theme Tint is on)
useThemeTint = true # liquidGlass only; false = neutral pure frost, no fill overlay
shape = "none" # none | pill | roundedRect | bar (none = no background, no outline)
backgroundOpacity = 0.35 # solid only, 0.01...1.0 (Settings slider 1...100%)
cornerRadius = 20.0 # roundedRect only, 0...40
margin = 6.0 # gap to the notch edge, clamped 0...40
yOffset = 0.0 # vertical nudge; positive moves the strip DOWN,
# clamped -10...10, 0 centered, NOT clamped back into the row
iconSpacing = 3.0 # extra gap between two app icons and before +N, clamped 0...20
indexPadding = 6.0 # gap from the space number to its first icon or placeholder, clamped 0...20
hoverPadding = 1.0 # grow around the hovered segment's glyph box, both
# axes (symmetric), clamped 0...12; hit-testing uses
# the full slot while the pill stays glyph-sized
hoverCornerRadius = 4.0 # rounding of that hover highlight, clamped 0...20
showDisplaySeparators = true # "|" between spaces on different displays
showAddSpaceButton = true # trailing "+"
showPlaceholders = true # placeholder glyph for empty spaces
leftClickAction = "focusSpace" # none | focusSpace | destroySpace | moveWindowHere |
# toggleFullscreen | floatWindow | balanceWindows | mergeWindows
rightClickAction = "destroySpace"
middleClickAction = "none"
position = "leftOfNotch" # leftOfNotch | rightOfNotch | center | custom
xOffset = 0 # custom only; points from the menu bar row's left edge, -4000...4000
borderEnabled = true # hairline outline, independent of the material;
# with none it follows shape, shape none = no outline
theme = "" # follow main HUD theme; or a theme name
# leftOfNotch/rightOfNotch sit BESIDE the notch:
# the strip's outer edge is anchored `margin` short
# of NSScreen.auxiliaryTopLeftArea.maxX /
# auxiliaryTopRightArea.minX, so it never overlaps the
# camera housing. Displays without a notch report empty
# auxiliary rects, so these fall back to the screen edge.
# center puts the strip on the notch midpoint, which is
# under the camera on most displays — avoid it.
Configuration reference
| Table | Useful keys |
|---|---|
[grid] |
cols, rows, maxSpaces, cellStyle, showMode, multiMonitorHUDMode, unifiedHUDVisibility, separateHUDVisibility, displayNavigationWrap, showSpaceNumbers, showSpaceLayout, showIconStrip, showMultiAppIcons |
[spaceNames] |
showSpaceNames; names live in [spaceNames.names] as quoted space-number keys; named sets live in [spaceNameProfiles] |
[appearance] |
theme, mode, backgroundAlpha, hudShadow, uiScale, iconScale |
[behavior] |
autoHideTimeout, useArrowKeys, useVimKeys, jumpToSpaceEnabled, hudPosition, focusSpaceOnWindowDrop, focusSpaceOnWindowDropModifier, showHUDOnSpaceChange, hideMenuBarIcon, updateMode, glyphStripHotkey (session-only strip toggle, default unbound) |
[glyphStrip] |
enabled, theme, showSpaceNumbers, showLayoutSuffix, showAppIcons, dedupeAppsPerSpace, maxIconsPerSpace, iconSize, indexSize, iconSpacing, indexPadding, highlightCurrentSpace, backgroundMaterial, glassAmount, useThemeTint, shape, backgroundOpacity, cornerRadius, margin, yOffset, hoverPadding, hoverCornerRadius, showDisplaySeparators, showAddSpaceButton, showPlaceholders, leftClickAction, rightClickAction, middleClickAction, position, xOffset, borderEnabled |
[advanced] |
socketHealthInterval, showExtraWindows |
Space names example:
[spaceNames.names]
"1" = "Desktop"
"2" = "Code"
"3" = "Web"
"4" = "Music"Spacemap uses Sparkle for in-app update checks. Choose Auto, Notify, or Off under Settings → Behavior → Automatic Updates.
Homebrew users can update with:
brew upgrade --cask spacemapManual installs can download the newest DMG from Releases, drag it over the old copy in Applications, and choose Replace. Your configuration stays in ~/.config/spacemap/.
- macOS 13+
- Xcode 15+ or Command Line Tools
- yabai and Accessibility permission for live testing
git clone https://github.com/wiggly-sheets/Spacemap.git
cd Spacemap
make run # build, install, launch
make test # unit tests
make app # assemble Spacemap.app (universal)
make dmg # arm64 and x86_64 DMGsFor an Xcode project:
python3 scripts/generate-xcodeproj.py
open spacemap.xcodeprojArchitecture-specific bundles:
make app-arm
make app-intel
make app-universalTip
Accessibility permission belongs to the .app bundle, not a raw executable. Reinstalling changes the app hash. For a clean local permission cycle, use make dev1, remove Spacemap from Accessibility settings, then run make dev2 and grant access again.
| Problem | Try this |
|---|---|
| HUD does not appear | Confirm Spacemap has Accessibility permission, then reopen it |
| No spaces or windows | Confirm yabai is running and executable at /opt/homebrew/bin/yabai or /usr/local/bin/yabai |
| Thumbnails are blank | Grant Screen Recording permission, then reopen the HUD |
| Layout moves unexpectedly | Disable macOS Automatically rearrange Spaces based on most recent use, then log out and back in |
| Multi-monitor HUD is wrong | Enable Displays have separate Spaces, then log out and back in |
| Config change seems ignored | Close/reopen HUD; hotkey changes apply immediately from Settings |
| App will not launch | Check Console.app for “spacemap”; reinstall with make dev1 then make dev2 in a checkout |
| Document | Purpose |
|---|---|
| Support | Get help or report a problem |
| Security policy | Report a vulnerability responsibly |
| Contributing | Contribute code or documentation |
| Developer guide | Technical implementation notes |
| Reference | Detailed config and command reference |
| Roadmap | Planned work and known issues |
| Changelog | Release history |
Spacemap is released under the MIT License. You are free to use, read, modify, and distribute it.