Show Spacepal's Space names in SketchyBar

SketchyBar only knows Spaces by number. Spacepal writes the name, note, color, apps and desktop number of every Space to a JSON file whenever something changes, so a small SketchyBar plugin can show "Client B" instead of "4", and a click can switch through Spacepal. This page gives a working item for the current Space's name and one for all Spaces.

Where the data is

Spacepal rewrites state.json on every change:

{
  "current": "Code",
  "spaces": [
    { "id": "…", "name": "Code", "number": 1, "display": "…",
      "isActive": true, "isFullscreen": false, "hasCustomName": true,
      "symbol": "chevron.left.forwardslash.chevron.right",
      "color": "#9B6BF4", "note": "Editor and terminal",
      "apps": ["Visual Studio Code", "Terminal"] }
  ],
  "updatedAt": "2026-10-27T09:12:00Z",
  "version": 1
}

current is the active Space on the display with the menu bar. color and note appear only when set, and full screen Spaces have no number. With several displays, each display has its own active Space, so more than one entry can have "isActive": true.

If you prefer HTTP, turn on the Local API in Settings, General; curl -s http://127.0.0.1:57301/spaces returns the same JSON. It is off by default.

Item 1: the current Space's name

In sketchybarrc:

sketchybar --add item spacepal left \
           --set spacepal script="$PLUGIN_DIR/spacepal.sh" \
                          click_script="open -g spacepal://overview" \
                          update_freq=5 \
           --subscribe spacepal space_change

And plugins/spacepal.sh (make it executable with chmod +x):

#!/bin/zsh
STATE="$HOME/Library/Application Support/Spacepal/state.json"
# space_change can fire just before Spacepal rewrites the file.
[ "$SENDER" = "space_change" ] && sleep 0.3
LABEL=$(jq -r '.current' "$STATE")
sketchybar --set "$NAME" label="$LABEL"

$NAME and $SENDER are set by SketchyBar. The update_freq poll catches renames and anything the space_change event misses. Clicking the item opens Spacepal's overview.

Item 2: every Space, current one marked

LABEL=$(jq -r '[.spaces[] | select(.isFullscreen | not)
  | if .isActive then "[\(.name)]" else .name end] | join("  ")' "$STATE")
sketchybar --set "$NAME" label="$LABEL"

For one clickable item per Space, generate items from the same file in sketchybarrc and give each a click_script of open -g spacepal://switch/N, where N is its number.

Requirements and notes

Related

Written by Dan Bayer, developer of Spacepal. Last updated 2026-10-27.