2026-01-18 05:14:34 +01:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
2026-01-31 08:02:27 +01:00
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
2026-01-18 22:04:02 +01:00
< meta name = "description" content = "Claude Code session manager with web interface" >
< meta name = "theme-color" content = "#0a0a0a" >
2026-01-18 05:14:34 +01:00
< title > Claudeman</ title >
2026-01-18 22:04:02 +01:00
< link rel = "icon" type = "image/svg+xml" href = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0%25' y1='0%25' x2='100%25' y2='100%25'%3E%3Cstop offset='0%25' stop-color='%2360a5fa'/%3E%3Cstop offset='100%25' stop-color='%233b82f6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='32' height='32' rx='6' fill='%230a0a0a'/%3E%3Cpath d='M18 4L8 18h6l-2 10 10-14h-6z' fill='url(%23g)'/%3E%3C/svg%3E" >
2026-02-13 21:21:33 +01:00
<!-- DNS preconnect for CDN — saves ~100ms on first load -->
< link rel = "preconnect" href = "https://cdn.jsdelivr.net" crossorigin >
< link rel = "dns-prefetch" href = "https://cdn.jsdelivr.net" >
2026-01-18 05:14:34 +01:00
< link rel = "stylesheet" href = "styles.css" >
2026-01-18 07:31:19 +01:00
< link rel = "stylesheet" href = "https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" >
2026-02-13 21:21:33 +01:00
<!-- Defer CDN scripts — they no longer block initial HTML parsing/paint.
'defer' preserves execution order (xterm loads before fit addon). -->
< script defer src = "https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js" ></ script >
< script defer src = "https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js" ></ script >
2026-01-18 05:14:34 +01:00
</ head >
< body >
2026-01-30 14:14:45 +01:00
<!-- Skip link for keyboard users -->
< a href = "#terminalContainer" class = "skip-link" > Skip to terminal</ a >
2026-01-18 05:14:34 +01:00
< div class = "app" >
2026-01-19 00:38:11 +01:00
<!-- Compact Header with Session Tabs -->
2026-01-18 05:14:34 +01:00
< header class = "header" >
2026-01-19 00:38:11 +01:00
< div class = "header-brand" >
2026-01-26 23:37:14 +01:00
< span class = "logo" onclick = "app.goHome()" title = "Go to main page" > Claudeman</ span >
2026-01-19 00:38:11 +01:00
</ div >
<!-- Session Tabs -->
2026-01-30 14:14:45 +01:00
< div class = "session-tabs" id = "sessionTabs" role = "tablist" aria-label = "Session tabs" >
2026-01-18 05:14:34 +01:00
</ div >
2026-01-19 00:38:11 +01:00
< div class = "header-right" >
2026-02-12 08:34:51 +01:00
< div class = "connection-indicator" id = "connectionIndicator" style = "display: none;" >
< span class = "connection-dot" id = "connectionDot" ></ span >
< span class = "connection-text" id = "connectionText" ></ span >
</ div >
2026-01-19 02:48:28 +01:00
< div class = "header-font-controls" >
2026-01-30 14:14:45 +01:00
< button class = "btn-icon-header btn-sm" onclick = "app.decreaseFontSize()" title = "Decrease font (Ctrl+-)" aria-label = "Decrease font size" > A-</ button >
< span class = "font-size-display" id = "fontSizeDisplay" aria-label = "Current font size" > 14</ span >
< button class = "btn-icon-header btn-sm" onclick = "app.increaseFontSize()" title = "Increase font (Ctrl++)" aria-label = "Increase font size" > A+</ button >
2026-01-19 02:48:28 +01:00
</ div >
2026-01-19 06:51:25 +01:00
< div class = "header-system-stats" id = "headerSystemStats" title = "System resource usage" >
2026-01-19 10:36:30 +01:00
< div class = "stat-item" >
< span class = "stat-label" > CPU</ span >
< div class = "stat-bar" >
< div class = "stat-bar-fill stat-bar-cpu" id = "statCpuBar" ></ div >
</ div >
< span class = "stat-value" id = "statCpu" > --%</ span >
</ div >
2026-01-24 19:57:28 +01:00
< div class = "stat-item" >
< span class = "stat-label" > MEM</ span >
< div class = "stat-bar" >
< div class = "stat-bar-fill stat-bar-mem" id = "statMemBar" ></ div >
</ div >
< span class = "stat-value" id = "statMem" > --</ span >
</ div >
2026-01-19 06:51:25 +01:00
</ div >
2026-01-30 14:14:45 +01:00
< button class = "btn-icon-header btn-notifications" onclick = "app.toggleNotifications()" title = "Notifications" aria-label = "Toggle notifications" >
< svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" aria-hidden = "true" >< path d = "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />< path d = "M13.73 21a2 2 0 0 1-3.46 0" /></ svg >
2026-01-24 01:22:53 +01:00
< span class = "notification-badge" id = "notifBadge" style = "display:none;" > 0</ span >
</ button >
2026-01-30 14:14:45 +01:00
< button class = "btn-icon-header btn-settings" onclick = "app.openAppSettings()" title = "App Settings" aria-label = "Open app settings" >< svg width = "16" height = "16" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" stroke-linecap = "round" stroke-linejoin = "round" aria-hidden = "true" >< circle cx = "12" cy = "12" r = "3" />< path d = "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" /></ svg ></ button >
2026-01-19 11:36:13 +01:00
< div class = "header-tokens" id = "headerTokens" title = "Total tokens across all sessions" > 0 tokens</ div >
2026-01-18 05:14:34 +01:00
</ div >
</ header >
<!-- Timer Banner (shown when timed run is active) -->
< div class = "timer-banner" id = "timerBanner" style = "display: none;" >
2026-01-19 00:38:11 +01:00
< div class = "timer-content" >
2026-01-18 05:14:34 +01:00
< span class = "timer-value" id = "timerValue" > 00:00:00</ span >
2026-01-19 00:38:11 +01:00
< div class = "timer-progress" >< div class = "timer-progress-fill" id = "timerProgress" ></ div ></ div >
< span class = "timer-meta" id = "timerMeta" > 0 tasks | $0.00</ span >
2026-01-18 05:14:34 +01:00
</ div >
2026-01-30 14:14:45 +01:00
< button class = "btn-icon-only" onclick = "app.stopCurrentRun()" title = "Stop" aria-label = "Stop current run" > ■ </ button >
2026-01-18 05:14:34 +01:00
</ div >
2026-01-26 02:21:34 +01:00
<!-- Respawn Banner - Compact 2-column layout -->
2026-01-18 07:31:19 +01:00
< div class = "respawn-banner" id = "respawnBanner" style = "display: none;" >
2026-01-26 02:21:34 +01:00
< div class = "respawn-compact-layout" >
< div class = "respawn-status-col" >
< div class = "respawn-status-row1" >
< span class = "respawn-indicator" > ↻ </ span >
< span class = "respawn-state" id = "respawnState" > Watching</ span >
< span class = "detection-confidence" id = "detectionConfidence" ></ span >
< span class = "respawn-cycles" > #< span id = "respawnCycleCount" > 0</ span ></ span >
< span class = "respawn-timer" id = "respawnTimer" style = "display: none;" ></ span >
< span class = "respawn-tokens" id = "respawnTokens" style = "display: none;" ></ span >
2026-01-30 14:14:45 +01:00
< button class = "btn-icon-only" onclick = "app.stopRespawn()" title = "Stop Respawn" aria-label = "Stop respawn" > ■ </ button >
2026-01-26 02:21:34 +01:00
</ div >
< div class = "respawn-status-row2" id = "respawnStatusRow2" >
< span class = "detection-hook" id = "detectionHook" style = "display: none;" ></ span >
< span class = "detection-ai-check" id = "detectionAiCheck" style = "display: none;" ></ span >
< span class = "detection-status" id = "detectionStatus" ></ span >
< span class = "detection-waiting" id = "detectionWaiting" style = "display: none;" ></ span >
< div class = "respawn-countdown-timers" id = "respawnCountdownTimers" ></ div >
</ div >
</ div >
2026-01-25 04:57:09 +01:00
< div class = "respawn-action-log" id = "respawnActionLog" ></ div >
2026-01-25 03:57:44 +01:00
</ div >
2026-01-18 07:31:19 +01:00
</ div >
2026-01-21 22:36:45 +01:00
<!-- Ralph / Todo Tracker Panel -->
< div class = "ralph-panel collapsed" id = "ralphStatePanel" style = "display: none;" >
2026-01-19 17:09:56 +01:00
<!-- Collapsed Summary Bar -->
2026-01-19 18:41:14 +01:00
< div class = "ralph-summary" id = "ralphSummary" >
2026-01-21 22:36:45 +01:00
< div class = "ralph-summary-content" onclick = "app.toggleRalphStatePanel()" >
2026-01-19 18:41:14 +01:00
< div class = "ralph-ring-mini" id = "ralphRingMini" >
< svg viewBox = "0 0 36 36" class = "ralph-ring-svg" >
2026-01-20 20:00:57 +01:00
< defs >
< linearGradient id = "ralphGradientMini" x1 = "0%" y1 = "0%" x2 = "100%" y2 = "100%" >
< stop offset = "0%" stop-color = "#3b82f6" />
< stop offset = "100%" stop-color = "#22c55e" />
</ linearGradient >
</ defs >
2026-01-19 18:41:14 +01:00
< circle class = "ralph-ring-bg" cx = "18" cy = "18" r = "15.9" />
2026-01-27 11:02:02 +01:00
< circle class = "ralph-ring-progress-mini" cx = "18" cy = "18" r = "15.9" id = "ralphRingMiniProgress" style = "stroke-dashoffset: 100" />
2026-01-19 18:41:14 +01:00
</ svg >
< span class = "ralph-ring-text" id = "ralphRingMiniText" > 0%</ span >
</ div >
< div class = "ralph-summary-info" >
2026-01-21 22:36:45 +01:00
< span class = "ralph-title" > Ralph / Todo Tracker</ span >
2026-01-19 18:41:14 +01:00
< span class = "ralph-status-badge" id = "ralphStatusBadge" >
< span class = "ralph-status-dot" ></ span >
< span class = "ralph-status-text" > Idle</ span >
</ span >
</ div >
< div class = "ralph-summary-stats" >
< span class = "ralph-stat" >< span class = "ralph-stat-icon" > ⏱ </ span >< span id = "ralphStatTime" > 0m</ span ></ span >
< span class = "ralph-stat" >< span class = "ralph-stat-icon" > ✓ </ span >< span id = "ralphStatTasks" > 0/0</ span ></ span >
</ div >
2026-01-20 18:56:55 +01:00
< span class = "ralph-toggle" id = "ralphToggle" > ▼ </ span >
2026-01-19 17:09:56 +01:00
</ div >
2026-01-19 18:41:14 +01:00
< div class = "ralph-controls" >
2026-01-27 01:02:38 +01:00
< div class = "ralph-menu-container" >
< button class = "btn-icon-sm" onclick = "event.stopPropagation(); app.toggleRalphMenu()" title = "Fix Plan Menu" id = "ralphMenuBtn" > ☰ </ button >
< div class = "ralph-dropdown" id = "ralphDropdown" >
< button onclick = "event.stopPropagation(); app.showFixPlan(); app.closeRalphMenu()" > View Fix Plan</ button >
< button onclick = "event.stopPropagation(); app.writeFixPlanToFile(); app.closeRalphMenu()" > Write to File</ button >
< button onclick = "event.stopPropagation(); app.importFixPlanFromFile(); app.closeRalphMenu()" > Import from File</ button >
< hr >
< button onclick = "event.stopPropagation(); app.resetCircuitBreaker(); app.closeRalphMenu()" > Reset Circuit Breaker</ button >
</ div >
</ div >
2026-01-20 17:37:49 +01:00
< button class = "btn-icon-sm" onclick = "event.stopPropagation(); app.toggleRalphDetach()" title = "Detach/Attach panel" id = "ralphDetachBtn" > ⧉ </ button >
2026-01-20 17:54:59 +01:00
< button class = "btn-icon-sm" onclick = "event.stopPropagation(); app.closeRalphTracker()" title = "Close tracker" > × </ button >
2026-01-19 17:09:56 +01:00
</ div >
</ div >
2026-01-20 17:59:34 +01:00
<!-- Expanded Detail View - Compact horizontal layout -->
2026-01-19 17:09:56 +01:00
< div class = "ralph-detail" id = "ralphDetail" >
2026-01-20 17:59:34 +01:00
< div class = "ralph-detail-row" >
<!-- Progress Ring -->
< div class = "ralph-ring-compact" >
2026-01-19 17:09:56 +01:00
< svg viewBox = "0 0 100 100" class = "ralph-ring-svg-large" >
< defs >
< linearGradient id = "ralphGradient" x1 = "0%" y1 = "0%" x2 = "100%" y2 = "100%" >
< stop offset = "0%" stop-color = "#3b82f6" />
< stop offset = "100%" stop-color = "#22c55e" />
</ linearGradient >
</ defs >
< circle class = "ralph-ring-track" cx = "50" cy = "50" r = "42" />
2026-01-27 11:02:02 +01:00
< circle class = "ralph-ring-fill" cx = "50" cy = "50" r = "42" id = "ralphRingProgress" style = "stroke-dashoffset: 264" />
2026-01-19 17:09:56 +01:00
</ svg >
< div class = "ralph-ring-center" >
< div class = "ralph-ring-percent" id = "ralphRingPercent" > 0%</ div >
< div class = "ralph-ring-label" > Complete</ div >
</ div >
</ div >
2026-01-20 20:26:04 +01:00
<!-- Meta Info + Tasks unified -->
< div class = "ralph-info-unified" >
< div class = "ralph-info-labels" >
< div class = "ralph-info-row" >
2026-01-20 20:35:00 +01:00
< span class = "ralph-info-label" > Tasks</ span >
< span class = "ralph-tasks-count" id = "ralphTasksCount" > 0/0</ span >
</ div >
< div class = "ralph-info-row" >
< span class = "ralph-info-label" > Phrase</ span >
2026-01-20 20:26:04 +01:00
< code id = "ralphPhrase" > --</ code >
</ div >
< div class = "ralph-info-row" >
< span class = "ralph-info-label" > Elapsed</ span >
< span id = "ralphElapsed" > 0m</ span >
</ div >
2026-01-27 23:15:25 +01:00
< div class = "ralph-info-row" id = "ralphVersionRow" style = "display: none;" >
< span class = "ralph-info-label" > Plan</ span >
< div class = "ralph-version-info" >
< span class = "version-badge" id = "ralphPlanVersion" > v1</ span >
< button class = "rollback-btn" id = "ralphRollbackBtn" onclick = "app.showPlanHistory()" title = "View history" > history</ button >
</ div >
</ div >
2026-01-20 17:59:34 +01:00
</ div >
< div class = "ralph-tasks-grid" id = "ralphTasksGrid" ></ div >
2026-01-19 17:09:56 +01:00
</ div >
</ div >
</ div >
2026-01-19 13:21:01 +01:00
</ div >
2026-01-19 00:38:11 +01:00
<!-- Main Terminal Area -->
2026-01-18 05:14:34 +01:00
< main class = "main" >
2026-01-19 00:38:11 +01:00
< div class = "terminal-container" id = "terminalContainer" ></ div >
2026-01-29 12:47:23 +01:00
<!-- Welcome Overlay (shown when no session active) -->
< div class = "welcome-overlay" id = "welcomeOverlay" >
< div class = "welcome-content" >
< h1 class = "welcome-title" > Claudeman Terminal</ h1 >
2026-02-12 13:44:07 +01:00
< p class = "welcome-desc" > Each instance opens a persistent tmux session running Claude or Shell.</ p >
2026-01-29 12:47:23 +01:00
< p class = "welcome-desc" > Sessions stay alive for autonomous work, even if you close this browser.</ p >
< div class = "welcome-actions" >
< button class = "welcome-btn welcome-btn-primary" onclick = "app.runClaude()" >
< svg width = "20" height = "20" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< polygon points = "5 3 19 12 5 21 5 3" /></ svg >
Run Claude
</ button >
< button class = "welcome-btn welcome-btn-ralph" onclick = "app.showRalphWizard()" >
< svg width = "20" height = "20" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< circle cx = "12" cy = "12" r = "10" />< path d = "M12 6v6l4 2" /></ svg >
Start Ralph Loop Wizard
</ button >
</ div >
< p class = "welcome-hint" > Or press < kbd > Ctrl</ kbd > +< kbd > Enter</ kbd > to start Claude</ p >
</ div >
</ div >
2026-01-18 05:14:34 +01:00
</ main >
2026-01-26 00:15:11 +01:00
<!-- Project Insights Panel (shows file-viewing Bash commands) -->
< div class = "project-insights-panel" id = "projectInsightsPanel" >
< div class = "project-insights-header" >
< span class = "project-insights-title" > Project Insights</ span >
< button class = "btn-icon-sm" onclick = "app.closeProjectInsightsPanel()" title = "Close" > × </ button >
2026-01-25 23:41:59 +01:00
</ div >
2026-01-26 00:15:11 +01:00
< div class = "project-insights-body" id = "projectInsightsList" ></ div >
< div class = "project-insights-resize-handle" ></ div >
2026-01-25 23:41:59 +01:00
</ div >
2026-01-27 01:02:38 +01:00
<!-- File Browser Panel -->
< div class = "file-browser-panel" id = "fileBrowserPanel" >
< div class = "file-browser-header" >
< span class = "file-browser-title" > Files</ span >
< div class = "file-browser-actions" >
< button class = "btn-icon-sm" onclick = "app.refreshFileBrowser()" title = "Refresh" > ↻ </ button >
< button class = "btn-icon-sm" onclick = "app.toggleFileBrowserExpand()" title = "Expand/Collapse All" id = "fileBrowserExpandBtn" > ⊞ </ button >
< button class = "btn-icon-sm" onclick = "app.closeFileBrowserPanel()" title = "Close" > × </ button >
</ div >
</ div >
< div class = "file-browser-search" >
< input type = "text" id = "fileBrowserSearch" placeholder = "Filter files..." oninput = "app.filterFileBrowser(this.value)" >
</ div >
< div class = "file-browser-body" id = "fileBrowserTree" >
< div class = "file-browser-empty" > Select a session to view files</ div >
</ div >
< div class = "file-browser-status" id = "fileBrowserStatus" ></ div >
</ div >
<!-- File Preview Overlay -->
< div class = "file-preview-overlay" id = "filePreviewOverlay" >
< div class = "file-preview-window" >
< div class = "file-preview-header" >
< span class = "file-preview-title" id = "filePreviewTitle" > file.ts</ span >
< div class = "file-preview-actions" >
< button class = "btn-icon-sm" onclick = "app.copyFilePreviewContent()" title = "Copy content" > ⎘ </ button >
< button class = "btn-icon-sm" onclick = "app.closeFilePreview()" title = "Close" > × </ button >
</ div >
</ div >
< div class = "file-preview-body" id = "filePreviewBody" ></ div >
< div class = "file-preview-footer" id = "filePreviewFooter" ></ div >
</ div >
</ div >
2026-01-19 00:38:11 +01:00
<!-- Bottom Toolbar -->
< footer class = "toolbar" >
< div class = "toolbar-left" >
2026-01-31 07:17:02 +01:00
<!-- Run Claude -->
2026-01-19 00:38:11 +01:00
< div class = "toolbar-group" >
2026-01-19 10:36:30 +01:00
< button class = "btn-toolbar btn-claude" onclick = "app.runClaude()" title = "Run Claude (Ctrl+Enter)" >
2026-01-29 12:47:23 +01:00
< svg width = "14" height = "14" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2.5" >< polygon points = "5 3 19 12 5 21 5 3" /></ svg >
2026-01-19 01:26:38 +01:00
Run Claude
</ button >
2026-01-31 07:17:02 +01:00
< div class = "tab-count-group" title = "Instance count" >
< button class = "tab-count-btn" onclick = "app.decrementTabCount()" > − </ button >
< input type = "number" id = "tabCount" class = "tab-count-input" value = "1" min = "1" max = "20" readonly >
< button class = "tab-count-btn" onclick = "app.incrementTabCount()" > +</ button >
</ div >
2026-01-19 10:36:30 +01:00
< button class = "btn-toolbar btn-shell" onclick = "app.runShell()" title = "Run Shell" >
Run Shell
2026-01-19 00:38:11 +01:00
</ button >
2026-01-31 07:17:02 +01:00
< div class = "tab-count-group" title = "Instance count" >
< button class = "tab-count-btn" onclick = "app.decrementShellCount()" > − </ button >
< input type = "number" id = "shellCount" class = "tab-count-input" value = "1" min = "1" max = "20" readonly >
< button class = "tab-count-btn" onclick = "app.incrementShellCount()" > +</ button >
</ div >
< div class = "case-select-group" >
< select id = "quickStartCase" class = "toolbar-select" title = "Select case" >
< option value = "testcase" > testcase</ option >
</ select >
< button class = "btn-case-add" onclick = "app.showCreateCaseModal()" title = "Create new case" > +</ button >
2026-02-12 08:34:51 +01:00
< button class = "btn-case-settings" onclick = "app.toggleCaseSettings()" title = "Case settings" > ⚙ </ button >
< div class = "case-settings-popover hidden" id = "caseSettingsPopover" >
< label class = "checkbox-inline" >
< input type = "checkbox" id = "caseAgentTeams" onchange = "app.onCaseSettingChanged()" >
< span > Agent Teams</ span >
</ label >
< span class = "form-hint" > Enable experimental Agent Teams for new sessions in this case</ span >
</ div >
2026-01-31 07:17:02 +01:00
</ div >
2026-01-31 22:17:47 +01:00
<!-- Mobile-only case button -->
< button class = "btn-toolbar btn-case-mobile" onclick = "app.showMobileCasePicker()" title = "Select case" >
< svg width = "12" height = "12" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< path d = "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" /></ svg >
< span id = "mobileCaseName" > Case</ span >
</ button >
2026-01-31 07:17:02 +01:00
</ div >
<!-- Directory (hidden) -->
< div class = "toolbar-group" style = "display: none;" >
< button class = "btn-toolbar" onclick = "app.toggleDirInput()" title = "Set working directory" >
< span id = "dirDisplay" > No directory</ span >
</ button >
< input type = "text" id = "dirInput" class = "toolbar-input hidden" placeholder = "Working directory..." onblur = "app.hideDirInput()" >
2026-01-18 07:31:19 +01:00
</ div >
2026-01-19 00:38:11 +01:00
</ div >
2026-01-25 04:04:24 +01:00
< div class = "toolbar-center" >
2026-01-31 07:17:02 +01:00
< span class = "version-display" id = "versionDisplay" title = "Claudeman version" > v0.0.0</ span >
2026-01-25 04:04:24 +01:00
</ div >
2026-01-19 00:38:11 +01:00
< div class = "toolbar-right" >
</ div >
</ footer >
2026-01-18 22:18:17 +01:00
<!-- Help Modal -->
< div class = "modal" id = "helpModal" >
< div class = "modal-backdrop" onclick = "app.closeHelp()" ></ div >
< div class = "modal-content" >
< div class = "modal-header" >
< h3 > Keyboard Shortcuts</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeHelp()" aria-label = "Close help" > × </ button >
2026-01-18 22:18:17 +01:00
</ div >
< div class = "modal-body" >
2026-01-19 00:38:11 +01:00
< div class = "shortcuts-grid" >
2026-01-19 01:42:47 +01:00
< div >< kbd > Ctrl</ kbd > +< kbd > Enter</ kbd ></ div >< div > Run Claude</ div >
2026-01-19 00:38:11 +01:00
< div >< kbd > Ctrl</ kbd > +< kbd > W</ kbd ></ div >< div > Close Session</ div >
< div >< kbd > Ctrl</ kbd > +< kbd > Tab</ kbd ></ div >< div > Next Session</ div >
2026-02-12 18:29:49 +01:00
< div >< kbd > Ctrl</ kbd > +< kbd > K</ kbd ></ div >< div > Kill All Sessions + Tmux</ div >
2026-01-19 00:38:11 +01:00
< div >< kbd > Ctrl</ kbd > +< kbd > L</ kbd ></ div >< div > Clear Terminal</ div >
< div >< kbd > Ctrl</ kbd > +< kbd > +</ kbd ></ div >< div > Increase Font</ div >
< div >< kbd > Ctrl</ kbd > +< kbd > -</ kbd ></ div >< div > Decrease Font</ div >
< div >< kbd > Ctrl</ kbd > +< kbd > ?</ kbd ></ div >< div > Show Help</ div >
< div >< kbd > Escape</ kbd ></ div >< div > Close Panels</ div >
2026-01-18 22:18:17 +01:00
</ div >
</ div >
</ div >
</ div >
2026-01-19 00:38:11 +01:00
2026-01-25 18:11:14 +01:00
<!-- Monitor Panel (Screen Sessions + Background Tasks) -->
2026-01-19 02:48:28 +01:00
< div class = "monitor-panel" id = "monitorPanel" >
2026-01-19 10:36:30 +01:00
< div class = "monitor-panel-header" id = "monitorPanelHeader" >
2026-01-25 18:11:14 +01:00
< div class = "monitor-panel-title" > Monitor</ div >
2026-01-19 02:48:28 +01:00
< div class = "monitor-panel-actions" >
2026-02-12 18:29:49 +01:00
< button class = "btn-toolbar btn-sm btn-danger" onclick = "app.killAllSessions()" title = "Kill all sessions and their tmux processes" > Kill All</ button >
2026-01-19 04:22:41 +01:00
< button class = "btn-icon-sm" onclick = "app.reconcileScreens()" title = "Refresh screens" > ↻ </ button >
2026-01-19 19:28:46 +01:00
< button class = "btn-icon-sm" onclick = "app.toggleMonitorDetach()" title = "Detach panel" id = "monitorDetachBtn" > ⧉ </ button >
< button class = "btn-icon-sm" onclick = "app.toggleMonitorPanel()" title = "Toggle panel" id = "monitorToggleBtn" > ▲ </ button >
2026-01-20 17:54:59 +01:00
< button class = "btn-icon-sm" onclick = "app.closeMonitor()" title = "Close monitor" > × </ button >
2026-01-19 02:18:51 +01:00
</ div >
</ div >
2026-01-19 10:36:30 +01:00
< div class = "monitor-resize-handle" id = "monitorResizeHandle" ></ div >
2026-01-25 18:11:14 +01:00
< div class = "monitor-panel-body" id = "monitorTabContent" >
2026-01-19 02:48:28 +01:00
< div class = "monitor-section" >
< div class = "monitor-section-header" >
< span > Screen Sessions</ span >
</ div >
< div class = "monitor-section-body" id = "screenSessionsBody" >
< div class = "monitor-empty" > No screen sessions</ div >
</ div >
</ div >
2026-01-29 11:27:44 +01:00
< div class = "monitor-section" id = "monitorPlanAgentsSection" style = "display: none;" >
< div class = "monitor-section-header" >
< span > Plan Wizard Agents</ span >
< span class = "task-stats" id = "monitorPlanAgentStats" > 0 active</ span >
< button class = "btn-toolbar btn-sm btn-danger" onclick = "app.cancelPlanFromMonitor()" title = "Cancel plan generation" > Cancel</ button >
</ div >
< div class = "monitor-section-body" id = "monitorPlanAgentsBody" >
< div class = "monitor-empty" > No plan agents</ div >
</ div >
</ div >
2026-01-28 07:07:18 +01:00
< div class = "monitor-section" id = "monitorSubagentsSection" >
< div class = "monitor-section-header" >
< span > Background Agents</ span >
< span class = "task-stats" id = "monitorSubagentStats" > 0 tracked</ span >
< button class = "btn-toolbar btn-sm btn-danger" onclick = "app.clearAllSubagents()" title = "Clear all" > Clear</ button >
</ div >
< div class = "monitor-section-body" id = "monitorSubagentsBody" >
< div class = "monitor-empty" > No background agents</ div >
</ div >
</ div >
2026-01-19 04:02:46 +01:00
< div class = "monitor-section" id = "backgroundTasksSection" style = "display: none;" >
2026-01-19 02:48:28 +01:00
< div class = "monitor-section-header" >
< span > Background Tasks</ span >
< span class = "task-stats" id = "taskPanelStats" > 0 running</ span >
</ div >
< div class = "monitor-section-body" id = "backgroundTasksBody" >
</ div >
</ div >
2026-01-25 17:40:28 +01:00
</ div >
2026-01-25 18:11:14 +01:00
</ div >
<!-- Subagents Panel (separate from Monitor) -->
< div class = "subagents-panel" id = "subagentsPanel" >
2026-01-25 18:33:43 +01:00
< div class = "subagents-panel-header" id = "subagentsPanelHeader" >
2026-01-25 18:11:14 +01:00
< div class = "subagents-panel-title" >
Subagents < span id = "subagentCountBadge" class = "subagent-badge" ></ span >
</ div >
< div class = "subagents-panel-actions" >
2026-01-28 07:07:18 +01:00
< button class = "btn-toolbar btn-sm btn-danger" onclick = "app.clearAllSubagents()" title = "Clear all tracked subagents" > Clear All</ button >
2026-01-25 18:33:43 +01:00
< button class = "btn-icon-sm" onclick = "app.toggleSubagentsDetach()" title = "Detach panel" id = "subagentsDetachBtn" > ⧉ </ button >
2026-01-25 18:11:14 +01:00
< button class = "btn-icon-sm" onclick = "app.toggleSubagentsPanel()" title = "Toggle panel" id = "subagentsToggleBtn" > ▲ </ button >
< button class = "btn-icon-sm" onclick = "app.closeSubagentsPanel()" title = "Close" > × </ button >
</ div >
</ div >
2026-01-25 18:33:43 +01:00
< div class = "subagents-resize-handle" id = "subagentsResizeHandle" ></ div >
2026-01-25 18:11:14 +01:00
< div class = "subagents-panel-body" id = "subagentsTabContent" >
2026-01-25 17:40:28 +01:00
< div class = "subagent-container" >
< div class = "subagent-list" id = "subagentList" >
< div class = "subagent-empty" > No background agents detected</ div >
2026-01-25 14:33:12 +01:00
</ div >
2026-01-25 17:40:28 +01:00
< div class = "subagent-detail" id = "subagentDetail" >
< div class = "subagent-empty" > Select an agent to view details</ div >
2026-01-25 14:33:12 +01:00
</ div >
</ div >
2026-01-19 00:38:11 +01:00
</ div >
</ div >
2026-01-19 03:40:57 +01:00
<!-- Session Options Modal (includes Respawn Settings) -->
2026-01-19 01:26:38 +01:00
< div class = "modal" id = "sessionOptionsModal" >
< div class = "modal-backdrop" onclick = "app.closeSessionOptions()" ></ div >
2026-01-19 03:40:57 +01:00
< div class = "modal-content" >
2026-01-19 01:26:38 +01:00
< div class = "modal-header" >
< h3 > Session Options</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeSessionOptions()" aria-label = "Close session options" > × </ button >
2026-01-19 01:26:38 +01:00
</ div >
2026-01-19 18:25:31 +01:00
<!-- Modal Tabs -->
< div class = "modal-tabs" >
< button class = "modal-tab-btn active" data-tab = "respawn" onclick = "app.switchOptionsTab('respawn')" > Respawn</ button >
2026-01-24 19:12:47 +01:00
< button class = "modal-tab-btn" data-tab = "context" onclick = "app.switchOptionsTab('context')" > Context</ button >
< button class = "modal-tab-btn" data-tab = "ralph" onclick = "app.switchOptionsTab('ralph')" > Ralph / Todo</ button >
2026-01-26 09:06:49 +01:00
< button class = "modal-tab-btn" data-tab = "summary" onclick = "app.switchOptionsTab('summary')" > Summary</ button >
2026-01-19 18:25:31 +01:00
</ div >
2026-01-19 01:26:38 +01:00
< div class = "modal-body" >
2026-01-19 18:25:31 +01:00
<!-- Respawn Tab Content -->
< div class = "modal-tab-content" id = "respawn-tab" >
2026-01-19 03:40:57 +01:00
<!-- Respawn Settings Section -->
< div class = "session-respawn-section" id = "sessionRespawnSection" >
2026-01-30 11:30:51 +01:00
< div class = "respawn-header" >
2026-01-19 03:40:57 +01:00
< div class = "session-respawn-status" id = "sessionRespawnStatus" >
< span class = "respawn-status-indicator" ></ span >
< span class = "respawn-status-text" > Not active</ span >
</ div >
2026-01-30 11:30:51 +01:00
< div class = "respawn-actions" >
< button class = "btn-toolbar btn-success btn-sm" onclick = "app.enableRespawnFromModal()" id = "modalEnableRespawnBtn" > Enable</ button >
< button class = "btn-toolbar btn-danger btn-sm" onclick = "app.stopRespawnFromModal()" id = "modalStopRespawnBtn" style = "display: none;" > Stop</ button >
</ div >
2026-01-19 02:06:37 +01:00
</ div >
2026-01-19 03:40:57 +01:00
2026-01-19 14:37:20 +01:00
< div class = "form-row" >
2026-01-30 11:30:51 +01:00
< label > Duration</ label >
2026-01-19 14:37:20 +01:00
< div class = "duration-presets" >
< button type = "button" class = "duration-preset-btn" data-minutes = "30" onclick = "app.selectDurationPreset('30')" > 30m</ button >
< button type = "button" class = "duration-preset-btn" data-minutes = "60" onclick = "app.selectDurationPreset('60')" > 1h</ button >
< button type = "button" class = "duration-preset-btn" data-minutes = "120" onclick = "app.selectDurationPreset('120')" > 2h</ button >
< button type = "button" class = "duration-preset-btn" data-minutes = "240" onclick = "app.selectDurationPreset('240')" > 4h</ button >
< button type = "button" class = "duration-preset-btn" data-minutes = "480" onclick = "app.selectDurationPreset('480')" > 8h</ button >
< button type = "button" class = "duration-preset-btn active" data-minutes = "" onclick = "app.selectDurationPreset('')" > ∞</ button >
< div class = "duration-custom" >
< button type = "button" class = "duration-preset-btn" data-minutes = "custom" onclick = "app.selectDurationPreset('custom')" > Custom</ button >
< div class = "input-suffix input-suffix-sm duration-custom-input" >
< input type = "number" id = "modalRespawnDuration" value = "" min = "1" placeholder = "min" >
< span > min</ span >
</ div >
</ div >
</ div >
</ div >
2026-01-30 14:14:45 +01:00
< div class = "form-section-header" > Presets</ div >
< div class = "form-row" >
< label > Load Preset</ label >
< div class = "preset-selector" >
< select id = "respawnPresetSelect" onchange = "app.updatePresetDescription()" >
< option value = "" > -- Select preset --</ option >
< optgroup label = "Built-in" id = "builtinPresetsGroup" >
</ optgroup >
< optgroup label = "Custom" id = "customPresetsGroup" >
</ optgroup >
</ select >
< button type = "button" class = "btn btn-sm" onclick = "app.loadRespawnPreset()" title = "Apply preset" > Apply</ button >
< button type = "button" class = "btn btn-sm btn-secondary" onclick = "app.saveCurrentAsPreset()" title = "Save current config as preset" > Save As...</ button >
</ div >
< p class = "form-hint" id = "presetDescriptionHint" ></ p >
</ div >
2026-01-30 11:39:15 +01:00
< div class = "form-section-header" > Respawn Cycle</ div >
2026-01-19 03:40:57 +01:00
< div class = "form-row" >
2026-01-30 11:39:15 +01:00
< label > 1. Update Prompt</ label >
2026-01-22 20:49:09 +01:00
< input type = "text" id = "modalRespawnPrompt" value = "update all the docs and CLAUDE.md" placeholder = "Prompt to send when idle" onchange = "app.autoSaveRespawnConfig()" >
2026-01-19 03:40:57 +01:00
</ div >
2026-01-30 11:39:15 +01:00
< div class = "respawn-options-row" style = "margin: 8px 0;" >
< label class = "checkbox-inline" >
< input type = "checkbox" id = "modalRespawnSendClear" checked onchange = "app.autoSaveRespawnConfig()" >
< span > 2. Send /clear</ span >
</ label >
< label class = "checkbox-inline" >
< input type = "checkbox" id = "modalRespawnSendInit" checked onchange = "app.autoSaveRespawnConfig()" >
< span > 3. Send /init</ span >
</ label >
</ div >
2026-01-29 13:03:17 +01:00
< div class = "form-row" >
2026-01-30 11:39:15 +01:00
< label > 4. Kickstart Prompt</ label >
2026-01-29 13:03:17 +01:00
< input type = "text" id = "modalRespawnKickstart" value = "" placeholder = "Optional: prompt if /init doesn't trigger work" onchange = "app.autoSaveRespawnConfig()" >
< span class = "form-hint" > Sent only when /init completes but Claude stays idle</ span >
</ div >
2026-01-30 11:30:51 +01:00
< div class = "form-section-header" > Behavior</ div >
< div class = "respawn-options-row" >
< label class = "checkbox-inline" >
< input type = "checkbox" id = "modalRespawnAutoAccept" checked onchange = "app.autoSaveRespawnConfig()" >
< span > Auto-accept prompts</ span >
</ label >
2026-01-24 19:12:47 +01:00
</ div >
2026-01-30 11:30:51 +01:00
< span class = "form-hint" > Auto-accept presses Enter for plan approvals and default question options</ span >
2026-01-24 19:12:47 +01:00
</ div >
</ div > <!-- End respawn-tab -->
<!-- Context Management Tab Content -->
< div class = "modal-tab-content hidden" id = "context-tab" >
2026-01-30 14:14:45 +01:00
< div class = "form-section-header" > Appearance</ div >
< div class = "form-row" >
< label > Session Color</ label >
< div class = "color-picker" id = "sessionColorPicker" >
< button type = "button" class = "color-swatch" data-color = "default" title = "Default" >
< span class = "swatch-inner" style = "background: var(--bg-hover)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "red" title = "Red" >
< span class = "swatch-inner" style = "background: var(--session-red)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "orange" title = "Orange" >
< span class = "swatch-inner" style = "background: var(--session-orange)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "yellow" title = "Yellow" >
< span class = "swatch-inner" style = "background: var(--session-yellow)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "green" title = "Green" >
< span class = "swatch-inner" style = "background: var(--session-green)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "blue" title = "Blue" >
< span class = "swatch-inner" style = "background: var(--session-blue)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "purple" title = "Purple" >
< span class = "swatch-inner" style = "background: var(--session-purple)" ></ span >
</ button >
< button type = "button" class = "color-swatch" data-color = "pink" title = "Pink" >
< span class = "swatch-inner" style = "background: var(--session-pink)" ></ span >
</ button >
</ div >
</ div >
2026-01-30 11:30:51 +01:00
< div class = "form-section-header" > Token Management</ div >
< div class = "context-settings-grid" >
< div class = "context-setting" >
< div class = "context-setting-header" >
< label class = "checkbox-inline" >
< input type = "checkbox" id = "modalAutoCompactEnabled" onchange = "app.autoSaveAutoCompact()" >
< span > Auto-Compact</ span >
</ label >
< div class = "input-suffix input-suffix-sm" >
< input type = "number" id = "modalAutoCompactThreshold" value = "110000" min = "10000" max = "500000" step = "10000" onchange = "app.autoSaveAutoCompact()" >
< span > tokens</ span >
</ div >
2026-01-19 13:08:53 +01:00
</ div >
2026-01-30 11:30:51 +01:00
< input type = "text" id = "modalAutoCompactPrompt" value = "" placeholder = "Focus prompt (optional)" onchange = "app.autoSaveAutoCompact()" >
< span class = "form-hint" > Summarizes context while preserving key information</ span >
2026-01-19 13:08:53 +01:00
</ div >
2026-01-30 11:30:51 +01:00
< div class = "context-setting" >
< div class = "context-setting-header" >
< label class = "checkbox-inline" >
< input type = "checkbox" id = "modalAutoClearEnabled" onchange = "app.autoSaveAutoClear()" >
< span > Auto-Clear</ span >
</ label >
< div class = "input-suffix input-suffix-sm" >
< input type = "number" id = "modalAutoClearThreshold" value = "140000" min = "10000" max = "500000" step = "10000" onchange = "app.autoSaveAutoClear()" >
< span > tokens</ span >
</ div >
2026-01-19 03:40:57 +01:00
</ div >
2026-01-30 11:30:51 +01:00
< span class = "form-hint" > Full context reset at threshold (use higher than compact)</ span >
2026-01-19 03:40:57 +01:00
</ div >
</ div >
2026-01-28 07:07:18 +01:00
2026-01-30 11:30:51 +01:00
< div class = "form-section-header" > File Watching</ div >
2026-01-28 07:07:18 +01:00
< div class = "form-row form-row-switch" >
< label > Image Watcher</ label >
< label class = "switch" >
< input type = "checkbox" id = "modalImageWatcherEnabled" checked onchange = "app.toggleSessionImageWatcher()" >
< span class = "slider" ></ span >
</ label >
2026-01-30 11:30:51 +01:00
< span class = "form-hint" > Auto-popup new images (screenshots, generated files) in this session's directory</ span >
2026-01-28 07:07:18 +01:00
</ div >
2026-01-30 17:50:02 +01:00
< div class = "form-section-header" > Performance</ div >
< div class = "form-row form-row-switch" >
< label > Flicker Filter</ label >
< label class = "switch" >
< input type = "checkbox" id = "modalFlickerFilterEnabled" onchange = "app.toggleFlickerFilter()" >
< span class = "slider" ></ span >
</ label >
< span class = "form-hint" > Buffers output after screen clears to reduce Ink UI flickering (adds ~50ms latency)</ span >
</ div >
2026-01-24 19:12:47 +01:00
</ div > <!-- End context-tab -->
2026-01-19 18:25:31 +01:00
<!-- Ralph Wiggum Tab Content -->
< div class = "modal-tab-content hidden" id = "ralph-tab" >
2026-01-19 18:56:34 +01:00
< div class = "form-row form-row-switch" >
< label > Enable Tracker</ label >
< label class = "switch" >
< input type = "checkbox" id = "modalRalphEnabled" >
< span class = "slider" ></ span >
</ label >
2026-01-30 11:30:51 +01:00
< span class = "form-hint" > Auto-detects loops and todos in Claude output</ span >
2026-01-19 18:56:34 +01:00
</ div >
2026-01-19 18:25:31 +01:00
< div class = "form-row" >
< label > Completion Phrase</ label >
< input type = "text" id = "modalRalphPhrase" placeholder = "e.g., COMPLETE, DONE, FINISHED" >
2026-01-30 11:30:51 +01:00
< span class = "form-hint" > Phrase Claude outputs when loop is complete (without < promise> tags)</ span >
2026-01-19 18:25:31 +01:00
</ div >
2026-01-30 11:30:51 +01:00
< div class = "form-section-header" > Limits</ div >
< div class = "ralph-limits-grid" >
< div class = "form-col" >
< label > Max Iterations</ label >
< input type = "number" id = "modalRalphMaxIterations" value = "0" min = "0" max = "1000" >
< span class = "form-hint" > 0 = unlimited</ span >
</ div >
< div class = "form-col" >
< label > Max Todos</ label >
< input type = "number" id = "modalRalphMaxTodos" value = "50" min = "1" max = "500" >
< span class = "form-hint" > Per session</ span >
</ div >
< div class = "form-col" >
< label > Todo Expiration</ label >
< div class = "input-suffix input-suffix-sm" >
< input type = "number" id = "modalRalphTodoExpiration" value = "60" min = "1" max = "1440" >
< span > min</ span >
</ div >
2026-01-19 18:25:31 +01:00
</ div >
</ div >
< div class = "ralph-config-actions" >
< button class = "btn-toolbar btn-primary" onclick = "app.saveRalphConfig()" > Save Ralph Config</ button >
</ div >
</ div > <!-- End ralph-tab -->
2026-01-26 09:06:49 +01:00
<!-- Summary Tab Content -->
< div class = "modal-tab-content hidden" id = "summary-tab" >
<!-- Filter Buttons -->
< div class = "run-summary-filters" >
< button class = "filter-btn active" data-filter = "all" onclick = "app.filterRunSummary('all')" > All</ button >
< button class = "filter-btn" data-filter = "errors" onclick = "app.filterRunSummary('errors')" > Errors</ button >
< button class = "filter-btn" data-filter = "warnings" onclick = "app.filterRunSummary('warnings')" > Warnings</ button >
< button class = "filter-btn" data-filter = "respawn" onclick = "app.filterRunSummary('respawn')" > Respawn</ button >
< button class = "filter-btn" data-filter = "idle" onclick = "app.filterRunSummary('idle')" > Idle/Working</ button >
</ div >
<!-- Timeline -->
< div class = "run-summary-timeline" id = "runSummaryTimeline" >
< p class = "empty-message" > Select a session to view summary</ p >
</ div >
<!-- Footer with actions -->
< div class = "run-summary-footer" >
< span class = "run-summary-session-info" id = "runSummarySessionInfo" ></ span >
< div class = "run-summary-actions" >
< label class = "auto-refresh-label" >
< input type = "checkbox" id = "runSummaryAutoRefresh" onchange = "app.toggleRunSummaryAutoRefresh()" >
Auto-refresh
</ label >
< button class = "btn-toolbar btn-sm" onclick = "app.refreshRunSummary()" title = "Refresh summary" > ↻ Refresh</ button >
< button class = "btn-toolbar btn-sm" onclick = "app.exportRunSummary('json')" title = "Export as JSON" > Export JSON</ button >
< button class = "btn-toolbar btn-sm" onclick = "app.exportRunSummary('md')" title = "Export as Markdown" > Export MD</ button >
</ div >
</ div >
</ div > <!-- End summary-tab -->
2026-01-19 01:26:38 +01:00
</ div >
</ div >
</ div >
2026-01-19 02:10:44 +01:00
<!-- Close Session Confirmation Modal -->
< div class = "modal" id = "closeConfirmModal" >
< div class = "modal-backdrop" onclick = "app.cancelCloseSession()" ></ div >
< div class = "modal-content modal-sm" >
< div class = "modal-header" >
2026-01-19 04:55:51 +01:00
< h3 > Close Session</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.cancelCloseSession()" aria-label = "Cancel close session" > × </ button >
2026-01-19 02:10:44 +01:00
</ div >
< div class = "modal-body" >
< p class = "modal-session-name" id = "closeConfirmSessionName" ></ p >
</ div >
2026-01-19 04:55:51 +01:00
< div class = "close-options" >
< button class = "close-option" onclick = "app.confirmCloseSession(false)" >
< span class = "close-option-title" > Remove Tab</ span >
< span class = "close-option-desc" > Screen session keeps running in background</ span >
</ button >
< button class = "close-option close-option-danger" onclick = "app.confirmCloseSession(true)" >
< span class = "close-option-title" > Kill Claude</ span >
< span class = "close-option-desc" > Terminate the session completely</ span >
</ button >
</ div >
< div class = "modal-footer-cancel" >
< button class = "btn-toolbar btn-sm" onclick = "app.cancelCloseSession()" > Cancel</ button >
2026-01-19 02:10:44 +01:00
</ div >
</ div >
</ div >
2026-01-19 02:08:58 +01:00
<!-- App Settings Modal -->
< div class = "modal" id = "appSettingsModal" >
< div class = "modal-backdrop" onclick = "app.closeAppSettings()" ></ div >
2026-01-21 13:07:45 +01:00
< div class = "modal-content modal-lg" >
2026-01-19 02:08:58 +01:00
< div class = "modal-header" >
< h3 > App Settings</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeAppSettings()" aria-label = "Close app settings" > × </ button >
2026-01-19 02:08:58 +01:00
</ div >
2026-01-21 13:07:45 +01:00
< div class = "modal-tabs" >
< button class = "modal-tab-btn active" data-tab = "settings-display" > Display</ button >
< button class = "modal-tab-btn" data-tab = "settings-claude" > Claude CLI</ button >
2026-01-28 07:07:18 +01:00
< button class = "modal-tab-btn" data-tab = "settings-models" > Models</ button >
2026-01-21 13:07:45 +01:00
< button class = "modal-tab-btn" data-tab = "settings-paths" > Paths</ button >
2026-01-24 01:22:53 +01:00
< button class = "modal-tab-btn" data-tab = "settings-notifications" > Notifications</ button >
2026-01-21 13:07:45 +01:00
</ div >
2026-01-19 02:08:58 +01:00
< div class = "modal-body" >
2026-01-21 13:07:45 +01:00
<!-- Display Tab -->
< div class = "modal-tab-content" id = "settings-display" >
2026-01-27 01:02:38 +01:00
< div class = "settings-grid" >
<!-- Header Displays Section -->
< div class = "settings-section-header" > Header Displays</ div >
< div class = "settings-item" title = "Show A-/A+ font size buttons in header" >
< span class = "settings-item-label" > Font Controls</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowFontControls" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Show CPU and memory usage in header" >
< span class = "settings-item-label" > System Stats</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowSystemStats" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Show total token count in header" >
< span class = "settings-item-label" > Token Count</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowTokenCount" checked >
< span class = "slider" ></ span >
</ label >
</ div >
2026-01-30 17:20:53 +01:00
< div class = "settings-item" title = "Show estimated cost next to token count" >
< span class = "settings-item-label" > Show Cost ($)</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowCost" checked >
< span class = "slider" ></ span >
</ label >
</ div >
2026-01-27 01:02:38 +01:00
<!-- Panels Section -->
< div class = "settings-section-header" > Panels</ div >
< div class = "settings-item" title = "Show Monitor panel at bottom right" >
< span class = "settings-item-label" > Monitor</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowMonitor" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Show active tools and file viewers in a floating panel" >
< span class = "settings-item-label" > Project Insights</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowProjectInsights" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Show file browser panel on the right side" >
< span class = "settings-item-label" > File Browser</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowFileBrowser" >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Show the Subagents panel (independent from Monitor)" >
< span class = "settings-item-label" > Subagents</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsShowSubagents" checked >
< span class = "slider" ></ span >
</ label >
</ div >
<!-- Subagent Options Section -->
< div class = "settings-section-header" > Subagent Options</ div >
< div class = "settings-item" title = "Monitor Claude Code background agents in real-time" >
< span class = "settings-item-label" > Enable Tracking</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsSubagentTracking" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Only show subagent windows when their parent tab is selected" >
< span class = "settings-item-label" > Active Tab Only</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsSubagentActiveTabOnly" >
< span class = "slider" ></ span >
</ label >
</ div >
2026-01-28 07:07:18 +01:00
<!-- Image Watcher Options Section -->
< div class = "settings-section-header" > Image Watcher</ div >
< div class = "settings-item" title = "Automatically detect and popup new images in session directories" >
< span class = "settings-item-label" > Enable Globally</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsImageWatcherEnabled" checked >
< span class = "slider" ></ span >
</ label >
</ div >
2026-01-26 00:15:11 +01:00
</ div >
2026-01-19 02:08:58 +01:00
</ div >
2026-02-13 06:02:12 +01:00
<!-- Tab-Switch Tab -->
2026-01-21 13:07:45 +01:00
<!-- Claude CLI Tab -->
< div class = "modal-tab-content hidden" id = "settings-claude" >
2026-01-21 04:19:34 +01:00
< div class = "form-row" >
< label > Startup Mode</ label >
< select id = "appSettingsClaudeMode" class = "form-select" >
< option value = "dangerously-skip-permissions" > Skip Permissions (default)</ option >
< option value = "normal" > Normal (with prompts)</ option >
< option value = "allowedTools" > Allowed Tools Only</ option >
</ select >
< span class = "form-hint" > How Claude CLI is started in screen sessions</ span >
</ div >
< div class = "form-row" id = "allowedToolsRow" style = "display: none;" >
< label > Allowed Tools</ label >
< input type = "text" id = "appSettingsAllowedTools" placeholder = "Read,Glob,Grep,Bash" >
2026-01-21 13:07:45 +01:00
< span class = "form-hint" > Comma-separated list of tools to allow</ span >
</ div >
< div class = "form-row form-row-switch" >
2026-01-21 22:36:45 +01:00
< label > Enable Ralph / Todo Tracker</ label >
2026-01-21 13:07:45 +01:00
< label class = "switch" >
< input type = "checkbox" id = "appSettingsRalphEnabled" >
< span class = "slider" ></ span >
</ label >
< span class = "form-hint" > Auto-enable for new sessions (otherwise auto-enables on Ralph pattern detection)</ span >
2026-01-21 04:19:34 +01:00
</ div >
2026-02-12 08:34:51 +01:00
<!-- Claude Permissions Section -->
< div class = "form-section-header" > Claude Permissions</ div >
< div class = "form-row form-row-switch" >
< label > Agent Teams</ label >
< label class = "switch" >
< input type = "checkbox" id = "appSettingsAgentTeams" >
< span class = "slider" ></ span >
</ label >
< span class = "form-hint" > Enable experimental Agent Teams for all new Claude sessions (disabled by default)</ span >
</ div >
2026-01-27 11:43:20 +01:00
<!-- Nice Priority Section -->
< div class = "form-section-header" > Nice Priority</ div >
2026-01-27 01:58:02 +01:00
< div class = "form-row form-row-switch" >
2026-01-27 11:43:20 +01:00
< label > Enable Nice Priority Reduction</ label >
2026-01-27 01:58:02 +01:00
< label class = "switch" >
2026-01-27 11:43:20 +01:00
< input type = "checkbox" id = "appSettingsNiceEnabled" >
2026-01-27 01:58:02 +01:00
< span class = "slider" ></ span >
</ label >
2026-01-27 11:43:20 +01:00
< span class = "form-hint" > Lower priority of Claude sessions (reduces system impact, only affects new sessions)</ span >
2026-01-27 01:58:02 +01:00
</ div >
2026-01-27 11:43:20 +01:00
< div class = "form-row" id = "niceValueRow" >
2026-01-27 01:58:02 +01:00
< label > Nice Value</ label >
2026-01-27 11:43:20 +01:00
< input type = "number" id = "appSettingsNiceValue" min = "-20" max = "19" value = "10" style = "width: 80px;" >
2026-01-27 01:58:02 +01:00
< span class = "form-hint" > Process priority (-20 to 19, higher = lower priority, default: 10)</ span >
</ div >
2026-01-21 04:19:34 +01:00
</ div >
2026-01-28 07:07:18 +01:00
<!-- Models Tab -->
< div class = "modal-tab-content hidden" id = "settings-models" >
< div class = "form-row" >
< label > Default Model</ label >
< select id = "appSettingsDefaultModel" class = "form-select" >
< option value = "sonnet" > Sonnet (Recommended - balanced)</ option >
< option value = "opus" > Opus (Most capable)</ option >
< option value = "haiku" > Haiku (Fast & cheap)</ option >
</ select >
< span class = "form-hint" > Model used for execution tasks. Optimizer suggestions are advisory only.</ span >
</ div >
< div class = "form-row form-row-switch" >
< label > Show Optimizer Recommendations</ label >
< label class = "switch" >
< input type = "checkbox" id = "appSettingsShowModelRecommendations" checked >
< span class = "slider" ></ span >
</ label >
< span class = "form-hint" > Show what the optimizer recommends (doesn't override your choice)</ span >
</ div >
< div class = "form-section-header" > Agent Type Overrides</ div >
< p class = "form-hint" style = "margin: 0 0 12px 0;" > Optionally set specific models for each task type. Leave as "Use Default" to use your default model.</ p >
< div class = "form-row" >
< label > Explore Tasks</ label >
< select id = "appSettingsModelExplore" class = "form-select" >
< option value = "" > Use Default</ option >
< option value = "haiku" > Haiku</ option >
< option value = "sonnet" > Sonnet</ option >
< option value = "opus" > Opus</ option >
</ select >
< span class = "form-hint" > Quick searches, codebase exploration</ span >
</ div >
< div class = "form-row" >
< label > Implement Tasks</ label >
< select id = "appSettingsModelImplement" class = "form-select" >
< option value = "" > Use Default</ option >
< option value = "haiku" > Haiku</ option >
< option value = "sonnet" > Sonnet</ option >
< option value = "opus" > Opus</ option >
</ select >
< span class = "form-hint" > Code writing, feature implementation</ span >
</ div >
< div class = "form-row" >
< label > Test Tasks</ label >
< select id = "appSettingsModelTest" class = "form-select" >
< option value = "" > Use Default</ option >
< option value = "haiku" > Haiku</ option >
< option value = "sonnet" > Sonnet</ option >
< option value = "opus" > Opus</ option >
</ select >
< span class = "form-hint" > Writing and running tests</ span >
</ div >
< div class = "form-row" >
< label > Review Tasks</ label >
< select id = "appSettingsModelReview" class = "form-select" >
< option value = "" > Use Default</ option >
< option value = "haiku" > Haiku</ option >
< option value = "sonnet" > Sonnet</ option >
< option value = "opus" > Opus</ option >
</ select >
< span class = "form-hint" > Code review, quality checks</ span >
</ div >
</ div >
2026-01-21 13:07:45 +01:00
<!-- Paths Tab -->
< div class = "modal-tab-content hidden" id = "settings-paths" >
2026-01-19 19:22:28 +01:00
< div class = "form-row" >
2026-01-21 13:07:45 +01:00
< label > Default CLAUDE.md Template</ label >
2026-01-19 19:22:28 +01:00
< input type = "text" id = "appSettingsClaudeMdPath" placeholder = "/path/to/CLAUDE.md template" >
< span class = "form-hint" > Used when creating new cases. Leave empty for built-in template.</ span >
</ div >
< div class = "form-row" >
< label > Default Working Directory</ label >
< input type = "text" id = "appSettingsDefaultDir" placeholder = "~/projects" >
< span class = "form-hint" > Default directory for new sessions.</ span >
</ div >
2026-01-21 04:19:34 +01:00
</ div >
2026-01-24 01:22:53 +01:00
<!-- Notifications Tab -->
< div class = "modal-tab-content hidden" id = "settings-notifications" >
2026-01-27 01:02:38 +01:00
< div class = "settings-grid" >
<!-- Master Control Section -->
< div class = "settings-section-header" > Master Control</ div >
< div class = "settings-item" title = "Master toggle for all notification layers" >
< span class = "settings-item-label" > Enable Notifications</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsNotifEnabled" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Show OS-level notifications when tab is hidden" >
< span class = "settings-item-label" > Browser</ span >
< div class = "settings-item-actions" >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsNotifBrowser" >
< span class = "slider" ></ span >
</ label >
< button class = "btn-toolbar btn-sm" onclick = "app.notificationManager?.requestPermission()" title = "Request browser notification permission" > Ask</ button >
< span class = "settings-status" id = "notifPermissionStatus" > ?</ span >
</ div >
</ div >
2026-01-30 14:14:45 +01:00
< span class = "form-hint" style = "grid-column: 1 / -1; margin-top: -8px;" > For remote access, HTTPS is required. Start with: < code > claudeman web --https</ code ></ span >
2026-01-27 01:02:38 +01:00
<!-- Alerts Section -->
< div class = "settings-section-header" > Alerts</ div >
< div class = "settings-item" title = "Play a short beep for critical events" >
< span class = "settings-item-label" > Audio Alerts</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsNotifAudio" >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Notify when a session is idle longer than this" >
< span class = "settings-item-label" > Idle Threshold</ span >
< div class = "settings-item-actions" >
< input type = "number" id = "appSettingsNotifStuckMins" class = "settings-item-input" value = "10" min = "1" max = "120" >
< span style = "font-size: 0.65rem; color: var(--text-muted);" > min</ span >
</ div >
</ div >
<!-- Notification Levels Section -->
< div class = "settings-section-header" > Notification Levels</ div >
2026-01-24 01:22:53 +01:00
</ div >
2026-01-27 01:02:38 +01:00
< div class = "settings-grid settings-grid-3col" >
< div class = "settings-item" title = "Errors, crashes, agent failures" >
< span class = "settings-item-label" > Critical</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsNotifCritical" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Completions, budget warnings, stuck sessions" >
< span class = "settings-item-label" > Warning</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsNotifWarning" checked >
< span class = "slider" ></ span >
</ label >
</ div >
< div class = "settings-item" title = "Auto-accepts, auto-clears, agent completions" >
< span class = "settings-item-label" > Info</ span >
< label class = "switch switch-sm" >
< input type = "checkbox" id = "appSettingsNotifInfo" checked >
< span class = "slider" ></ span >
</ label >
</ div >
2026-01-24 01:22:53 +01:00
</ div >
2026-01-30 14:14:45 +01:00
<!-- Event Type Preferences -->
< div class = "settings-grid" style = "margin-top: 12px;" >
< div class = "settings-section-header" > Per-Event Settings</ div >
</ div >
< div class = "event-type-grid" >
< div class = "event-header" > Event</ div >
< div class = "event-header" > On</ div >
< div class = "event-header" > Browser</ div >
< div class = "event-header" > Sound</ div >
< div class = "event-label" > Permission prompts</ div >
< input type = "checkbox" id = "eventPermissionEnabled" checked >
< input type = "checkbox" id = "eventPermissionBrowser" checked >
< input type = "checkbox" id = "eventPermissionAudio" checked >
< div class = "event-label" > Questions from Claude</ div >
< input type = "checkbox" id = "eventQuestionEnabled" checked >
< input type = "checkbox" id = "eventQuestionBrowser" checked >
< input type = "checkbox" id = "eventQuestionAudio" checked >
< div class = "event-label" > Session idle</ div >
< input type = "checkbox" id = "eventIdleEnabled" checked >
< input type = "checkbox" id = "eventIdleBrowser" checked >
< input type = "checkbox" id = "eventIdleAudio" >
< div class = "event-label" > Response complete</ div >
< input type = "checkbox" id = "eventStopEnabled" checked >
< input type = "checkbox" id = "eventStopBrowser" >
< input type = "checkbox" id = "eventStopAudio" >
< div class = "event-label" > Respawn cycles</ div >
< input type = "checkbox" id = "eventRespawnEnabled" checked >
< input type = "checkbox" id = "eventRespawnBrowser" >
< input type = "checkbox" id = "eventRespawnAudio" >
< div class = "event-label" > Task complete</ div >
< input type = "checkbox" id = "eventRalphEnabled" checked >
< input type = "checkbox" id = "eventRalphBrowser" checked >
< input type = "checkbox" id = "eventRalphAudio" checked >
< div class = "event-label" > Subagent activity</ div >
< input type = "checkbox" id = "eventSubagentEnabled" >
< input type = "checkbox" id = "eventSubagentBrowser" >
< input type = "checkbox" id = "eventSubagentAudio" >
</ div >
2026-01-24 01:22:53 +01:00
</ div >
2026-01-19 02:08:58 +01:00
</ div >
< div class = "form-actions" >
< button class = "btn-toolbar" onclick = "app.closeAppSettings()" > Cancel</ button >
< button class = "btn-toolbar btn-primary" onclick = "app.saveAppSettings()" > Save</ button >
</ div >
</ div >
</ div >
2026-01-19 10:36:30 +01:00
<!-- Create Case Modal -->
< div class = "modal" id = "createCaseModal" >
< div class = "modal-backdrop" onclick = "app.closeCreateCaseModal()" ></ div >
2026-01-21 13:20:43 +01:00
< div class = "modal-content modal-lg" >
2026-01-19 10:36:30 +01:00
< div class = "modal-header" >
2026-01-21 13:20:43 +01:00
< h3 > Add Case</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeCreateCaseModal()" aria-label = "Close create case" > × </ button >
2026-01-19 10:36:30 +01:00
</ div >
2026-01-21 13:20:43 +01:00
< div class = "modal-tabs" >
< button class = "modal-tab-btn active" data-tab = "case-create" > Create New</ button >
< button class = "modal-tab-btn" data-tab = "case-link" > Link Existing</ button >
</ div >
2026-01-19 10:36:30 +01:00
< div class = "modal-body" >
2026-01-21 13:20:43 +01:00
<!-- Create New Tab -->
< div class = "modal-tab-content" id = "case-create" >
< div class = "form-row" >
< label > Case Name</ label >
< input type = "text" id = "newCaseName" placeholder = "my-project" pattern = "[a-zA-Z0-9_-]+" >
< span class = "form-hint" > Letters, numbers, hyphens, underscores only. Created in ~/claudeman-cases/</ span >
</ div >
< div class = "form-row" >
< label > Description (optional)</ label >
< input type = "text" id = "newCaseDescription" placeholder = "A brief description..." >
</ div >
2026-01-19 10:36:30 +01:00
</ div >
2026-01-21 13:20:43 +01:00
<!-- Link Existing Tab -->
< div class = "modal-tab-content hidden" id = "case-link" >
< div class = "form-row" >
< label > Case Name</ label >
< input type = "text" id = "linkCaseName" placeholder = "my-project" pattern = "[a-zA-Z0-9_-]+" >
< span class = "form-hint" > Name to identify this case in Claudeman</ span >
</ div >
< div class = "form-row" >
< label > Folder Path</ label >
< input type = "text" id = "linkCasePath" placeholder = "/home/user/projects/my-project" >
< span class = "form-hint" > Absolute path to an existing project folder</ span >
</ div >
2026-01-19 10:36:30 +01:00
</ div >
</ div >
< div class = "form-actions" >
< button class = "btn-toolbar" onclick = "app.closeCreateCaseModal()" > Cancel</ button >
2026-01-21 13:20:43 +01:00
< button class = "btn-toolbar btn-primary" id = "caseModalSubmit" onclick = "app.submitCaseModal()" > Create</ button >
2026-01-19 10:36:30 +01:00
</ div >
</ div >
</ div >
2026-01-31 22:17:47 +01:00
<!-- Mobile Case Picker (Bottom Sheet) -->
< div class = "modal mobile-case-picker" id = "mobileCasePickerModal" >
< div class = "modal-backdrop" onclick = "app.closeMobileCasePicker()" ></ div >
< div class = "mobile-case-picker-sheet" >
< div class = "mobile-case-picker-header" >
< h3 > Select Case</ h3 >
< button class = "modal-close" onclick = "app.closeMobileCasePicker()" aria-label = "Close case picker" > × </ button >
</ div >
< div class = "mobile-case-picker-body" >
< div class = "mobile-case-list" id = "mobileCaseList" >
<!-- Cases populated by JS -->
</ div >
</ div >
< div class = "mobile-case-picker-footer" >
< button class = "btn-toolbar btn-case-create-mobile" onclick = "app.showCreateCaseFromMobile()" >
< svg width = "14" height = "14" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" stroke-width = "2" >< line x1 = "12" y1 = "5" x2 = "12" y2 = "19" />< line x1 = "5" y1 = "12" x2 = "19" y2 = "12" /></ svg >
Create New Case
</ button >
</ div >
</ div >
</ div >
2026-01-26 23:37:14 +01:00
<!-- Ralph Loop Wizard Modal -->
< div class = "modal" id = "ralphWizardModal" >
2026-01-28 02:31:58 +01:00
< div class = "modal-backdrop" ></ div >
2026-01-27 01:58:02 +01:00
< div class = "modal-content modal-wizard" >
2026-01-26 23:37:14 +01:00
< div class = "modal-header" >
< h3 > Start Ralph Loop</ h3 >
2026-01-28 04:04:40 +01:00
< div class = "modal-header-actions" >
< button class = "wizard-minimize-agents" id = "wizardMinimizeAgentsBtn" onclick = "app.togglePlanAgentsMinimized()" style = "display: none;" >
< span class = "icon" > 🤖</ span >
< span class = "agent-count" id = "wizardAgentCount" > 0</ span >
</ button >
2026-01-28 06:03:48 +01:00
< button class = "btn-icon-only wizard-minimize-btn" id = "wizardMinimizeBtn" onclick = "app.minimizeRalphWizard()" title = "Minimize wizard" > ‒ </ button >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeRalphWizard()" aria-label = "Close Ralph wizard" > × </ button >
2026-01-28 04:04:40 +01:00
</ div >
2026-01-26 23:37:14 +01:00
</ div >
<!-- Wizard Progress Steps -->
< div class = "wizard-progress" >
< div class = "wizard-step active" data-step = "1" >
< span class = "wizard-step-number" > 1</ span >
2026-01-27 01:58:02 +01:00
< span class = "wizard-step-label" > Describe</ span >
2026-01-26 23:37:14 +01:00
</ div >
< div class = "wizard-step" data-step = "2" >
< span class = "wizard-step-number" > 2</ span >
2026-01-27 01:58:02 +01:00
< span class = "wizard-step-label" > Plan</ span >
</ div >
< div class = "wizard-step" data-step = "3" >
< span class = "wizard-step-number" > 3</ span >
2026-01-26 23:37:14 +01:00
< span class = "wizard-step-label" > Launch</ span >
</ div >
</ div >
< div class = "modal-body" >
<!-- Step 1: Task & Completion Setup -->
2026-01-27 01:58:02 +01:00
< div class = "wizard-page wizard-page-compact" id = "ralphWizardStep1" >
< div class = "wizard-step-intro" >
< p > Describe your task below. Claude will generate an implementation plan with testing steps.</ p >
</ div >
2026-01-26 23:37:14 +01:00
< div class = "form-row" >
2026-01-27 01:58:02 +01:00
< label > What do you want to build?</ label >
2026-01-26 23:37:14 +01:00
< div class = "textarea-with-assist" >
< textarea
id = "ralphTaskDescription"
2026-01-28 02:31:58 +01:00
rows = "3"
2026-01-27 01:58:02 +01:00
placeholder = "Build a REST API for user authentication with JWT tokens, login/logout endpoints, and password reset flow." ></ textarea >
2026-01-26 23:37:14 +01:00
</ div >
</ div >
2026-01-27 01:58:02 +01:00
< div class = "wizard-inline-row" >
< div class = "wizard-inline-field" >
2026-01-27 11:02:02 +01:00
< label > Working Directory < span id = "existingPlanBadge" class = "existing-plan-badge" style = "display:none" ></ span ></ label >
2026-01-27 01:58:02 +01:00
< div class = "case-select-inline" >
2026-01-27 11:02:02 +01:00
< select id = "ralphCaseSelect" class = "form-select" onchange = "app.onRalphCaseChange()" ></ select >
2026-01-27 01:58:02 +01:00
< button class = "btn-toolbar btn-sm" onclick = "app.showCreateCaseModal()" > +</ button >
</ div >
2026-01-26 23:37:14 +01:00
</ div >
2026-01-27 01:58:02 +01:00
< div class = "wizard-inline-field wizard-inline-field-small" >
< label > Iterations</ label >
< div class = "iteration-presets-compact" >
< button type = "button" class = "iteration-preset-btn active" data-iterations = "10" onclick = "app.selectIterationPreset(10)" > 10</ button >
< button type = "button" class = "iteration-preset-btn" data-iterations = "25" onclick = "app.selectIterationPreset(25)" > 25</ button >
< button type = "button" class = "iteration-preset-btn" data-iterations = "50" onclick = "app.selectIterationPreset(50)" > 50</ button >
< button type = "button" class = "iteration-preset-btn" data-iterations = "0" onclick = "app.selectIterationPreset(0)" > ∞ </ button >
</ div >
</ div >
</ div >
<!-- Hidden completion phrase with default -->
< input type = "hidden" id = "ralphCompletionPhrase" value = "COMPLETE" >
</ div >
<!-- Step 2: Plan Generation -->
< div class = "wizard-page wizard-page-compact hidden" id = "ralphWizardStep2" >
2026-01-27 11:02:02 +01:00
<!-- Existing plan detected (shown when @fix_plan.md exists) -->
< div id = "existingPlanSection" class = "plan-section hidden" >
<!-- Content populated by app.updateExistingPlanUI() -->
</ div >
<!-- Loading state (shown during generation) -->
< div id = "planGenerationLoading" class = "plan-loading-state hidden" >
2026-01-27 01:58:02 +01:00
< div class = "plan-loading-content" >
< div class = "plan-spinner" ></ div >
< div class = "plan-loading-text" >
2026-01-27 02:38:37 +01:00
< span class = "plan-loading-title" id = "planLoadingTitle" > Starting Opus 4.5...</ span >
2026-01-27 01:58:02 +01:00
< span class = "plan-loading-time" id = "planLoadingTime" > 0s</ span >
</ div >
</ div >
2026-01-27 02:38:37 +01:00
< p class = "plan-loading-hint" id = "planLoadingHint" > Initializing deep reasoning model</ p >
2026-01-27 23:15:25 +01:00
< div class = "plan-loading-actions" >
< button class = "btn-toolbar btn-sm plan-cancel-btn" onclick = "app.cancelPlanGeneration()" > Stop</ button >
< button class = "btn-toolbar btn-sm" onclick = "app.regeneratePlan()" > Regenerate</ button >
</ div >
2026-01-28 04:17:14 +01:00
<!-- Auto-start toggle visible during generation -->
< div class = "plan-autostart-toggle" >
< label class = "plan-autostart-label" >
< input type = "checkbox" id = "ralphAutoStartStep2" onchange = "app.syncAutoStartCheckbox(this)" >
< span class = "plan-autostart-text" > Auto-launch when plan completes</ span >
</ label >
</ div >
2026-01-26 23:37:14 +01:00
</ div >
2026-01-27 23:15:25 +01:00
<!-- Stopped/Error state -->
2026-01-27 01:58:02 +01:00
< div id = "planGenerationError" class = "plan-section hidden" >
2026-01-27 23:15:25 +01:00
< div class = "plan-stopped-indicator" id = "planStoppedIndicator" >
< span class = "plan-stopped-icon" > ■ </ span >
< span class = "plan-stopped-text" > Stopped</ span >
</ div >
2026-01-27 01:58:02 +01:00
< p class = "plan-error-msg" id = "planErrorMsg" ></ p >
< div class = "plan-actions" >
2026-01-27 23:15:25 +01:00
< button class = "btn-toolbar btn-primary" onclick = "app.generatePlan()" > Regenerate Plan</ button >
2026-01-26 23:37:14 +01:00
</ div >
2026-01-27 23:15:25 +01:00
< p class = "plan-skip-hint" > Use < strong > Back</ strong > to edit your task, or < strong > Next</ strong > to continue without a plan</ p >
2026-01-26 23:37:14 +01:00
</ div >
2026-01-27 01:58:02 +01:00
<!-- Editor state -->
< div id = "planEditor" class = "plan-section hidden" >
< div class = "plan-editor-header" >
2026-01-27 11:02:02 +01:00
< span > Implementation Plan < span class = "plan-stats" id = "planStats" ></ span ></ span >
2026-01-27 01:58:02 +01:00
< div class = "plan-editor-actions" >
< div class = "plan-option-group" >
< label > Detail:</ label >
< div class = "plan-detail-btns" >
2026-01-27 18:16:19 +01:00
< button type = "button" class = "plan-detail-btn" data-detail = "brief" onclick = "app.setPlanDetail('brief')" title = "High-level milestones only" > Brief</ button >
2026-01-27 23:15:25 +01:00
< button type = "button" class = "plan-detail-btn" data-detail = "standard" onclick = "app.setPlanDetail('standard')" title = "Single-pass generation with Opus 4.5" > Standard</ button >
< button type = "button" class = "plan-detail-btn active" data-detail = "detailed" onclick = "app.setPlanDetail('detailed')" title = "Enhanced: 4 parallel subagents + verification (slower but more thorough)" > Enhanced</ button >
2026-01-27 01:58:02 +01:00
</ div >
</ div >
< button class = "btn-toolbar btn-sm" onclick = "app.regeneratePlan()" > Regenerate</ button >
</ div >
</ div >
2026-01-27 18:16:19 +01:00
< div id = "planWarnings" class = "hidden" ></ div >
2026-01-27 01:58:02 +01:00
< div id = "planItemsList" class = "plan-items-list" ></ div >
< div class = "plan-editor-footer" >
< button class = "btn-toolbar btn-sm" onclick = "app.addPlanItem()" > + Add Step</ button >
2026-01-27 23:15:25 +01:00
< div class = "plan-view-toggle" >
< button type = "button" class = "plan-view-btn active" data-view = "list" onclick = "app.setPlanViewMode('list')" title = "Flat list" > ☰ </ button >
< button type = "button" class = "plan-view-btn" data-view = "grouped" onclick = "app.setPlanViewMode('grouped')" title = "Group by TDD phase" > ⊞ </ button >
</ div >
2026-01-26 23:37:14 +01:00
</ div >
</ div >
</ div >
2026-01-27 01:58:02 +01:00
<!-- Step 3: Preview & Launch -->
< div class = "wizard-page hidden" id = "ralphWizardStep3" >
2026-01-26 23:37:14 +01:00
< div class = "ralph-preview-section" >
< label > Prompt Preview</ label >
< div class = "ralph-prompt-preview" id = "ralphPromptPreview" ></ div >
</ div >
< div class = "ralph-config-summary" >
< div class = "config-summary-row" >
< span class = "config-label" > Completion Phrase:</ span >
< code id = "summaryPhrase" > COMPLETE</ code >
</ div >
< div class = "config-summary-row" >
< span class = "config-label" > Max Iterations:</ span >
< span id = "summaryIterations" > 10</ span >
</ div >
< div class = "config-summary-row" >
< span class = "config-label" > Case:</ span >
< span id = "summaryCase" > testcase</ span >
</ div >
2026-01-27 01:58:02 +01:00
< div class = "config-summary-row" style = "display: none;" >
< span class = "config-label" > Plan:</ span >
< span id = "summaryPlan" > -</ span >
</ div >
2026-01-26 23:37:14 +01:00
</ div >
<!-- Advanced Options (Collapsible) -->
< details class = "advanced-options" >
< summary > Advanced Options</ summary >
< div class = "advanced-options-content" >
< div class = "form-row form-row-switch" >
< label > Enable Respawn</ label >
< label class = "switch" >
2026-01-27 17:46:43 +01:00
< input type = "checkbox" id = "ralphEnableRespawn" >
2026-01-26 23:37:14 +01:00
< span class = "slider" ></ span >
</ label >
2026-01-27 17:46:43 +01:00
< span class = "form-hint" > Auto-restart sessions when context fills up (usually not needed)</ span >
2026-01-26 23:37:14 +01:00
</ div >
</ div >
</ details >
</ div >
</ div >
<!-- Wizard Footer -->
< div class = "wizard-footer" >
< button class = "btn-toolbar" id = "ralphBackBtn" onclick = "app.ralphWizardBack()" style = "display: none;" > Back</ button >
< div class = "wizard-footer-right" >
< button class = "btn-toolbar" onclick = "app.closeRalphWizard()" > Cancel</ button >
< button class = "btn-toolbar btn-primary" id = "ralphNextBtn" onclick = "app.ralphWizardNext()" > Next</ button >
< button class = "btn-toolbar btn-success" id = "ralphStartBtn" onclick = "app.startRalphLoop()" style = "display: none;" > Start Loop</ button >
</ div >
</ div >
</ div >
</ div >
2026-01-28 06:03:48 +01:00
<!-- Ralph Wizard Minimized Indicator -->
< div class = "wizard-minimized-indicator" id = "wizardMinimizedIndicator" onclick = "app.restoreRalphWizard()" >
< span class = "wizard-minimized-icon" > 🔄</ span >
< span class = "wizard-minimized-text" > Ralph Wizard</ span >
< span class = "wizard-minimized-time" id = "wizardMinimizedTime" > 0s</ span >
</ div >
2026-01-19 10:36:30 +01:00
<!-- Kill All Confirmation Modal -->
< div class = "modal" id = "killAllModal" >
< div class = "modal-backdrop" onclick = "app.closeKillAllModal()" ></ div >
< div class = "modal-content modal-sm" >
< div class = "modal-header" >
< h3 > Kill All Sessions</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeKillAllModal()" aria-label = "Close kill all modal" > × </ button >
2026-01-19 10:36:30 +01:00
</ div >
< div class = "modal-body" >
< p class = "modal-warning-text" > Choose how to close < span id = "killAllCount" > 0</ span > session(s):</ p >
</ div >
< div class = "close-options" >
< button class = "close-option" onclick = "app.confirmKillAll(false)" >
< span class = "close-option-title" > Remove All Tabs</ span >
2026-02-12 18:29:49 +01:00
< span class = "close-option-desc" > Tmux sessions keep running in background</ span >
2026-01-19 10:36:30 +01:00
</ button >
< button class = "close-option close-option-danger" onclick = "app.confirmKillAll(true)" >
2026-02-12 18:29:49 +01:00
< span class = "close-option-title" > Kill All Claude + Tmux</ span >
2026-01-19 10:36:30 +01:00
< span class = "close-option-desc" > Terminate everything completely</ span >
</ button >
</ div >
< div class = "modal-footer-cancel" >
< button class = "btn-toolbar btn-sm" onclick = "app.closeKillAllModal()" > Cancel</ button >
</ div >
</ div >
</ div >
2026-01-24 01:22:53 +01:00
<!-- Notification Drawer -->
< div class = "notification-drawer" id = "notifDrawer" >
< div class = "notif-drawer-header" >
< span class = "notif-drawer-title" > Notifications</ span >
< div class = "notif-drawer-actions" >
< button class = "btn-notif-action" onclick = "app.notificationManager?.markAllRead()" title = "Mark all read" > ✓ </ button >
< button class = "btn-notif-action" onclick = "app.notificationManager?.clearAll()" title = "Clear all" > 🗑 </ button >
< button class = "btn-notif-action" onclick = "app.toggleNotifications()" title = "Close" > × </ button >
</ div >
</ div >
< div class = "notif-drawer-list" id = "notifList" ></ div >
< div class = "notif-drawer-empty" id = "notifEmpty" > No notifications</ div >
</ div >
2026-01-25 20:36:04 +01:00
<!-- Token Stats Modal -->
< div class = "modal" id = "tokenStatsModal" >
< div class = "modal-backdrop" onclick = "app.closeTokenStats()" ></ div >
< div class = "modal-content token-stats-modal" >
< div class = "modal-header" >
< h3 > Token Usage Statistics</ h3 >
2026-01-30 14:14:45 +01:00
< button class = "modal-close" onclick = "app.closeTokenStats()" aria-label = "Close token statistics" > × </ button >
2026-01-25 20:36:04 +01:00
</ div >
< div class = "modal-body" >
< div class = "stats-summary" id = "statsSummary" ></ div >
< div class = "stats-chart-container" >
< div class = "stats-chart-label" > Last 7 Days</ div >
< div class = "stats-chart" id = "statsChart" ></ div >
< div class = "stats-chart-days" id = "statsChartDays" ></ div >
</ div >
< div class = "stats-table-container" >
< div class = "stats-table-label" > Daily Breakdown</ div >
< div class = "stats-table" id = "statsTable" ></ div >
</ div >
</ div >
</ div >
</ div >
2026-01-18 05:14:34 +01:00
</ div >
2026-01-30 14:14:45 +01:00
<!-- Save Preset Modal -->
< div class = "modal" id = "savePresetModal" >
< div class = "modal-backdrop" onclick = "app.closeSavePresetModal()" ></ div >
< div class = "modal-content modal-sm" >
< div class = "modal-header" >
< h3 > Save Respawn Preset</ h3 >
< button class = "modal-close" onclick = "app.closeSavePresetModal()" aria-label = "Close" > × </ button >
</ div >
< div class = "modal-body" >
< div class = "form-row" >
< label > Preset Name</ label >
< input type = "text" id = "presetNameInput" placeholder = "My Custom Preset" maxlength = "30" >
</ div >
< div class = "form-row" >
< label > Description (optional)</ label >
< input type = "text" id = "presetDescriptionInput" placeholder = "When to use this preset" maxlength = "100" >
</ div >
</ div >
< div class = "modal-footer" >
< button class = "btn btn-secondary" onclick = "app.closeSavePresetModal()" > Cancel</ button >
< button class = "btn btn-primary" onclick = "app.confirmSavePreset()" > Save Preset</ button >
</ div >
</ div >
</ div >
2026-01-25 23:41:59 +01:00
<!-- SVG Overlay for Subagent Connection Lines -->
< svg id = "connectionLines" class = "connection-lines-svg" >
<!-- Lines drawn dynamically -->
</ svg >
2026-02-13 21:21:33 +01:00
< script defer src = "app.js" ></ script >
2026-01-18 05:14:34 +01:00
</ body >
</ html >