mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 08:59:40 +02:00
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:
@@ -74,6 +74,7 @@ export function App(): React.ReactElement {
|
|||||||
createCase,
|
createCase,
|
||||||
killSession,
|
killSession,
|
||||||
killAllSessions,
|
killAllSessions,
|
||||||
|
killAllScreensAndClaude,
|
||||||
nextSession,
|
nextSession,
|
||||||
prevSession,
|
prevSession,
|
||||||
sendInput,
|
sendInput,
|
||||||
@@ -339,6 +340,7 @@ export function App(): React.ReactElement {
|
|||||||
onSelectSession={handleSelectSession}
|
onSelectSession={handleSelectSession}
|
||||||
onAttachSession={handleAttachSession}
|
onAttachSession={handleAttachSession}
|
||||||
onDeleteSession={handleDeleteSession}
|
onDeleteSession={handleDeleteSession}
|
||||||
|
onDeleteAll={killAllScreensAndClaude}
|
||||||
onCreateSession={handleCreateSession}
|
onCreateSession={handleCreateSession}
|
||||||
onCreateCase={createCase}
|
onCreateCase={createCase}
|
||||||
onRefresh={refreshSessions}
|
onRefresh={refreshSessions}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const SHORTCUT_GROUPS: ShortcutGroup[] = [
|
|||||||
{ key: 'Enter', description: 'View session in TUI' },
|
{ key: 'Enter', description: 'View session in TUI' },
|
||||||
{ key: 'a', description: 'Attach to screen (full terminal)' },
|
{ key: 'a', description: 'Attach to screen (full terminal)' },
|
||||||
{ key: 'd', description: 'Delete/kill selected session' },
|
{ 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: 'c', description: 'Switch to cases view' },
|
||||||
{ key: 'n', description: 'Quick-start new session' },
|
{ key: 'n', description: 'Quick-start new session' },
|
||||||
{ key: 'r', description: 'Refresh list' },
|
{ key: 'r', description: 'Refresh list' },
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ interface StartScreenProps {
|
|||||||
onSelectSession: (session: ScreenSession) => void;
|
onSelectSession: (session: ScreenSession) => void;
|
||||||
onAttachSession: (session: ScreenSession) => void;
|
onAttachSession: (session: ScreenSession) => void;
|
||||||
onDeleteSession: (session: ScreenSession) => void;
|
onDeleteSession: (session: ScreenSession) => void;
|
||||||
|
onDeleteAll: () => void;
|
||||||
onCreateSession: (caseName?: string, count?: number, mode?: 'claude' | 'shell') => void;
|
onCreateSession: (caseName?: string, count?: number, mode?: 'claude' | 'shell') => void;
|
||||||
onCreateCase: (name: string) => Promise<boolean>;
|
onCreateCase: (name: string) => Promise<boolean>;
|
||||||
onRefresh: () => void;
|
onRefresh: () => void;
|
||||||
@@ -80,6 +81,7 @@ export function StartScreen({
|
|||||||
onSelectSession,
|
onSelectSession,
|
||||||
onAttachSession,
|
onAttachSession,
|
||||||
onDeleteSession,
|
onDeleteSession,
|
||||||
|
onDeleteAll,
|
||||||
onCreateSession,
|
onCreateSession,
|
||||||
onCreateCase,
|
onCreateCase,
|
||||||
onRefresh,
|
onRefresh,
|
||||||
@@ -168,6 +170,12 @@ export function StartScreen({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 'D' (shift+d) to delete ALL screens and Claude processes
|
||||||
|
if (input === 'D') {
|
||||||
|
onDeleteAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 'c' to switch to cases view
|
// 'c' to switch to cases view
|
||||||
if (input === 'c') {
|
if (input === 'c') {
|
||||||
onRefreshCases();
|
onRefreshCases();
|
||||||
@@ -513,6 +521,8 @@ export function StartScreen({
|
|||||||
<Text> Attach </Text>
|
<Text> Attach </Text>
|
||||||
<Text color="red">[d]</Text>
|
<Text color="red">[d]</Text>
|
||||||
<Text> Delete </Text>
|
<Text> Delete </Text>
|
||||||
|
<Text color="red" bold>[D]</Text>
|
||||||
|
<Text> Delete ALL </Text>
|
||||||
<Text color="yellow">[q]</Text>
|
<Text color="yellow">[q]</Text>
|
||||||
<Text> Quit</Text>
|
<Text> Quit</Text>
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ interface SessionManagerState {
|
|||||||
createCase: (name: string) => Promise<boolean>;
|
createCase: (name: string) => Promise<boolean>;
|
||||||
killSession: (sessionId: string) => void;
|
killSession: (sessionId: string) => void;
|
||||||
killAllSessions: () => void;
|
killAllSessions: () => void;
|
||||||
|
killAllScreensAndClaude: () => void;
|
||||||
nextSession: () => void;
|
nextSession: () => void;
|
||||||
prevSession: () => void;
|
prevSession: () => void;
|
||||||
sendInput: (sessionId: string, input: string) => void;
|
sendInput: (sessionId: string, input: string) => void;
|
||||||
@@ -576,6 +577,44 @@ export function useSessionManager(): SessionManagerState {
|
|||||||
setTimeout(refreshSessions, 500);
|
setTimeout(refreshSessions, 500);
|
||||||
}, [sessions, refreshSessions]);
|
}, [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
|
// Navigate to next session
|
||||||
const nextSession = useCallback(() => {
|
const nextSession = useCallback(() => {
|
||||||
if (sessions.length === 0) return;
|
if (sessions.length === 0) return;
|
||||||
@@ -684,6 +723,7 @@ export function useSessionManager(): SessionManagerState {
|
|||||||
createCase,
|
createCase,
|
||||||
killSession,
|
killSession,
|
||||||
killAllSessions,
|
killAllSessions,
|
||||||
|
killAllScreensAndClaude,
|
||||||
nextSession,
|
nextSession,
|
||||||
prevSession,
|
prevSession,
|
||||||
sendInput,
|
sendInput,
|
||||||
|
|||||||
Reference in New Issue
Block a user