Remove the large "done" animation that appeared when Ralph loops completed.
The completion state is now simply reflected in the tracker panel without
the intrusive overlay.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Performance improvements:
- Throttle cleanupExpiredTodos() to run every 30s instead of every chunk
- Add early exit in detectTodoItems() for lines without todo markers
- Remove redundant PROMISE_PATTERN check from LOOP_START_PATTERN
Code quality:
- Extract activateLoopIfNeeded() helper to eliminate duplicate loop start logic
- Improve hash function using djb2 algorithm for better distribution
- Add guards for empty/whitespace-only content in upsertTodo()
- Simplify startLoop() to use existing enable() method
Tests:
- Add 5 new tests for edge cases and optimizations
- Test empty content handling, early exit, ID uniqueness
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TODO_NATIVE_PATTERN to match ☐/☒/◐ icons from Claude Code's TodoWrite
- Add TODO_EXCLUDE_PATTERNS to filter out tool invocations (Bash, Search, etc.)
- Update iconToStatus() to recognize ☒ as completed
- Add tests for native checkbox detection
The tracker now correctly parses Claude Code's actual terminal output format
instead of only matching markdown checkboxes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The tracker was incorrectly marking Ralph loops as complete when the
completion phrase appeared in the prompt text itself (e.g., when user
types the /ralph-loop command with the completion phrase in quotes).
Now it only marks completion when the loop is already active, and
records the expected phrase without triggering completion otherwise.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the global "Enable Ralph Wiggum Tracker" setting was enabled,
new sessions had the tracker enabled on the server but the panel
wasn't rendered. The inner-config API call happened before
activeSessionId was set, so updateInnerState() didn't trigger
renderInnerStatePanel(). Added explicit call after setting activeSessionId.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Restore inner loop tracker state (enabled flag, todos, loop state) when
sessions are restored from screen sessions after server restart.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pass existing screenSession to Session constructor for restored sessions
- Skip terminal buffer clearing when attaching to restored (existing) screens
- Frontend auto-calls /interactive endpoint when selecting a restored session
- Fixes issue where restored sessions appeared broken after server restart
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change toggle icon to show ▲ when closed, ▼ when open
- Update detach/attach icons: ⧉ (detach) and ⊞ (attach)
- Adjust panel width to 380px
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove auto-open of monitor panel on startup
- Reduce monitor panel width from 500px to 320px
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add visibility toggles in App Settings modal for A-/A+, CPU/MEM, and token count
- Make settings gear icon larger (32px) for better accessibility
- Apply settings on startup and immediately when saved
- All options enabled by default, persisted to localStorage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to enable/disable the Ralph tracker:
- Per-session toggle in Session Options > Ralph Wiggum tab
- Global default toggle in App Settings
Changes:
- Add "Enable Tracker" toggle to ralph-tab in session options modal
- Add "Enable Ralph Wiggum Tracker" toggle to app settings modal
- Update /api/sessions/:id/inner-config endpoint to handle `enabled` param
- Add CSS for toggle switch component
- New sessions inherit global setting from app settings
- Setting is saved in innerConfig and synced with backend
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ability to detach the Ralph Wiggum tracker panel as a floating
window that can be dragged around the screen.
Changes:
- Add detach button to the Ralph panel header
- Restructure HTML to separate clickable content from controls
- Add CSS styles for detached state (floating, draggable, resizable)
- Add toggleRalphDetach() and setupRalphDrag() JavaScript methods
- Panel auto-expands when detached for better visibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The InnerLoopTracker is now disabled by default and auto-enables when
Ralph-related patterns are detected:
- /ralph-loop command
- <promise>PHRASE</promise> completion phrases
- TodoWrite tool usage
- Iteration patterns (Iteration 5/50, [5/50])
- Todo checkboxes (- [ ]/- [x]) or indicator icons
This reduces noise for sessions that don't use Ralph loops while
maintaining full functionality when loops are detected.
Changes:
- Add `enabled` property to InnerLoopState type
- Add enable()/disable() methods to InnerLoopTracker
- Implement shouldAutoEnable() for pattern detection
- Update frontend to show "Tracking" status when enabled
- Add CSS for tracking state indicator
- Update CLAUDE.md documentation
- Add comprehensive tests for auto-enable behavior
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add cache-busting to /api/cases fetch to prevent stale data
- Use created case path from API response (was using old empty caseData)
- Add selectCaseName parameter to loadQuickStartCases for post-create selection
- Add toast() alias for showToast() to fix "toast is not a function" error
- Prevent duplicate event listeners on case dropdown
- Show "(will be created)" hint when no cases exist
- Add Ralph Wiggum config tab to session options modal
- Add inner-config API endpoint for Ralph loop settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add deduplication guard to prevent spamming the same completion toast.
Uses a Set to track shown completions per session, with 30s expiry to
allow re-notification if loop restarts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Expand ANSI regex to match all escape sequences (cursor movement,
color codes, etc.) not just color codes. This fixes todo content
having residual escape sequences like cursor movements.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add polished, animated Ralph Wiggum Loop panel with:
- Circular progress ring showing task completion percentage
- Task cards with status indicators (pending/in-progress/completed)
- Animated status badge with pulsing indicator when active
- Completion celebration animation with animated checkmark
- Smart time formatting ("1h 23m" instead of "1.38 hours")
Enhanced detection patterns based on official Ralph plugin:
- /ralph-loop command detection
- Iteration patterns: "Iteration 5/50", "[5/50]"
- Max iterations from YAML: "max-iterations: 50"
- TodoWrite tool output detection
Adds maxIterations field to InnerLoopState for tracking loop limits.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-compact now uses writeViaScreen with \r
- Auto-clear now uses writeViaScreen with \r
- Standardized respawn controller to use \r consistently
- Removed session name input from options modal (use right-click to rename)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Claude CLI (Ink) doesn't process carriage return correctly when sent
together with text via screen -X stuff. Splitting into two separate
commands works reliably:
1. screen -X stuff "text"
2. screen -X stuff "$(printf '\015')"
Also adds writeViaScreen() method to Session for programmatic input
that bypasses PTY and uses screen -X stuff directly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The bash $'...' escaping wasn't reliably sending carriage return to
Ink/Claude CLI. Using printf with octal '\015' works correctly.
Tested: screen -X stuff "$(printf 'text\015')" successfully triggers
Enter key submission in Claude CLI.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Regular user input should go through PTY, only respawn controller
should use screen -X stuff. Added writeViaScreen() method for
programmatic input that needs reliable Enter key delivery.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When writing to an attached PTY connected to screen, the input doesn't
reliably reach Claude CLI. This fix uses `screen -X stuff` command to
send input directly to the screen session, bypassing the PTY attachment.
Research findings:
- Claude CLI uses Ink (React for CLI) for terminal UI
- Ink's parseKeypress detects \r as key.return (Enter)
- screen -X stuff with $'...' syntax reliably sends literal characters
Changes:
- Add ScreenManager.sendInput() using screen -X stuff
- Modify Session.write() to prefer screen -X stuff when available
- Keep \r as Enter key (what Ink expects for key.return)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Screen sessions require \n (line feed) for Enter key input, not \r
(carriage return). This fixes the issue where respawn prompts would
appear in the terminal but not be submitted.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed all command writes from \n (newline) to \r (carriage return).
PTY terminals expect \r for Enter key, \n only creates a new line
without executing the command.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The respawn controller was calling removeAllListeners('terminal')
which also removed the server's listener that streams output to
the browser. This made the console appear "blocked" when respawn
was enabled.
Now properly tracks and removes only its own listener.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shortens the session options modal by putting the name input
and action buttons on the same row at the top.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
process.env.HOME and process.cwd() don't exist in browsers.
Replaced with proper error handling when case path is missing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fixed respawn controller immediately sending commands when Claude
becomes idle, which prevented users from typing. Now waits for
idleTimeoutMs (default 10s) before triggering the respawn cycle.
- Removed Directory field from Session Options modal for cleaner UI
- Compacted CLAUDE.md documentation for better readability
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace the simple number input for respawn duration with a preset
button group (30m, 1h, 2h, 4h, 8h, ∞, Custom). Move duration to be
the first option in the Respawn Controller settings.
- Add duration preset buttons with visual highlighting for selection
- ∞ (unlimited) is selected by default
- Custom option reveals a number input for arbitrary values
- Reset to default when modal opens
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add InnerLoopTracker to detect and expose internal Claude Code state
running inside claudeman sessions by parsing terminal output patterns.
Detection patterns:
- Completion phrases: <promise>PHRASE</promise>
- Todo items: checkbox format, indicator icons, status parentheses
- Loop status: cycle counts, elapsed time, start/completion
New features:
- Inner state panel UI (collapsible, below session tabs)
- SSE events: innerLoopUpdate, innerTodoUpdate, innerCompletionDetected
- API endpoint: GET /api/sessions/:id/inner-state
- State persistence to ~/.claudeman/state-inner.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Kickstart Prompt:
- Remove Idle Timeout setting from respawn UI (uses 10s default)
- Add Kickstart Prompt field sent when /init doesn't trigger work
- New states: monitoring_init, sending_kickstart, waiting_kickstart
- Monitors 3s after /init to detect if Claude started working
Auto-Compact Context:
- Add auto-compact at 110k tokens (sends /compact with optional prompt)
- Preserves summarized context unlike /clear which wipes everything
- Optional focus prompt to guide what compact should preserve
- Blocks auto-clear while compacting to prevent conflicts
Also updates auto-clear default threshold from 100k to 140k tokens.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The interStepDelayMs config is rarely needed and clutters the UI.
Backend still supports it with default value (1000ms).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Primary: Use '↵ send' indicator for immediate response when ready
- Fallback: Use timeout-based detection for prompt patterns
- Add working indicators: Synthesizing, Brewing, ✻, ✽
- Cleaner step completion handlers (checkUpdateComplete, etc.)
The hybrid approach responds immediately when Claude shows the
suggestion indicator, while still having timeout fallback for
reliability.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add '↵ send' as primary idle indicator (suggestion ready)
- Add 'Synthesizing', 'Brewing' to working patterns
- Add '✻', '✽' activity indicators to working patterns
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change default idleTimeoutMs from 5s to 10s
- Use configured idle timeout for all step completion checks
- Ensures each step (update, /clear, /init) waits properly until idle
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move launch and completion detection patterns to module-level constants
- Use iterator directly instead of Array.from for deduplication check
- Reduces regex compilation overhead on every terminal output
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Debounce save() calls by 500ms to batch multiple updates
- Add saveNow() for immediate persistence when needed
- Add flush() method for shutdown cleanup
- Reduces disk I/O from O(n) to O(1) for rapid state changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pre-compile ANSI escape and whitespace regex patterns in respawn controller
- Pre-compile screen pattern regex for screen list parsing
- Batch ps and pgrep calls in getScreensWithStats() for multiple screens
- Reduces subprocess spawns from O(2n) to O(2) for n screens
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pre-compile regex patterns (ANSI escape, token parsing) in session.ts
- Optimize SSE broadcast to serialize JSON once for all clients
- Add DOM element caching ($() helper) to avoid repeated getElementById
- Throttle resize observer with dimension change detection
- Use array.join() for session tab HTML building
- Replace DOM-based escapeHtml with regex replacement
- Cache toast container reference
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove "Connected/Disconnected" indicator to save header space
- Move token count to the far right of the header (after settings icon)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Session tabs: 150px → 220px (show more of filename)
- Case select dropdown: 120px → 180px (show full case names)
- Working dir display: 300px → 450px (show full paths)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- killScreen now uses 4 strategies for reliable cleanup:
1. Kill all child processes recursively (SIGTERM then SIGKILL)
2. Kill entire process group (-PID) to catch orphans
3. Kill screen by name (screen -X quit)
4. Direct SIGKILL as final fallback
- Refresh screen PID from screen -ls before killing (handles stale PIDs)
- reconcileScreens now discovers unknown claudeman screens from screen -ls
This prevents "ghost" screens that persist after screens.json is lost
- restoreScreenSessions handles newly discovered screens
The rapid session creation test now fails because discovery is working -
it finds screens that weren't killed fast enough (test timing issue)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- killScreen now finds and kills all child processes before quitting screen
to prevent claude processes from becoming orphaned (the main bug)
- Add cleanupSession() method for comprehensive resource cleanup:
respawn controllers, timers, batches, event listeners, and sessions
- Fix /api/run endpoint to cleanup sessions after completion
- Fix /api/quick-start error path to cleanup on failure
- Add MAX_CONCURRENT_SESSIONS (50) limit to prevent unbounded growth
- Update CLAUDE.md with improved documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Redesign Run Claude button with purple gradient
- Redesign Run Shell button with dark green gradient
- Add + button to create new cases from toolbar
- Add Create Case modal for quick case creation
- Add Kill All modal with two options (tabs only vs full kill)
- Add CPU/Memory progress bars with color gradients
- Make monitor panel detachable as floating draggable window
- Monitor panel resizable when detached (min 350x250)
- Default CLAUDE.md template now uses /home/arkon/default/CLAUDE.md
- Streamline CLAUDE.md documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Kill All button with confirmation dialog to monitor panel header
- Button shows red X icon, confirms before killing all sessions
- Center-align close session modal options for better UX
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When switching between Claude session tabs, the terminal buffer was
rendered at a different size than the current terminal. This caused
Claude's banner to appear squished/corrupted.
Changes:
- Remove ANSI regex stripping that was breaking terminal output
- Send Ctrl+L after resize to trigger Claude CLI to redraw at correct size
- Only send Ctrl+L for Claude sessions, not shell sessions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>