name the live sessions instead of showing their ids

The titles were looked up client-side against the sessions query already in cache, which only covers the
group being browsed — so anything running in another directory rendered as a truncated uuid, which is
most of them.

Resolved server-side now. The agent reports keys and nothing else, so liveSessionTitle finds the
transcript by scanning the project slugs, takes the cwd off its own first entry, and hands that to
claudeSessionContext — the same path the list uses, so the two agree on naming, /clear chains merged
included, rather than offering a second opinion.

A null title means no transcript has been written yet. That row says 'Starting…' and is deliberately not
a link: pointing at a session you cannot open yet is worse than plainly not being a link.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 01:18:54 +01:00
co-authored by Claude Opus 5
parent 8f2d80573a
commit 27bbbaee47
4 changed files with 77 additions and 18 deletions
+11 -1
View File
@@ -12,6 +12,7 @@ import {
renameClaudeSession,
loadBackgroundTask,
claudeSessionContext,
liveSessionTitle,
} from './claude-sessions';
import {
listOpenCodeSessions,
@@ -100,8 +101,17 @@ chatRouter.get('/sessions/:id', async (ctx) => {
//
// `pendingTasks` is background work started but not yet notified — with `isGenerating` it is what the
// agent's own idle GC consults, so a caller can tell "busy" from "merely open" the same way it does.
// Titles are resolved here rather than in the client: the agent reports session keys and nothing else,
// and the client can only name the sessions in the group it happens to be browsing — which is how the
// list ended up showing raw ids for anything running elsewhere.
chatRouter.get('/live', async (ctx) => {
return ctx.json({ sessions: await sidecar.listLiveClaudeSessions() });
const email = ctx.get('user').email;
const live = await sidecar.listLiveClaudeSessions();
const sessions = live.map((session) => {
const resolved = isOpenCodeSessionId(session.sessionKey) ? null : liveSessionTitle(email, session.sessionKey);
return { ...session, title: resolved?.title ?? null, cwd: resolved?.cwd ?? null };
});
return ctx.json({ sessions });
});
// DELETE /chat/sessions/:id[?cwd=] — remove a conversation from the owning harness's store. For a