feat: dashboard UX — shortcuts, reconnect, per-project sessions - #14
Conversation
- Ctrl+B toggles sidebar (VSCode-style, intercepted even in terminal) - Ctrl+O passes through to Claude Code for show-details - Auto-reconnect WebSocket with exponential backoff on disconnect - Reconnect on tab visibility change (browser suspend recovery) - Per-project "+" button to start sessions in project directory - createSession now accepts optional workingDirectory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| // Reconnect when tab regains focus (browser may have killed the WS) | ||
| const handleVisibility = () => { | ||
| if ( | ||
| document.visibilityState === "visible" && |
There was a problem hiding this comment.
🟡 Warning
Problem: handleVisibility can trigger connect() while a pending reconnectTimer is still queued. If the WS dropped while the tab was hidden, the timer was already scheduled — then visibility fires and calls connect() immediately, then the timer fires and calls connect() again. The second call overwrites wsRef.current, leaving the first socket as a zombie writing duplicate data into the terminal.
Why it matters: User returns to tab, gets reconnected, sees output — then a second WebSocket fires ~1s later and starts writing duplicate/interleaved terminal data. Hard to reproduce reliably, but definitely possible.
Suggested fix:
const handleVisibility = () => {
if (
document.visibilityState === "visible" &&
wsRef.current?.readyState !== WebSocket.OPEN &&
wsRef.current?.readyState !== WebSocket.CONNECTING
) {
if (reconnectTimer) {
clearTimeout(reconnectTimer);
reconnectTimer = null;
}
retryDelay = 1000;
connect();
}
};
nox-0x
left a comment
There was a problem hiding this comment.
Solid UX wins — reconnect logic, per-project sessions, and keyboard shortcuts all look clean. One warning left inline: handleVisibility needs to clear the pending reconnectTimer before calling connect() to avoid a double-socket race that could write duplicate output to the terminal. Easy one-liner fix, not blocking merge.
…F-003) Add a ChatGPT-style conversation view for browsing Claude Code session transcripts. User messages appear as right-aligned bubbles, assistant messages flow freely on the left with an avatar. Tool calls render as expandable blocks with status indicators and tool-specific summaries. Architecture: Parser (provider-specific) → RenderItem[] (stable contract) → Renderer (swappable). ClaudeCodeParser handles JSONL format with cross-message tool_use/tool_result pairing. New packages/routes: - core: RenderItem types, SessionParser interface, ClaudeCodeParser - server: GET /api/conversation/:sessionId endpoint - dashboard: ConversationView, ToolCallBlock, ThinkingBlock components Also fixes TS errors from PR #14 (Sidebar onClick signature, sessionId null check). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
+button that starts a session in that project's directory.createSessionnow accepts optionalworkingDirectoryTest plan
+appears → click starts session in that project dir+still creates session at~🤖 Generated with Claude Code