
There are times when I am embarrassed to realize that I have accepted a painful limitation for years. In this case, it is my resistance to restarting my IDEs because I don’t want to lose my terminals. Now, thanks to a burst of motivation and a modern chatbot, I’m setup for my IDEs to resume exactly where they left off.
TL;DR: show me the code
VSCode / Cursor Config
{
"terminal.integrated.profiles.osx": {
"ide-persistent-shell": {
"path": "/Users/yourusername/.local/bin/ide-persistent-shell"
}
},
"terminal.integrated.defaultProfile.osx": "ide-persistent-shell",
"terminal.integrated.env.osx": {
"EDITOR_ID": "cursor"
},
"terminal.integrated.enablePersistentSessions": true
}
Main script
#!/bin/bash
# ~/.local/bin/ide-persistent-shell
# Get editor identifier from environment variable (defaults to 'vscode')
EDITOR_ID="${EDITOR_ID:-vscode}"
PROJECT_NAME=$(basename "$(pwd)")
SESSION_PREFIX="${EDITOR_ID}-${PROJECT_NAME}"
STATE_FILE="/tmp/tmux-${EDITOR_ID}-${PROJECT_NAME}-counter"
# Initialize counter file if it doesn't exist
if [ ! -f "$STATE_FILE" ]; then
echo "0" > "$STATE_FILE"
fi
# Find existing sessions for this project and editor
existing_sessions=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | grep "^${SESSION_PREFIX}-" || true)
if [ -n "$existing_sessions" ]; then
# Try to find an unattached session
for session in $existing_sessions; do
is_attached=$(tmux list-sessions -F "#{session_name}:#{session_attached}" 2>/dev/null | grep "^${session}:" | cut -d: -f2)
if [ "$is_attached" = "0" ]; then
echo "Reattaching to: $session"
tmux attach -t "$session"
exit 0
fi
done
fi
# No unattached sessions found, create new one
counter=$(cat "$STATE_FILE")
counter=$((counter + 1))
echo "$counter" > "$STATE_FILE"
new_session="${SESSION_PREFIX}-${counter}"
echo "Creating new session: $new_session"
tmux new -s "$new_session"
If you’re an old head working in the terminal, you probably that the tools for this job are screen and tmux. I used to use those regularly, but something about how my brain works makes me friction-avoidant. So I fell out of using those before I ever adopted VSCode, and I kind of never bothered to reintegrate them.
To make this whole thing automatic, I knew I’d have to do some scripting, and for me, there’s no bigger rabbit hole than having to do some scripting. I don’t do it enough to have the muscle memory, so I end up having to relearn the arcane flags and best practices every time. And then I’d also have to figure out how to configure my IDEs to use my script.
I described my problem, and less than 5 minutes, I had a working solution. You might note that I still needed a strong notion of what I was doing for it to be that easy. But I have found these LLM tools to be incredibly good engines for transforming intention + background knowledge + written communication into solutions.
Now, I just need a local(ish) terminal that can survive reboots 😉
