Skip to content

feat(desktop): native macOS app packaged as Apple Silicon DMG - #26

Merged
stretchcloud merged 1 commit into
mainfrom
feat/desktop-app
Jul 7, 2026
Merged

feat(desktop): native macOS app packaged as Apple Silicon DMG#26
stretchcloud merged 1 commit into
mainfrom
feat/desktop-app

Conversation

@stretchcloud

Copy link
Copy Markdown
Owner

Summary

  • Adds a native macOS desktop app (Apple Silicon) under desktop/, distributed as a DMG attached to GitHub Releases.
  • The app is a thin Electron shell: it boots the full Campfire server (same Bun + Hono backend as npm/Docker) as a bundled sidecar — backend sources, a minimal production node_modules (hono, croner, @lancedb/lancedb), and the Bun runtime ship inside the .app — then loads the web UI in a native window. Every feature is included by construction.

Why

  • One-click install for Mac users: no Bun, no terminal, no npm. Download DMG → drag to Applications.
  • Distribution is free: ad-hoc signing (no Apple Developer account), DMG built on the free macos-14 runner, hosted on GitHub Releases.

Behavior

  • Reuse-first: attaches to an existing Campfire on :4567 (service installs, bunx the-campfire) instead of double-spawning against ~/.campfire; otherwise spawns the sidecar on the first free port.
  • Shared ~/.campfire state with the CLI/web flavors; sidecar logs at ~/.campfire/logs/desktop-server.log; Cmd+Q stops the sidecar, agent processes resume on next launch like any server restart.
  • External links open in the default browser; native menu, window-state persistence, crash dialog with relaunch.

Notable fixes found along the way

  • electron-builder silently drops node_modules from extraResources; the bundle appeared to work because Bun auto-installs missing packages at runtime (would break offline). The afterPack hook now copies them explicitly.
  • codesign rejects node_modules/.bin symlinks — stripped during packaging.
  • The orchestration MCP server was spawned via a bare bun PATH lookup; it now uses the running Bun executable's absolute path, so multi-agent tools work in the desktop app and on machines without a global Bun install.

Testing

  • web: typecheck + full suite green (87 files, 1635 tests), including new coverage for the Bun-runtime MCP command branch.
  • desktop: 6 unit tests for the boot helpers (free-port scan, Campfire probe, readiness wait).
  • Manual: staged sidecar boots with the bundled Bun; Electron smoke run (spawn → load UI → clean exit); DMG mounted and launched; GUI (Finder) launch verified — cold start ~22 s (one-time Gatekeeper scan), warm ~3 s; clean teardown confirmed twice; signature verifies (codesign --verify --deep --strict).

An Electron shell that boots the full Campfire server as a bundled Bun
sidecar (backend + minimal node_modules + Bun runtime staged into the app
bundle), so every backend and feature ships identically to the web build
with no Bun install required.

- Reuse-first boot: attaches to an existing Campfire on :4567 (service
  installs, bunx) instead of double-spawning against ~/.campfire;
  otherwise spawns on the first free port
- afterPack hook copies backend node_modules (electron-builder drops them
  from extraResources by default) and ad-hoc signs the bundle (valid
  signature on Apple Silicon, no Apple Developer account needed)
- Orchestration MCP server now spawns via the running Bun executable's
  absolute path so multi-agent tools work without a global bun install
- CI: macos-14 job builds the DMG on v* tags and attaches it to the
  GitHub Release; desktop helper tests wired into ci.yml
- make desktop-stage / desktop / dmg targets; docs in desktop/README.md
@stretchcloud
stretchcloud merged commit ff79b24 into main Jul 7, 2026
1 check passed
@stretchcloud
stretchcloud deleted the feat/desktop-app branch July 7, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant