Bringing Claude Code sessions back to the right desktop after a restart
I keep one Mac desktop per project, each with an iTerm2 window running Claude Code and a Chrome window or two. A restart used to cost me twenty minutes of putting it all back. This is how Spacepal now does it on its own, what macOS makes hard, and the bug the first real restart test turned up.
The test: 16 desktops, 17 terminal windows running Claude Code, 23 Chrome windows. After a restart, all 17 terminals were back on their desktops in the right folders running claude --continue, all 23 Chrome windows were on their desktops, and nothing opened twice. The Claude Code session that ran the test picked up where it was.
Which terminal is which?
A terminal window has no stable identity across a restart. Its window number changes and its title is whatever the shell last printed. What does survive is the folder you were working in, so that is the key.
iTerm2 and Terminal both answer AppleScript with each window's id and each session's tty. The folder comes from the processes on that tty: Spacepal reads the process table once per pass with proc_listallpids, and for each process gets its controlling terminal (PROC_PIDTBSDINFO) and its working directory (PROC_PIDVNODEPATHINFO). The first real folder in a window, other than your home folder, names it.
The same table says what is running. One detail: the kernel's name for Claude Code is the executable file's name, which for a versioned install is something like 2.1.316, not claude. The name a program was started as comes from KERN_PROCARGS2 instead. If a window was running claude, it is saved with the command claude --continue. Nothing else is run again automatically, because running an arbitrary command twice can do real work twice. You can type a command for a terminal yourself if you want one.
Which desktop is it on?
macOS has no public API that says which Space a window is on. Spacepal asks the WindowServer for the Spaces of a window id, and only trusts the answer when it is exactly one Space. Chrome's AppleScript window ids are not WindowServer ids, so Chrome windows are matched to on-screen windows by position and size, then by the active tab's title when two windows are stacked in the same place. If it is still ambiguous, Spacepal leaves the window alone: moving the wrong window is worse than not moving one.
After the restart: wait first
The hard part is timing. After you log in, iTerm2 and Chrome reopen their own windows, and they take a while. If Spacepal opened what was missing straight away, you would get every window twice.
So after a restart it waits 8 seconds before reading the desktops, gives apps 20 seconds before launching any that are not running, and treats an app as settled only when it has been up for 15 seconds and its window count has stopped changing. It checks every 3 seconds and gives up after 5 minutes. Windows that came back are matched by folder (exact folders first, so a terminal in a parent folder cannot take a sub-project's window) and moved to their desktop. Only then does it open terminals that are still missing, three at a time.
A reopened terminal has an empty shell, because the restart ended what was running. If the shell is idle, Spacepal types cd into the saved folder followed by the saved command. It never types into a terminal where something is already running.
The bug the test found
Preparing the test, I counted 61 saved Chrome windows and 23 open ones. A restart would have reopened about 38 windows I had closed in the past week.
The saved list is updated in the background. A window that is missing might just not be back yet, so the update kept missing windows for 7 days before dropping them. Terminals with a command were never dropped at all, so every Claude Code window I had ever closed would have come back.
The fix in 1.2.9 uses the app's launch time. If a window was seen open after its app last launched, and is gone while the app is still running, you closed it, and it is removed. If the app quit or the Mac restarted, a missing window is kept, because it may still be on its way back. An app that could not be read completely, for example because one of its windows is in a full-screen Space, is never used to decide what was closed.
Limits
- It handles iTerm2, Terminal and Chrome. Other apps are placed by macOS, which often gets it wrong.
- Moving windows that are not in front only works on macOS 14.0 to 14.4 and 26.4 and later, with System Integrity Protection on.
- Only
claudeis resumed automatically. Anything else needs a command you type in yourself.
Spacepal is a paid Mac app with a 14-day free trial. See Spacepal for AI coding, or the guide to windows on the wrong desktop after a restart.
Written by Dan Bayer, developer of Spacepal. Last updated 2026-11-09.