diff --git a/CLAUDE.md b/CLAUDE.md index 8aa7752f..f82e3fa4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,7 @@ When user says "COM": 1. Increment version in BOTH `package.json` AND `CLAUDE.md` (verify they match with `grep version package.json && grep Version CLAUDE.md`) 2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web` -**Version**: 0.1618 (must match `package.json`) +**Version**: 0.1619 (must match `package.json`) ## Project Overview diff --git a/package.json b/package.json index cb518489..51df94ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claudeman", - "version": "0.1618", + "version": "0.1619", "description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence", "type": "module", "main": "dist/index.js", diff --git a/src/web/public/app.js b/src/web/public/app.js index 95a5dc01..c663477a 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -16057,22 +16057,76 @@ class ClaudemanApp { let html = ''; for (const muxSession of this.muxSessions) { const stats = muxSession.stats || { memoryMB: 0, cpuPercent: 0, childCount: 0 }; - const modeClass = muxSession.mode === 'shell' ? 'shell' : ''; + + // Look up rich session data by sessionId + const session = this.sessions.get(muxSession.sessionId); + const status = session ? session.status : 'unknown'; + const isWorking = session ? session.isWorking : false; + + // Status badge + let statusLabel, statusClass; + if (status === 'idle' && !isWorking) { + statusLabel = 'IDLE'; + statusClass = 'status-idle'; + } else if (status === 'busy' || isWorking) { + statusLabel = 'WORKING'; + statusClass = 'status-working'; + } else if (status === 'stopped') { + statusLabel = 'STOPPED'; + statusClass = 'status-stopped'; + } else { + statusLabel = status.toUpperCase(); + statusClass = ''; + } + + // Token and cost info + const tokens = session && session.tokens ? session.tokens : null; + const totalCost = session ? session.totalCost : 0; + const model = session ? (session.cliModel || '') : ''; + const modelShort = model.includes('opus') ? 'opus' : model.includes('sonnet') ? 'sonnet' : model.includes('haiku') ? 'haiku' : ''; + + // Ralph/Todo progress + const todoStats = session ? session.ralphTodoStats : null; + let todoHtml = ''; + if (todoStats && todoStats.total > 0) { + const pct = Math.round((todoStats.completed / todoStats.total) * 100); + todoHtml = `${todoStats.completed}/${todoStats.total} (${pct}%)`; + } + + // Format tokens + let tokenHtml = ''; + if (tokens && tokens.total > 0) { + const totalK = (tokens.total / 1000).toFixed(1); + tokenHtml = `${totalK}k tok`; + } + + // Format cost + let costHtml = ''; + if (totalCost > 0) { + costHtml = `$${totalCost.toFixed(2)}`; + } + + // Model badge + let modelHtml = ''; + if (modelShort) { + modelHtml = `${modelShort}`; + } html += `