From f8fa4f1ff6c99204df16e4a17d1e7a3d0e8d1163 Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 29 May 2026 23:25:53 -0700 Subject: [PATCH] fix: lower default auto-kill idle timeout from 180 to 15 minutes Detached terminals previously survived up to 3 hours of idle, which accumulates running-but-orphaned PTYs toward the 50-terminal cap. Lower the default `safety.autoKillIdleMinutes` to 15 so idle detached terminals are reaped promptly and the running count stays well under the limit. Also drop the Safety slider min/step from 10 to 5 so the new 15-minute default is a reachable slider stop and finer values are selectable. Co-Authored-By: Claude Opus 4.8 (1M context) --- AGENTS.md | 2 +- shared/settings.ts | 2 +- src/components/settings/SafetySettings.tsx | 4 ++-- test/unit/client/components/SettingsView.behavior.test.tsx | 2 +- test/unit/shared/settings.test.ts | 1 + 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 930661144..3d01994db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -115,7 +115,7 @@ npm run test:vitest -- ... # Repo-owned direct Vitest path for focused passthro **WebSocket Protocol:** Schema-validated messages using Zod. Handshake flow: client sends `hello` with token → server validates → sends `ready`. Message types include `terminal.create/input/resize/detach/attach` and broadcasts like `sessions.updated`. -**PTY Lifecycle:** Each terminal has a unique ID. Server maintains 64KB scrollback buffer. On attach, client receives buffer snapshot then streams new output. On detach, process continues running (background session). Configurable idle timeout (180 mins default). +**PTY Lifecycle:** Each terminal has a unique ID. Server maintains 64KB scrollback buffer. On attach, client receives buffer snapshot then streams new output. On detach, process continues running (background session). Configurable idle timeout (15 mins default). **Claude Session Discovery:** Watches `~/.claude/projects/*/sessions/*.jsonl` for new files. Parses JSONL streams to extract messages, groups by project path. diff --git a/shared/settings.ts b/shared/settings.ts index ee1f34356..9608eced5 100644 --- a/shared/settings.ts +++ b/shared/settings.ts @@ -725,7 +725,7 @@ export function createDefaultServerSettings(options: SettingsDefaultsOptions = { debug: options.loggingDebug ?? false, }, safety: { - autoKillIdleMinutes: 180, + autoKillIdleMinutes: 15, }, terminal: { scrollback: 10000, diff --git a/src/components/settings/SafetySettings.tsx b/src/components/settings/SafetySettings.tsx index 4c49aa08b..8cdc4e41f 100644 --- a/src/components/settings/SafetySettings.tsx +++ b/src/components/settings/SafetySettings.tsx @@ -498,9 +498,9 @@ export default function SafetySettings({ String(v)} onChange={(v) => { applyServerSetting({ safety: { autoKillIdleMinutes: v } }) diff --git a/test/unit/client/components/SettingsView.behavior.test.tsx b/test/unit/client/components/SettingsView.behavior.test.tsx index e267187ef..90824299e 100644 --- a/test/unit/client/components/SettingsView.behavior.test.tsx +++ b/test/unit/client/components/SettingsView.behavior.test.tsx @@ -327,7 +327,7 @@ describe('SettingsView behavior sections', () => { const autoKillSlider = getSlider((slider) => { const min = slider.getAttribute('min') const max = slider.getAttribute('max') - return min === '10' && max === '720' + return min === '5' && max === '720' }) fireEvent.change(autoKillSlider, { target: { value: '300' } }) diff --git a/test/unit/shared/settings.test.ts b/test/unit/shared/settings.test.ts index 96f63fe5f..f213efcdd 100644 --- a/test/unit/shared/settings.test.ts +++ b/test/unit/shared/settings.test.ts @@ -176,6 +176,7 @@ describe('shared settings contract', () => { expect(resolved.terminal.fontFamily).toBe('Fira Code') expect(resolved.terminal.scrollback).toBe(10000) + expect(resolved.safety.autoKillIdleMinutes).toBe(15) expect(resolved.sidebar.sortMode).toBe('project') expect(resolved.agentChat.defaultPlugins).toEqual([]) })