feat: Electron desktop wrapper for macOS app distribution#3
Merged
Conversation
- Add desktop/ directory with Electron shell that spawns the Python/Gradio subprocess and embeds the UI in a native window (no browser tabs) - Splash screen shown during Python startup; window revealed once Gradio is ready; closing the window terminates the Python process cleanly - Port-fallback logic tries 7860-7862 in order - electron-builder config targets ARM64 DMG for internal distribution - scripts/build.sh automates bundling Python runtime + dependencies - Set ELECTRON_RUN=1 env var so main.py suppresses Gradio's inbrowser auto-launch when running inside Electron - Add desktop build artifacts to .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New FastAPI server (src/ui/server.py): camera API, MJPEG stream, clip download, all bound to 127.0.0.1 only - /api/config endpoint for ROI options and slowdown presets - /api/status returns buffer stats, FPS, connection state - CORS restricted to views:// and localhost origins only - Clips stored in ~/Movies/High Speed Camera/ via HSCAM_CLIPS_DIR env var - MJPEG generator exits cleanly on client disconnect (GeneratorExit) - Recording thread is non-daemon; SIGTERM waits up to 10 s for flush - Atomic clip write: .tmp file renamed on success, no corrupt files on kill - Ring buffer keeps most-recent frames when target FPS is reduced - Remove Gradio modules: app.py, session.py, errors.py, lifecycle.py - Switch to opencv-python-headless (no Qt GUI needed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Serves via Electrobun views:// scheme — no browser URL bar. - ROI presets and slowdown controls loaded from /api/config on startup - MJPEG stream preview via <img src="/stream"> - Blob URL download for WKWebView compatibility - Buffer bar denominator syncs from clip_duration_sec each poll - Settings response correctly parsed from data.settings.* - Record poll resets to idle after 20 s timeout (no infinite-saving hang) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Electrobun uses Bun/TypeScript for the main process and WKWebView for the UI. - index.ts: spawn Python/FastAPI, poll /api/status for readiness, inject active port, handle startup failure with visible error screen - build.sh: full pipeline — python-build-standalone + uv + bun build; removes com.apple.quarantine from libmvsdk.dylib so Gatekeeper doesn't block it - Clips stored in ~/Movies/High Speed Camera/ (HSCAM_CLIPS_DIR env var) - Port retry: 50 ms sleep after kill so OS releases socket before next attempt - Remove old Electron files: main.js, electron-builder.yml, package-lock.json - Splash window relocated to desktop/src/splash/index.html Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add tests/integration/test_server_api.py: 19 tests covering /api/status, /api/config, /api/cameras, /api/settings validation, /api/record lifecycle, and localhost binding assertion - Remove tests that imported deleted Gradio modules: test_scenario_02_single_viewer.py (ViewerSession) test_scenario_05_localhost.py (launch_app) test_viewer_session_contract.py (session module) test_gradio_ui_contract.py (Gradio UI contract) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updates .claude, .cursor, .cline, .gemini, .github, .amazonq, .kilocode, .opencode, .qwen, .windsurf, and .clinerules with the opsx skill set (explore, propose, apply, archive). Removes the old openspec command files. Also updates AGENTS.md, CLAUDE.md, CLINE.md, adds QWEN.md, and adds openspec/ design/spec documents for the Gradio → FastAPI migration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FastAPI + Electrobun desktop wrapper (v0.2.0)
This branch replaces the Gradio web UI with a native macOS
.appbundle. Non-technical operators double-click to open — no Python, pip, or terminal required.Backend
src/ui/server.py: FastAPI replacing Gradio. MJPEG live preview, camera API, clip download, all on127.0.0.1only (no LAN exposure)./api/configendpoint — single source of truth for ROI options and slowdown presets. Frontend no longer duplicates hardware constants.~/Movies/High Speed Camera/(persistent across app updates).views://and localhost origins (was wildcard).Desktop wrapper
desktop/src/bun/index.ts: Electrobun main process replaces Electron. Spawns Python, polls/api/statusfor readiness, shows error screen with Close button on failure.desktop/scripts/build.sh: hermetic build pipeline — python-build-standalone ARM64 + uv + bun. Removescom.apple.quarantinefromlibmvsdk.dylibso Gatekeeper doesn't block it.Reliability fixes (from adversarial review)
.tmp→ rename on success. No corrupt files if killed mid-save.GeneratorExit— no leaked generators accumulating after reconnects.data.settings.*(wasdata.*— always undefined).Tests
tests/integration/test_server_api.py: 19 tests covering all FastAPI endpoints.Test Coverage
All new server endpoints have integration tests. TypeScript/JS frontend code is not unit tested (expected — no browser test framework configured; the WKWebView renders are verified manually).
Tests: 81 → 100 (+19 new)
Pre-Landing Review
No issues found. All adversarial findings fixed (7 auto-fixed + 4 user-approved).
Design Review
No frontend framework changes — custom HTML/JS/CSS served via views://. No design review tool applicable.
Adversarial Review
13 findings from Claude subagent:
Auto-fixed:
User-approved fixes:
Scope Drift
Scope: CLEAN
Intent: replace Electron + Gradio with Electrobun + FastAPI for macOS distribution
Delivered: exactly that, plus reliability fixes surfaced by adversarial review
Plan Completion
No formal plan file. Design doc at
~/.gstack/projects/high-speed-camera-testing/swong-feat-electron-desktop-wrapper-design-20260331-161613.md. All code items implemented. Two deferred items (hardware test on clean Mac, DMG creation) tracked in TODOS.md.TODOS
Created TODOS.md:
Test plan
🤖 Generated with Claude Code