From 6e9788804fa620518fd258389f6c2d5b8f55b8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Tue, 24 Feb 2026 01:54:15 +0000 Subject: [PATCH] fix: deduplicate idle sessions and refresh session data on transitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple claude processes in the same CWD share one sessionFile via findActiveJsonl, causing duplicate idle entries. Now deduplicates by project+sessionFile key. Also refreshes session data on busy→idle transitions so the parser fix takes effect immediately. Co-Authored-By: Claude Opus 4.6 --- src/data/monitor.ts | 10 +++++++--- src/index.ts | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/data/monitor.ts b/src/data/monitor.ts index 79ae150..6039253 100644 --- a/src/data/monitor.ts +++ b/src/data/monitor.ts @@ -267,14 +267,17 @@ export interface IdleSessionInfo { } export function getIdleSessions(projects: Project[]): IdleSessionInfo[] { - const idle: IdleSessionInfo[] = [] + // Deduplicate by project+sessionFile — multiple processes in same CWD share one sessionFile + const seen = new Map() for (const project of projects) { const sessions = sessionsByPath.get(project.path) if (!sessions) continue for (const s of sessions) { if (s.busy) continue if (!s.lastActivityMs) continue - // Find matching session info for title/prompt + const dedupeKey = `${project.path}:${s.sessionFile || s.pid}` + const existing = seen.get(dedupeKey) + if (existing && existing.idleSinceMs >= s.lastActivityMs) continue let title = "" let lastPrompt = "" let lastResponse = "" @@ -288,7 +291,7 @@ export function getIdleSessions(projects: Project[]): IdleSessionInfo[] { lastResponse = match.lastAssistantMsg } } - idle.push({ + seen.set(dedupeKey, { projectPath: project.path, projectName: project.name, tty: s.tty, @@ -299,6 +302,7 @@ export function getIdleSessions(projects: Project[]): IdleSessionInfo[] { }) } } + const idle = Array.from(seen.values()) idle.sort((a, b) => b.idleSinceMs - a.idleSinceMs) return idle } diff --git a/src/index.ts b/src/index.ts index 2d5b0e9..4e5a0c3 100755 --- a/src/index.ts +++ b/src/index.ts @@ -812,14 +812,14 @@ async function main() { } else { const sessions = await detectActiveSessions() const changed = updateProjectSessions(projects, sessions) - // Eagerly load session data for active projects (needed for idle panel) + const transitioned = checkTransitions(projects, prevBusySnapshot) + // Eagerly load/refresh session data for active projects (needed for idle panel) for (const p of projects) { - if (p.activeSessions > 0 && !p.sessions) { + if (p.activeSessions > 0 && (!p.sessions || transitioned.length > 0)) { p.sessions = await loadSessions(p.path) p.sessionCount = p.sessions.length } } - const transitioned = checkTransitions(projects, prevBusySnapshot) prevBusySnapshot = snapshotBusy(projects) if (transitioned.length > 0) { playDoneSound()