diff --git a/src/services/unified-session-service.ts b/src/services/unified-session-service.ts
index 16fb7d11..03b7c618 100644
--- a/src/services/unified-session-service.ts
+++ b/src/services/unified-session-service.ts
@@ -29,6 +29,7 @@ export type UnifiedSessionItem = {
claudeSessionId?: string;
firstPrompt?: string;
sizeBytes?: number;
+ projectKey?: string;
remote?: boolean;
sources: string[];
stats?: { memoryMB: number; cpuPercent: number };
@@ -76,6 +77,7 @@ export type HistoryInput = {
sizeBytes: number;
lastModified: string;
firstPrompt?: string;
+ projectKey?: string;
};
/** Mux process-stat view. */
@@ -147,6 +149,7 @@ export function mergeUnifiedSessions(sources: UnifiedSources): UnifiedSessionIte
overwrite(item, 'workingDir', h.workingDir);
overwrite(item, 'sizeBytes', h.sizeBytes);
overwrite(item, 'firstPrompt', h.firstPrompt);
+ overwrite(item, 'projectKey', h.projectKey);
const ms = Date.parse(h.lastModified);
if (!Number.isNaN(ms) && item.lastActivityAt === undefined) item.lastActivityAt = ms;
}
diff --git a/src/web/public/app.js b/src/web/public/app.js
index bf24e78e..ea3ccd66 100644
--- a/src/web/public/app.js
+++ b/src/web/public/app.js
@@ -1421,6 +1421,18 @@ class CodemanApp {
for (const [event] of _SSE_HANDLER_MAP) {
addListener(event, this._sseHandlerWrappers.get(event));
}
+
+ // COD-121: live-refresh the unified session list (Session Manager modal +
+ // visible welcome list) on session structural changes. Extra listeners on the
+ // same EventSource — EventSource supports multiple listeners per event — so the
+ // existing handlers above are untouched. Registered through addListener so they
+ // are torn down with the rest on reconnect. Only structural events (created /
+ // deleted) trigger a refetch: session:updated is batch-broadcast every ~500ms
+ // per active session, which would otherwise turn an open modal / visible welcome
+ // list into a sustained ~1 Hz full ~/.claude/projects rescan loop.
+ for (const event of [SSE_EVENTS.SESSION_CREATED, SSE_EVENTS.SESSION_DELETED]) {
+ addListener(event, () => this._onSessionListMaybeChanged());
+ }
}
// ═══════════════════════════════════════════════════════════════
diff --git a/src/web/public/index.html b/src/web/public/index.html
index 79d5ab8b..bf1d34ab 100644
--- a/src/web/public/index.html
+++ b/src/web/public/index.html
@@ -119,6 +119,7 @@
+