feat(tui): add Delete All (D) to kill all screens and Claude processes

- Add killAllScreensAndClaude() function to useSessionManager
- Kills all tracked sessions, orphan claudeman screens, and Claude CLI processes
- Press 'D' (Shift+d) in sessions view to trigger
- Update HelpOverlay with new shortcut documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-21 10:35:35 +01:00
co-authored by Claude Opus 4.5
parent cb4cb202b9
commit e6ba373d12
4 changed files with 53 additions and 0 deletions
+2
View File
@@ -74,6 +74,7 @@ export function App(): React.ReactElement {
createCase,
killSession,
killAllSessions,
killAllScreensAndClaude,
nextSession,
prevSession,
sendInput,
@@ -339,6 +340,7 @@ export function App(): React.ReactElement {
onSelectSession={handleSelectSession}
onAttachSession={handleAttachSession}
onDeleteSession={handleDeleteSession}
onDeleteAll={killAllScreensAndClaude}
onCreateSession={handleCreateSession}
onCreateCase={createCase}
onRefresh={refreshSessions}
+1
View File
@@ -33,6 +33,7 @@ const SHORTCUT_GROUPS: ShortcutGroup[] = [
{ key: 'Enter', description: 'View session in TUI' },
{ key: 'a', description: 'Attach to screen (full terminal)' },
{ key: 'd', description: 'Delete/kill selected session' },
{ key: 'D (Shift+d)', description: 'Delete ALL screens & Claude processes' },
{ key: 'c', description: 'Switch to cases view' },
{ key: 'n', description: 'Quick-start new session' },
{ key: 'r', description: 'Refresh list' },
+10
View File
@@ -30,6 +30,7 @@ interface StartScreenProps {
onSelectSession: (session: ScreenSession) => void;
onAttachSession: (session: ScreenSession) => void;
onDeleteSession: (session: ScreenSession) => void;
onDeleteAll: () => void;
onCreateSession: (caseName?: string, count?: number, mode?: 'claude' | 'shell') => void;
onCreateCase: (name: string) => Promise<boolean>;
onRefresh: () => void;
@@ -80,6 +81,7 @@ export function StartScreen({
onSelectSession,
onAttachSession,
onDeleteSession,
onDeleteAll,
onCreateSession,
onCreateCase,
onRefresh,
@@ -168,6 +170,12 @@ export function StartScreen({
return;
}
// 'D' (shift+d) to delete ALL screens and Claude processes
if (input === 'D') {
onDeleteAll();
return;
}
// 'c' to switch to cases view
if (input === 'c') {
onRefreshCases();
@@ -513,6 +521,8 @@ export function StartScreen({
<Text> Attach </Text>
<Text color="red">[d]</Text>
<Text> Delete </Text>
<Text color="red" bold>[D]</Text>
<Text> Delete ALL </Text>
<Text color="yellow">[q]</Text>
<Text> Quit</Text>
</Text>
+40
View File
@@ -156,6 +156,7 @@ interface SessionManagerState {
createCase: (name: string) => Promise<boolean>;
killSession: (sessionId: string) => void;
killAllSessions: () => void;
killAllScreensAndClaude: () => void;
nextSession: () => void;
prevSession: () => void;
sendInput: (sessionId: string, input: string) => void;
@@ -576,6 +577,44 @@ export function useSessionManager(): SessionManagerState {
setTimeout(refreshSessions, 500);
}, [sessions, refreshSessions]);
// Kill ALL claudeman screens and Claude processes (nuclear option)
const killAllScreensAndClaude = useCallback(() => {
// 1. Kill all tracked sessions first
for (const session of sessions) {
try {
execSync(`screen -S ${session.screenName} -X quit`, {
encoding: 'utf-8',
timeout: 5000,
});
} catch {
// Ignore
}
}
// 2. Kill any remaining claudeman screen sessions
try {
execSync('pkill -f "SCREEN.*claudeman"', {
encoding: 'utf-8',
timeout: 5000,
});
} catch {
// May not find any, that's ok
}
// 3. Kill all Claude CLI processes
try {
execSync('pkill -f "claude"', {
encoding: 'utf-8',
timeout: 5000,
});
} catch {
// May not find any, that's ok
}
setActiveSessionId(null);
setTimeout(refreshSessions, 500);
}, [sessions, refreshSessions]);
// Navigate to next session
const nextSession = useCallback(() => {
if (sessions.length === 0) return;
@@ -684,6 +723,7 @@ export function useSessionManager(): SessionManagerState {
createCase,
killSession,
killAllSessions,
killAllScreensAndClaude,
nextSession,
prevSession,
sendInput,