Skip to content

Add macOS workspace restoration plan documentation#4

Open
kertal wants to merge 5 commits into
mainfrom
claude/workspace-restoration-plan-gvVif
Open

Add macOS workspace restoration plan documentation#4
kertal wants to merge 5 commits into
mainfrom
claude/workspace-restoration-plan-gvVif

Conversation

@kertal

@kertal kertal commented Feb 19, 2026

Copy link
Copy Markdown
Owner

Summary

This adds comprehensive documentation for a scriptable macOS workspace restoration system that enables developers to save, restore, and switch between multi-project developer workspaces with a single keystroke.

Key Changes

  • Architecture overview: Documents a recommended stack combining AeroSpace (virtual workspace manager), iTerm2 (terminal sessions), and shell scripts for project launching
  • Detailed implementation plan: Five-phase rollout covering:
    • AeroSpace configuration with workspace keybindings (alt-1 through alt-5)
    • iTerm2 profile and arrangement setup per project
    • Project launcher shell script (workspace.sh) with TOML-based configuration
    • Keyboard shortcut integration via AeroSpace callbacks or Raycast
    • Git worktree support for parallel branch work
  • UI layer options: Compares SwiftBar, Raycast, Alfred, and other approaches for menu bar workspace switching, with recommended implementations for both
  • Complete examples: Full working configurations for two sample projects (React frontend and Python API)
  • Installation checklist: Step-by-step setup guide
  • Future extensions: Ideas for auto-detection, teardown commands, monitor-aware layouts, and MCP integration

Notable Details

  • Justifies technology choices (why AeroSpace over native Spaces or Yabai, considering SIP requirements and corporate policy)
  • Includes actual TOML config examples, shell script implementations, and AppleScript snippets
  • Provides comparison tables for different UI approaches to help users choose the best fit
  • Addresses practical concerns like git worktrees for parallel Claude Code sessions on different branches

https://claude.ai/code/session_019NLEfbmYTkMtdnVYuS6UZM

Covers AeroSpace virtual workspaces, iTerm2 arrangements, shell-based
project launcher scripts, and keyboard shortcut integration for instant
switching between parallel Claude Code + browser preview setups.

https://claude.ai/code/session_019NLEfbmYTkMtdnVYuS6UZM
Covers SwiftBar plugin (lowest friction, always-visible dropdown),
Raycast extension (searchable list for many projects), and comparison
of 6 approaches including Hammerspoon, rumps, Alfred, and SwiftUI.

https://claude.ai/code/session_019NLEfbmYTkMtdnVYuS6UZM

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a standalone documentation plan describing a scriptable macOS “workspace restoration” workflow for switching between multi-project dev setups (terminals, browser previews, and related tools) using AeroSpace + iTerm2 + scripts.

Changes:

  • Introduces an end-to-end architecture and phased setup guide for workspace switching on macOS.
  • Provides example AeroSpace config, iTerm2 profile/arrangement guidance, and a sample workspace.sh launcher.
  • Documents optional UI integrations (SwiftBar / Raycast) plus git worktree usage for parallel branch workflows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +244 to +245
aerospace workspace "$ws" 2>/dev/null || true

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AeroSpace workspace switch command is effectively fire-and-forget (aerospace workspace "$ws" 2>/dev/null || true). If ws is empty/invalid or AeroSpace isn’t available, the script will silently continue and print success. Consider validating ws and failing with a clear error when the workspace switch doesn’t succeed.

Suggested change
aerospace workspace "$ws" 2>/dev/null || true
if [[ -z "$ws" ]]; then
echo "Error: No AeroSpace workspace configured for project '${project}'" >&2
exit 1
fi
if ! command -v aerospace >/dev/null 2>&1; then
echo "Error: 'aerospace' command not found; cannot switch workspace '${ws}' for project '${project}'" >&2
exit 1
fi
if ! aerospace workspace "$ws"; then
echo "Error: Failed to switch to AeroSpace workspace '${ws}' for project '${project}'" >&2
exit 1
fi

