Goal
Don't leave stale terminal sessions open indefinitely. Add a user-configurable idle timeout that auto-closes sessions after N minutes of inactivity, default-on with a sensible value.
Current state
The mechanism already exists internally — it's just not exposed:
src/terminal/terminal-manager.ts
DEFAULT_IDLE_TIMEOUT = 30 * 60 * 1000 (30 min, hardcoded)
DEFAULT_CLEANUP_INTERVAL = 60 * 1000 (sweep every minute)
lastActivityAt is updated on transport data events (output) and on sendInput / sendKeys (input)
cleanupIdleTerminals() closes sessions where now - lastActivityAt > idleTimeoutMs
TerminalManagerOptions.idleTimeoutMs is accepted but never wired from config — src/index.ts:95 constructs new TerminalManager(endpointRepo, …) with no options, so production always uses the 30 min default.
- No Settings UI surface for it today.
Scope
- Config schema: add
terminal.idleTimeoutMinutes (or similar) to src/config/schema.ts with a default. Wire it through to the TerminalManager constructor in src/index.ts.
- Settings UI: add a control on the Settings page — toggle (default on) + numeric minutes input. Disabling the toggle should pass
idleTimeoutMs: Infinity / 0 (whatever the agreed sentinel is) so cleanup is skipped.
- Persistence: needs to live wherever runtime-editable settings already live (config file vs. DB-backed settings — pick whichever pattern the rest of Settings uses; there's no precedent yet for runtime-editable terminal settings).
- Default: keep 30 min as the default, or revisit (15 min? 60 min?) — open to discussion.
Open questions
- What counts as activity? Today, output data resets the idle clock too. That means a session running
tail -f or top is never idle. Options:
- Keep current behavior (output = activity) — predictable, won't kill long-running tails the user cares about.
- Input-only — closes "I forgot this tab" sessions that are still streaming output. More aggressive, probably what most users actually want.
- Two separate thresholds (input-idle vs. output-idle).
Recommend (2) but worth confirming.
- Close behavior on auto-close: do we surface a notice in the UI / send a final output line so the user understands why the session went away? Currently it just transitions to
closed.
- Per-endpoint override? Probably overkill for a first pass — a single global setting is fine.
Non-goals
- Server-side
ClientAliveInterval / SSH keepalive tuning. This is purely about the ShellWatch session-broker layer.
- Closing the web UI tab on idle. This is about the underlying SSH session, not the browser session.
Goal
Don't leave stale terminal sessions open indefinitely. Add a user-configurable idle timeout that auto-closes sessions after N minutes of inactivity, default-on with a sensible value.
Current state
The mechanism already exists internally — it's just not exposed:
src/terminal/terminal-manager.tsDEFAULT_IDLE_TIMEOUT = 30 * 60 * 1000(30 min, hardcoded)DEFAULT_CLEANUP_INTERVAL = 60 * 1000(sweep every minute)lastActivityAtis updated on transportdataevents (output) and onsendInput/sendKeys(input)cleanupIdleTerminals()closes sessions wherenow - lastActivityAt > idleTimeoutMsTerminalManagerOptions.idleTimeoutMsis accepted but never wired from config —src/index.ts:95constructsnew TerminalManager(endpointRepo, …)with no options, so production always uses the 30 min default.Scope
terminal.idleTimeoutMinutes(or similar) tosrc/config/schema.tswith a default. Wire it through to theTerminalManagerconstructor insrc/index.ts.idleTimeoutMs: Infinity/0(whatever the agreed sentinel is) so cleanup is skipped.Open questions
tail -fortopis never idle. Options:Recommend (2) but worth confirming.
closed.Non-goals
ClientAliveInterval/ SSH keepalive tuning. This is purely about the ShellWatch session-broker layer.