feat: Electron desktop app#7
Conversation
Ports the Bubble Tea TUI to a native Electron desktop app while keeping the existing CLI intact. Architecture: Go WebSocket server (cmd/warroom-server) exposes the debate Runner's async event loop over WS, and an Electron frontend (electron/) connects and renders the same 3-column dashboard (models, activity feed, stats) with web technologies. New files: - cmd/warroom-server/main.go — WebSocket server wrapping debate.Runner - electron/ — Electron app (main process, preload, HTML/CSS/JS renderer) - Justfile recipes: build-server, electron, electron-build Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WalkthroughThese changes introduce an Electron-based desktop client for the Warroom application, paired with a new WebSocket-based Go server. The Go server manages debate state, handles LLM interactions, and streams state updates to clients. The Electron app provides a real-time dashboard UI with model roster, activity feed, and statistics. Build infrastructure and dependencies are updated to support the new components. Changes
Sequence Diagram(s)sequenceDiagram
participant R as Renderer (JS)
participant EM as Electron Main
participant GS as Go Server
participant WS as WebSocket
EM->>GS: Spawn server process
GS->>EM: stdout: port number
EM->>EM: Port received, store
EM->>R: App ready, window created
R->>EM: getServerPort() via IPC
EM-->>R: Return port
R->>WS: WebSocket connect to localhost:port/ws
WS->>GS: Connection established
GS->>WS: Send "hello" with models/presets
WS->>R: Receive hello message
R->>R: Render start screen
R->>WS: Send "set_api_key" message
WS->>GS: Process API key
GS->>WS: Send state snapshot
WS->>R: Receive state update
R->>R: Render dashboard
R->>WS: Send "set_topic" message
WS->>GS: Initialize debate runner
GS->>GS: Execute round logic
GS->>WS: Send state updates
WS->>R: Stream activity/model status
R->>R: Real-time dashboard refresh
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~50 minutes
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
Core resilience: - #1: Add React ErrorBoundary wrapping the app — render errors now show a styled fallback with reload button instead of a white screen - #2: Wire onUpdateDownloaded from preload into useDebate state so the renderer can display an update-available banner - #4: Remove dead submitTopic from useDebate hook and DebatePage - #5: Add backend crash detection — main process forwards Go exit event via IPC, preload exposes onBackendExited, useDebate sets connected=false and shows error banner when backend dies - #8: Fix route param changes being silently ignored — remove stale connectedRef guard; useEffect now disconnects previous session and reconnects on topic/resume change - #11: Fix O(n²) activity scan per stream tick — walk backwards and break on first match instead of .map + .slice().some() per element - #19: Add beforeunload handler during active debates to prevent accidental window close / data loss Accessibility: - #6: Add ARIA attributes across all components — role="alert" on ErrorBanner, role="status" + aria-label on GlowDot, role="complementary" on ModelRoster, role="progressbar" on progress bars, aria-label on textarea and dialog, aria-checked on QuestionStep options - #12: Add focus management to AskUserOverlay — saves previous focus, auto-focuses first interactive element on mount, restores focus on unmount, implements keyboard focus trap (Tab/Shift+Tab) - #14: Surface JSON parse errors in AskUserOverlay — shows visible error state with dismiss button instead of silently fabricating a question - #15: Fix partial answer submission — check raw answers array for all-empty instead of checking formatted string against "(no answer)" UX polish: - #3: Delete dead LoadingState component (zero imports) - #7: Lower noise-overlay z-index from 50 to 1 to avoid stacking conflict with titlebar drag region - #9: Add "Open Folder" button to SessionListPage using the existing but previously unused openSessionsFolder preload API - #10: Extract renderTranscriptEvent and roleBadge as pure functions outside DebateDashboard component to avoid recreation on every render - #13: Replace hardcoded Tailwind colors in StatusBadge with theme tokens (text-success, text-error, text-warning) - #16: Add window.confirm() before shutdown to prevent accidental cancellation of in-progress debates - #18: Add refresh() to useSessionList hook, wire refresh button and visibilitychange auto-refresh to SessionListPage - #21: Remove defaultOpen from transcript Collapsibles in SessionDetailPage — long transcripts now load collapsed https://claude.ai/code/session_01QPxpz4R7j4MFwGAqLEkwpb
Summary
cmd/warroom-server) wraps the existingdebate.Runnerevent loop and exposes state + actions over WebSocketelectron/) renders the same 3-column dashboard (models roster, activity feed, stats) with web technologiesArchitecture
New files
cmd/warroom-server/main.goelectron/main.jselectron/preload.jselectron/renderer.htmlelectron/renderer.csselectron/renderer.jselectron/package.jsonUsage
Test plan
just electronlaunches the app🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Chores