Copilot uses AI. Check for mistakes.
Comment on lines +325 to +328
alt-1 = ['workspace 1', 'exec-and-forget ~/.config/workspaces/workspace.sh open project-a --no-switch']
```

(Add a `--no-switch` flag to skip the `aerospace workspace` call when triggered from AeroSpace itself.)

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Option A shows calling workspace.sh open project-a --no-switch, but the provided workspace.sh argument parsing doesn’t handle --no-switch (it passes only the project name to cmd_open). Either implement flag parsing (and behavior) in the script, or remove the flag from the example so the instructions are directly runnable.

Copilot uses AI. Check for mistakes.
Comment on lines +189 to +192
app_mode = true # Open as standalone window (no browser chrome)

[extras]
# Additional apps to open/focus

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The project TOML example includes browser.app_mode and extras.apps, but the provided workspace.sh implementation doesn’t read or apply either setting. Clarify these are future extensions, or extend the script to honor them so the example config matches the implementation.

Suggested change
app_mode = true # Open as standalone window (no browser chrome)
[extras]
# Additional apps to open/focus
# NOTE: `app_mode` is a planned extension; current workspace.sh ignores this setting.
app_mode = true # Intended: open as standalone window (no browser chrome)
[extras]
# Additional apps to open/focus
# NOTE: `extras.apps` is a planned extension; current workspace.sh does not yet launch these.

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +88
# Disable macOS Spaces animations (they interfere)
[gaps]
inner.horizontal = 8
inner.vertical = 8
outer.left = 8
outer.right = 8
outer.top = 8
outer.bottom = 8

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the AeroSpace config snippet, the comment says “Disable macOS Spaces animations” but the following [gaps] settings only configure window gaps. Update the comment to reflect what the settings actually do (or document the correct place/setting for animation control if applicable).

Copilot uses AI. Check for mistakes.
| `project-a` | `~/code/project-a` | `PROJECT-A` | Blue | `claude` |
| `project-a-server` | `~/code/project-a` | `PROJECT-A:dev` | Blue | `npm run dev` |
| `project-b` | `~/code/project-b` | `PROJECT-B` | Green | `claude` |
| `project-b-server` | `~/code/project-b` | `PROJECT-B:dev` | `yarn dev` | Green |

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the iTerm2 profile examples table, the project-b-server row has the Tab Color and Startup Command columns swapped (it lists yarn dev as the tab color and Green as the startup command). This makes the example inconsistent with the column headers and the other rows.

Suggested change
| `project-b-server` | `~/code/project-b` | `PROJECT-B:dev` | `yarn dev` | Green |
| `project-b-server` | `~/code/project-b` | `PROJECT-B:dev` | Green | `yarn dev` |

Copilot uses AI. Check for mistakes.
# Parse TOML value (basic — for simple key = "value" pairs)
toml_get() {
local file="$1" key="$2"
grep "^${key}" "$file" | sed 's/.*= *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' | tr -d ' '

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toml_get relies on grep inside a script running with set -e, so if an optional key (e.g., url or arrangement) is missing the script will exit before the later -n checks run. Consider making toml_get return an empty string when the key is absent (e.g., grep ... || true) and avoid deleting all spaces so values with spaces or inline comments aren’t mangled.

Suggested change
grep "^${key}" "$file" | sed 's/.*= *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' | tr -d ' '
local line
line=$(grep "^${key}" "$file" || true)
if [[ -z "$line" ]]; then
echo ""
return 0
fi
echo "$line" | sed -E 's/.*=\s*"?([^"]*)"?\s*(#.*)?$/\1/'

Copilot uses AI. Check for mistakes.
Comment on lines +236 to +239
local dir=$(toml_get "$config" "directory")
local url=$(toml_get "$config" "url")
local arrangement=$(toml_get "$config" "arrangement")
dir="${dir/#\~/$HOME}"

Copilot AI Feb 19, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd_open reads directory into dir (and expands ~) but never uses it. Either use it to set the working directory for launched apps/terminal sessions, or remove it from the script (and update the doc) to avoid implying it affects behavior.

Suggested change
local dir=$(toml_get "$config" "directory")
local url=$(toml_get "$config" "url")
local arrangement=$(toml_get "$config" "arrangement")
dir="${dir/#\~/$HOME}"
local url=$(toml_get "$config" "url")
local arrangement=$(toml_get "$config" "arrangement")

Copilot uses AI. Check for mistakes.
Covers why native Cmd+Tab doesn't work with AeroSpace workspaces,
recommends alt-tab bindings for workspace-back-and-forth and window
cycling, and documents the Karabiner-Elements approach for reclaiming
literal Cmd+Tab.

https://claude.ai/code/session_019NLEfbmYTkMtdnVYuS6UZM
- AeroSpace config with workspace switching, tiling, vim-style focus,
  alt-tab back-and-forth, and window cycling
- workspace CLI tool: open/close/list/save/status/note/notes/ensure
- Example project configs for frontend and API workspaces
- iTerm2 AppleScript helpers for arrangement save/restore/close
- SwiftBar menu bar plugin showing active workspace and notes
- Raycast script commands for workspace switching and listing
- install.sh symlinks everything into ~/.config and ~/bin
- Per-workspace editable notes (stored in project TOML, displayed on
  switch and in menu bar)

https://claude.ai/code/session_019NLEfbmYTkMtdnVYuS6UZM
Click the note in the menu bar dropdown to open a macOS input dialog
where you can edit, save, or clear the note. Also shows "Add note..."
when no note is set.

https://claude.ai/code/session_019NLEfbmYTkMtdnVYuS6UZM
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants