Problem
Every time you switch away from the Shell tab and come back, you get a completely fresh bash session. If claude is running in that session, it's gone — and depending on OAuth token state, it asks for re-authentication. For Claude Code users, this means re-authenticating multiple times per day just from normal tab switching.
Root Cause
In src/server.ts, the WebSocket close handler unconditionally kills the PTY:
ws.on('close', () => {
sessions.delete(sessionId);
try { ptyProc.kill(); } catch { /* ignore */ }
});
There is no reconnect path — every new WebSocket connection spawns a fresh shell with a new session ID. The client-side code includes the comment "Sessions persist across mount/unmount (tab switching)", but the server does not honor that intent.
Impact
- Any long-running process in the Shell tab (claude, a build, a server) is killed on every tab switch
- Claude Code users must re-run
claude each time they return to the tab; if the OAuth access token is near expiry, this triggers the full re-authentication flow
- The "--- reconnected ---" message shown in the terminal gives the false impression that the session is preserved
Proposed Fix
Keep the PTY alive on WebSocket disconnect and reconnect to it on the next connection. A per-session timeout (e.g. 30 minutes) would handle cleanup for truly abandoned sessions:
// On disconnect: detach WebSocket but keep PTY alive
ws.on('close', () => {
const session = sessions.get(sessionId);
if (session) {
session.ws = null;
session.cleanupTimer = setTimeout(() => {
try { session.pty.kill(); } catch { /* ignore */ }
sessions.delete(sessionId);
}, 30 * 60 * 1000);
}
});
// On new connection: reuse existing session if available
wss.on('connection', (ws) => {
const existingEntry = [...sessions.entries()].find(([, s]) => s.ws === null);
if (existingEntry) {
const [sessionId, session] = existingEntry;
clearTimeout(session.cleanupTimer);
session.ws = ws;
// Reattach data handlers and send ready
return;
}
// No existing session — spawn fresh
});
Workaround
Until this is fixed, users can add a tmux auto-attach to .bashrc gated on $TERM_PROGRAM=web-terminal. The web-terminal kills the PTY (tmux client), but the tmux server keeps running, so long-running processes survive tab switches:
# At the end of ~/.bashrc
if [ -z "$TMUX" ] && [ "$TERM_PROGRAM" = "web-terminal" ]; then
exec tmux new-session -A -s main
fi
Problem
Every time you switch away from the Shell tab and come back, you get a completely fresh bash session. If claude is running in that session, it's gone — and depending on OAuth token state, it asks for re-authentication. For Claude Code users, this means re-authenticating multiple times per day just from normal tab switching.
Root Cause
In
src/server.ts, the WebSocket close handler unconditionally kills the PTY:There is no reconnect path — every new WebSocket connection spawns a fresh shell with a new session ID. The client-side code includes the comment "Sessions persist across mount/unmount (tab switching)", but the server does not honor that intent.
Impact
claudeeach time they return to the tab; if the OAuth access token is near expiry, this triggers the full re-authentication flowProposed Fix
Keep the PTY alive on WebSocket disconnect and reconnect to it on the next connection. A per-session timeout (e.g. 30 minutes) would handle cleanup for truly abandoned sessions:
Workaround
Until this is fixed, users can add a tmux auto-attach to
.bashrcgated on$TERM_PROGRAM=web-terminal. The web-terminal kills the PTY (tmux client), but the tmux server keeps running, so long-running processes survive tab switches: