diff --git a/src/tui/App.tsx b/src/tui/App.tsx
index 16983451..3dea5f0f 100644
--- a/src/tui/App.tsx
+++ b/src/tui/App.tsx
@@ -45,6 +45,7 @@ export function App(): React.ReactElement {
terminalOutput,
innerLoopState,
innerTodos,
+ respawnStatus,
} = useSessionManager();
// Calculate terminal height based on stdout dimensions
@@ -255,7 +256,7 @@ export function App(): React.ReactElement {
/>
)}
-
+
);
}
diff --git a/src/tui/components/StatusBar.tsx b/src/tui/components/StatusBar.tsx
index fc6b187f..164c9146 100644
--- a/src/tui/components/StatusBar.tsx
+++ b/src/tui/components/StatusBar.tsx
@@ -13,9 +13,16 @@ import React from 'react';
import { Box, Text } from 'ink';
import type { ScreenSession } from '../../types.js';
+interface RespawnStatus {
+ enabled: boolean;
+ state: string;
+ cycleCount: number;
+}
+
interface StatusBarProps {
session: ScreenSession | null;
inputMode?: boolean;
+ respawnStatus?: RespawnStatus | null;
}
/**
@@ -38,7 +45,7 @@ function formatDuration(ms: number): string {
/**
* StatusBar component showing session information
*/
-export function StatusBar({ session, inputMode = false }: StatusBarProps): React.ReactElement {
+export function StatusBar({ session, inputMode = false, respawnStatus }: StatusBarProps): React.ReactElement {
if (!session) {
return (
INPUT MODE
>
)}
+ {respawnStatus?.enabled && (
+ <>
+ |
+
+ respawn: {respawnStatus.state.replace(/_/g, ' ')}
+ {respawnStatus.cycleCount > 0 && ` (${respawnStatus.cycleCount})`}
+
+ >
+ )}
{/* Right side: Keyboard hints */}
diff --git a/src/tui/hooks/useSessionManager.ts b/src/tui/hooks/useSessionManager.ts
index 12600048..bb760f82 100644
--- a/src/tui/hooks/useSessionManager.ts
+++ b/src/tui/hooks/useSessionManager.ts
@@ -18,6 +18,12 @@ const SCREENS_FILE = join(homedir(), '.claudeman', 'screens.json');
const INNER_STATE_FILE = join(homedir(), '.claudeman', 'state-inner.json');
const OUTPUT_POLL_INTERVAL = 500; // Poll terminal output every 500ms
+interface RespawnStatus {
+ enabled: boolean;
+ state: string;
+ cycleCount: number;
+}
+
interface SessionManagerState {
sessions: ScreenSession[];
activeSessionId: string | null;
@@ -25,6 +31,7 @@ interface SessionManagerState {
terminalOutput: string;
innerLoopState: InnerLoopState | null;
innerTodos: InnerTodoItem[];
+ respawnStatus: RespawnStatus | null;
refreshSessions: () => void;
selectSession: (sessionId: string) => void;
createSession: () => Promise;
@@ -93,6 +100,7 @@ export function useSessionManager(): SessionManagerState {
const [terminalOutput, setTerminalOutput] = useState('');
const [innerLoopState, setInnerLoopState] = useState(null);
const [innerTodos, setInnerTodos] = useState([]);
+ const [respawnStatus, setRespawnStatus] = useState(null);
const outputBufferRef = useRef('');
// Load sessions on mount and watch for changes
@@ -153,6 +161,48 @@ export function useSessionManager(): SessionManagerState {
};
}, [activeSessionId]);
+ // Poll respawn status via API (when server is running)
+ useEffect(() => {
+ if (!activeSessionId) {
+ setRespawnStatus(null);
+ return;
+ }
+
+ const pollRespawnStatus = async () => {
+ try {
+ const response = await fetch(`http://localhost:3000/api/sessions/${activeSessionId}`);
+ if (response.ok) {
+ const data = await response.json() as {
+ success?: boolean;
+ session?: {
+ respawnEnabled?: boolean;
+ respawnState?: string;
+ respawnCycleCount?: number;
+ };
+ };
+ if (data.success && data.session) {
+ setRespawnStatus({
+ enabled: data.session.respawnEnabled || false,
+ state: data.session.respawnState || 'stopped',
+ cycleCount: data.session.respawnCycleCount || 0,
+ });
+ }
+ }
+ } catch {
+ // Server not running, that's ok
+ setRespawnStatus(null);
+ }
+ };
+
+ // Poll less frequently than output (every 2 seconds)
+ pollRespawnStatus();
+ const intervalId = setInterval(pollRespawnStatus, 2000);
+
+ return () => {
+ clearInterval(intervalId);
+ };
+ }, [activeSessionId]);
+
// Poll terminal output for active session
useEffect(() => {
if (!activeSessionId || !activeSession) return;
@@ -335,6 +385,7 @@ export function useSessionManager(): SessionManagerState {
terminalOutput,
innerLoopState,
innerTodos,
+ respawnStatus,
refreshSessions,
selectSession,
createSession,