Workspace-centric macOS environment using Aerospace, SketchyBar, and iTerm2. Treats workspaces as project contexts rather than collections of unrelated windows.
Aerospace manages windows in accordion (stacked) layout — one app visible at a time per workspace, switched with alt-j/alt-k.
SketchyBar displays active workspaces in a transparent top bar. Only workspaces with windows are shown. Each workspace shows its slot (1-9, A-Z) and display name.
Templates define which apps to launch for a given project type. Multiple workspaces can be created from the same template.
Slots are the fixed Aerospace workspace identifiers (1-9, A-Z). Each slot has a permanent keybinding (alt-1 through alt-9, alt-a through alt-z). Workspace 1 is persistent and always available as the default workspace.
| Key | Action |
|---|---|
alt-space |
Open workspace picker (switch or create) |
alt-1..alt-9 |
Switch to workspace slot 1-9 |
alt-a..alt-z |
Switch to workspace slot A-Z |
alt-j / alt-k |
Focus next/previous window in stack |
alt-h / alt-l |
Focus left/right |
alt-shift-1..alt-shift-z |
Move window to workspace slot |
alt-shift-tab |
Move workspace to next monitor |
alt-tab |
Switch to previous workspace |
alt-slash |
Switch to tiles layout |
alt-comma |
Switch to accordion layout |
Opens an fzf-based menu in an iTerm2 popup window:
Switch or create workspace
1 Backend
* 2 (current)
A AI
─────────────────
+ New from AI
+ New from Backend
- Select an active workspace to switch to it
- Select a template to create a new workspace (prompts for slot and name)
- Type a slot character for instant filtering (
--select-1) *marks the currently focused workspace
Defined in templates/workspaces.yaml. Each template lists apps to launch:
AI:
apps:
- app: iTerm
- app: Google Chrome
args: ["--new-window", "https://claude.ai"]Apps can be a bare string (just the name) or an object with app and args for launch arguments.
Via picker: alt-space → select template → enter slot and name.
Via command line:
bin/ws-launch AI A # Template "AI" in slot A, display name "AI"
bin/ws-launch AI B my-project # Template "AI" in slot B, display name "my-project"alt-space → ws-pick-wrapper (background process)
├── launches iTerm2 with "Workspace Picker" profile
├── ws-pick shows fzf, writes selection to temp file
└── wrapper reads result, runs aerospace workspace switch
Aerospace workspace change → exec-on-workspace-change hook
└── sketchybar --trigger aerospace_workspace_change
└── ws_trigger item runs ws-sync
└── recreates ws.* items in SketchyBar
Slot-to-name mappings stored in ~/.local/state/workspaces/names:
A=AI
B=my-project
1=Backend
Written by ws-launch, read by ws-sync for SketchyBar display.
The Aerospace config is not stored in the repo. bin/generate-aerospace-config.py reads the default config from /Applications/AeroSpace.app/Contents/Resources/default-config.toml and applies:
- Accordion as default layout
exec-on-workspace-changehook for SketchyBarafter-startup-commandto run initial ws-syncpersistent-workspaces = ["1"]alt-spacekeybinding for the picker- Top gap for SketchyBar bar
This keeps the config up to date with Aerospace releases.
bin/
setup # Install: venv, configs, profiles, services
generate-aerospace-config.py # Reads default config, applies modifications
ws-sync # Syncs Aerospace state → SketchyBar items
ws-launch # Launches workspace from template into a slot
ws-pick # fzf picker (runs inside iTerm2)
ws-pick-wrapper # Launches picker, acts on result (runs outside iTerm2)
config/
sketchybar/
sketchybarrc # Bar appearance, events, system indicators
plugins/
workspaces.sh # Triggers ws-sync on workspace change
clock.sh # Clock display
battery.sh # Battery indicator
volume.sh # Volume indicator
iterm2/
workspace-picker.json # iTerm2 dynamic profile for picker popup
templates/
workspaces.yaml # Workspace template definitions
Install via Homebrew:
brew install --cask aerospace
brew install sketchybar jq yq fzfiTerm2 and Python 3.11+ are also required.
bin/setupThis will:
- Check all dependencies are installed
- Create a Python venv and install
tomli_w(for TOML config generation) - Warn if "Automatically rearrange Spaces" is enabled in macOS settings
- Back up existing Aerospace and SketchyBar configs
- Generate Aerospace config from the app's default
- Symlink SketchyBar config from this repo
- Install iTerm2 dynamic profile for the workspace picker
- Start or reload Aerospace and SketchyBar
Safe to run multiple times.
- Notification badges per workspace (phase 2)
- Per-workspace app filtering
- Persistent workspace state across restarts