- Move subagents view into its own independent panel
- Position subagents panel to the left of monitor panel
- Add collapsible/closeable behavior for subagents panel
- Add responsive stacking on small screens
- Simplify monitor panel (now just Screen Sessions + Background Tasks)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move COM shorthand to prominent position after safety warning
- Add version sync note (must match package.json)
- Consolidate Key Files into 4 logical categories
- Clarify next available test port (3128)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Double-click on subagent items in the Subagents tab to open
the floating tracking window. Includes tooltip hint.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract better titles from task description (first line/sentence)
- Make subagent window text white for better readability
- Expand monitor panel to 700px when subagents tab is active
- Add smooth width transition when switching tabs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SubagentWatcher service that discovers and tails Claude Code's subagent
transcript files (~/.claude/projects/.../subagents/agent-*.jsonl)
- Track tool calls, progress events, and messages in real-time via file watching
- Add SSE events for subagent:discovered, subagent:tool_call, subagent:progress,
subagent:message, subagent:completed
- Add REST API endpoints: GET /api/subagents, /api/subagents/:id,
/api/subagents/:id/transcript
- Add subagent panel in Monitor section showing active agents and their activity
- Add floating draggable windows that auto-open for each active agent
- Add standalone CLI tool: scripts/watch-subagents.ts for terminal monitoring
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add isTerminalAtBottom() helper and modify batchTerminalWrite() to implement
sticky scroll behavior. When SSE terminal data arrives after tab switch,
terminal now stays scrolled to Claude input if user was already at bottom.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AiCheckerBase abstract class to eliminate ~700 lines of duplication
between AiIdleChecker and AiPlanChecker
- Fix missing persistence fields (completionConfirmMs, noOutputTimeoutMs)
that caused custom timing values to be lost on server restart
- Extract restoreRespawnController() helper to dedupe session restoration
logic between state.json and screens.json paths
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When /respawn/stop was called, the controller was stopped but remained
in the respawnControllers map. This caused persistSessionState() to
still read config.enabled=true and save respawnEnabled=true to state.json.
On server restart, the respawn controller would be re-enabled because
state.json had respawnEnabled=true.
Fix: Remove controller from map and clear any timed respawn when
/respawn/stop is called, so persistSessionState() correctly sets
respawnEnabled=false.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- persistSessionState() now saves respawnEnabled based on config.enabled
(user intent) instead of controller.state (running state)
- cleanupSession() saves respawn config BEFORE removing controller
- AiIdleChecker and AiPlanChecker constructors filter undefined values
to prevent overwriting defaults (fixes "timed out after undefinedms")
- updateConfig() methods also filter undefined values
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add restoreTokens() method to Session class for recovery after restart
- Add GlobalStats type for cumulative usage tracking across all sessions
- Accumulate tokens from deleted sessions into global stats
- Track lifetime session count with incrementSessionsCreated()
- Add /api/stats endpoint for global stats
- Include globalStats in /api/status response
- Frontend shows aggregate tokens + cost in header
- Fix respawn controller config to filter undefined values
- Add 7 new tests for global stats functionality (v0.1343)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add state check in startPlanCheck() to prevent Enter if state changed
- sendAutoAcceptEnter() now cancels pending AI idle checks and resets state
- Log auto-accept as [command] type for visibility in action log
- Highlight command entries with blue background in action log
- Show action log row when there are actions (not just timers)
- Increase action log height and opacity for better visibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- State label now white on green pill for better visibility
- AI check shows detailed status with color-coded badges:
- Blue: Analyzing terminal output
- Green: Idle confirmed
- Yellow: Working detected
- Gray: Disabled
- Shows time since last check when recent (<2min)
- Bump version to 0.1338
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Respawn banner changes:
- Human-friendly state labels (e.g., "Kickstarting..." vs "waiting_kickstart")
- Removed redundant "→ waiting for" text
- Simplified AI check display (only shows when actively checking)
- Shorter cycle counter (#1 vs "Cycle 1")
- Fixed NaN timer bug with validation
- Flatter HTML structure
CLAUDE.md improvements:
- Reorganized Commands section into clear subsections
- Test port allocation in table format
- Simplified TypeScript config section
- Removed duplicate keyboard shortcuts (already in README)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Display version number in center of bottom toolbar
- Load version from package.json via server's /api/status
- Version shown on initial load and SSE reconnect
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix "enable twice" bug: add enabled:true to getModalRespawnConfig()
- Add timer tracking with countdown display in respawn banner
- New events: timerStarted, timerCancelled, timerCompleted, actionLog
- Show active timers with progress bars and recent action log
- Skip remaining timeouts after AI check returns IDLE/WORKING verdict
- Enhanced DetectionStatus with activeTimers, recentActions, currentPhase
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a two-stage gate before auto-accepting plan mode prompts:
1. Strict regex pre-filter - checks for numbered options + selector
2. AI confirmation - spawns Opus to classify as PLAN_MODE or NOT_PLAN_MODE
This prevents spurious Enter key presses when Claude is paused mid-thought
or experiencing network lag, rather than showing a plan approval prompt.
New files:
- src/ai-plan-checker.ts: AI checker following ai-idle-checker.ts pattern
Config fields added to RespawnConfig:
- aiPlanCheckEnabled (default: true)
- aiPlanCheckModel (default: claude-opus-4-5-20251101)
- aiPlanCheckMaxContext (default: 8000)
- aiPlanCheckTimeoutMs (default: 60000)
- aiPlanCheckCooldownMs (default: 30000)
New events: planCheckStarted, planCheckCompleted, planCheckFailed
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The header-system-stats had its own border-left in addition to the
header-right border-left, creating two vertical lines. Removed the
inner one for a cleaner look.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reduce header-right gap from 1rem to 0.5rem and remove margin-left
from notification button for tighter grouping.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace gear emoji with SVG icon matching the bell, remove extra margin
between them, and ensure both sit at the same vertical position.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use an inline SVG bell that inherits currentColor, matching the gray
monochrome style of the settings gear icon.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
attachCustomWheelEventHandler doesn't exist in xterm.js 5.3.0,
causing initTerminal() to crash and abort all app initialization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Claude's Ink UI enables terminal mouse reporting, causing xterm.js to
forward wheel events to the application. This made scrolling up to read
the plan impossible. Intercept wheel events to always scroll the terminal
viewport directly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split the session options modal into three tabs (Respawn, Context,
Ralph/Todo) to reduce vertical height. Removed redundant header and
border from the Respawn section. Also condensed CLAUDE.md and added
AI idle checker documentation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace the "Worked for Xm Xs" pattern as the sole primary idle
detection signal with a final AI-powered check. When pre-filter
conditions are met (output silence, no working patterns, tokens
stable), a fresh Claude CLI session is spawned in a screen to
analyze terminal output and provide a definitive IDLE/WORKING
verdict before proceeding with the respawn cycle.
New state in state machine: `ai_checking` (between pre-filter
confirmation and `sending_update`). WORKING verdict triggers a
3-minute cooldown. Errors auto-disable after 3 consecutive
failures, falling back to the existing noOutputTimeoutMs safety net.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The server was dropping the `data` field from hook-event POST requests,
so notifications always showed generic messages. Now forwards tool name,
command, question text, and reason to the frontend.
Notifications now show:
- permission_prompt: "Bash: docker push prod:latest"
- elicitation_dialog: "Merge PR #42 to main?"
- idle_prompt: custom message if provided
- stop: reason if provided
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add scripts/claudeman-web.service: respawning systemd user service
for `claudeman web --https` (Restart=always, RestartSec=5)
- Slow tab blink animations: red 1s→2.5s, yellow 1.5s→3.5s
with ease-in-out and reduced opacity for less aggressive feel
Install: symlink to ~/.config/systemd/user/, enable, start
Linger: loginctl enable-linger keeps it running after logout
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Red blink for action-required events (permission_prompt, elicitation_dialog)
- Yellow blink for idle sessions (idle_prompt)
- Alert clears when user clicks the tab or session starts working again
- Only blinks non-active tabs (active tab is already visible)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Three issues fixed:
- Default browserNotifications to true (was false, never fired)
- Remove tab-visibility gate for critical/warning notifications
(monitoring dashboard should alert regardless of tab focus)
- Auto-request Notification permission on first attempt instead of
silently failing (re-sends the notification after permission granted)
- Migrate existing localStorage prefs from v1 default (false → true)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
switchToSession didn't exist - was calling a nonexistent method.
Changed to selectSession which actually switches the active tab and
loads the terminal buffer. Also enhanced browser push notifications
to navigate to the session when clicked (previously only focused window).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add hook:elicitation_dialog SSE handler in frontend (critical urgency)
- Add Desktop Notifications section to README with hook event table
- Add hooks API endpoint to README API reference
- Update CLAUDE.md SSE events and API routes for elicitation_dialog
- Add session log entry for hooks feature
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The auto-accept feature was too aggressive - it would press Enter for any
silence without a completion message, including AskUserQuestion prompts.
Now uses the elicitation_dialog notification hook to detect when Claude is
asking a question, and blocks auto-accept in that case. Only plan mode
approvals (silence with no completion message AND no elicitation signal)
trigger auto-accept.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wire Claude Code's official hooks system (Notification, Stop) to POST
back to Claudeman's new /api/hook-event endpoint, which broadcasts SSE
events consumed by the existing NotificationManager for desktop alerts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Notification prefs are now included in the PUT /api/settings payload
and stored in ~/.claudeman/settings.json. On page load, server-stored
prefs are loaded as fallback when localStorage is empty (e.g. new
browser or cleared cache).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Also closes the notification drawer if it was open when the user
disables notifications in settings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enables the Web Notifications API when accessing via SSH tunnel or
non-localhost URLs. Self-signed cert is auto-generated with openssl
and stored in ~/.claudeman/certs/ for reuse across restarts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After loading the terminal buffer on tab switch, xterm.js wasn't
guaranteed to be scrolled to the bottom, requiring users to manually
scroll down. Fix by:
1. Adding scrollToBottom() after chunkedTerminalWrite completes
2. Adding scrollToBottom() after terminal.focus()
3. Delaying chunkedTerminalWrite resolution by one extra rAF to ensure
xterm.js has finished rendering the final chunk
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of parsing terminal output for <spawn1337> tags, spawn capabilities
are now exposed as native MCP tools that Claude Code can call directly.
The MCP server (stdio transport) proxies requests to the existing REST API.
- Add src/mcp-server.ts with 6 tools: spawn_agent, list_agents,
get_agent_status, get_agent_result, send_agent_message, cancel_agent
- Remove src/spawn-detector.ts and all references in session.ts/server.ts
- Add CLAUDEMAN_API_URL env var propagation to sessions and screens
- Write .mcp.json to case directories during creation
- Remove spawn1337 tag documentation from case-template.md
- Add claudeman-mcp bin entry to package.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The w1/w2/s1/s2 session counter was scanning all sessions regardless
of case name, causing cross-case number inflation. Now only counts
sessions belonging to the same case when determining the next number.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ralph tracker no longer auto-enables on pattern detection. It must be
explicitly enabled per-session (via API) or globally via the new
`ralphEnabled` AppConfig setting. Adds GET/PUT /api/config endpoints
for runtime configuration. Spawn agent ralph enable is unchanged.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When Claude enters plan mode or asks a question (AskUserQuestion), output
stops without a completion message. The new autoAcceptPrompts feature
detects this state and sends Enter after a configurable delay (default 8s)
to accept the plan or select the default option, keeping Claude working
autonomously.
Enabled by default. Adds UI checkbox in the respawn config panel.
Safety: only fires once per silence period, requires prior output,
and won't fire during active respawn cycles.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces the ~400-line inline template string in claude-md.ts with a
file read from src/templates/case-template.md. Removes the hardcoded
/home/arkon/default/CLAUDE.md path from server.ts. The build script
now copies the template to dist/templates/ for production use.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
state.json is now the primary source for session recovery, but
screens.json is used as a fallback for respawn config since it was
the proven working path before. This provides double-redundancy:
both files would need to be lost for respawn state to disappear.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
cleanupSession() always called store.removeSession() which deleted the
session from state.json. On server stop, cleanupSession(id, false) was
called for all sessions - preserving screens but deleting their saved
state. On next restart, state.json was empty so nothing was restored.
Now only removes from state.json when killScreen=true (user explicitly
deleting a session), preserving state for recovery on restart.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All session settings (auto-compact, auto-clear, ralph, respawn) are now
restored from state.json on server restart. Previously settings were
split across state.json, screens.json, and state-inner.json which was
fragile. state-inner.json is kept as a fallback for ralph state only.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
persistSessionState was called before the respawn controller was restored,
so respawnEnabled was always saved as false during recovery. Moved the
persist call to after all restorations (auto-compact, auto-clear, ralph,
respawn) are applied.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>