Files
fidelity-ai-workspace/core/services/macos-installation-model.md

3.3 KiB

macOS Installation Model

How production macOS utilities commonly do it

Apps such as Cloudflare WARP, VPN clients, Docker Desktop, and device agents usually separate:

  • a user-facing app or menu bar app;
  • one or more background services;
  • launchd configuration for automatic startup;
  • privileged helpers only when system-level networking, drivers, packet filtering, or protected paths are required.

Common mechanisms:

  • LaunchAgent in ~/Library/LaunchAgents for per-user background/login startup.
  • LaunchDaemon in /Library/LaunchDaemons for root/system services.
  • SMAppService / login items for sandboxed or App Store-aligned apps.
  • Privileged helper tools via SMJobBless when admin-level installation is required.
  • .pkg installers when the install needs privileged locations, daemons, receipts, or managed deployment.

Use a staged model:

  1. Current local developer install

    • Build a real .app bundle into apps/mac/AIWorkspace/dist/.
    • Install to ~/Applications/AIWorkspace.app.
    • Install a per-user LaunchAgent for start at login.
  2. Production-ready local install

    • Keep using a per-user LaunchAgent because services are local user tools and do not require root.
    • Add a one-step installer script that builds, installs, optionally enables start at login, and opens the app.
    • Avoid privileged helpers until a real system-level requirement appears.
  3. Future polished distribution

    • Create a signed/notarized .app distributed in a .dmg with an Applications shortcut, or a .pkg only if privileged installation becomes necessary.
    • Use SMAppService for login item management from inside the app so the user can toggle Start at Login in the UI instead of running launchctl scripts manually.
    • Add a small daemon API if the UI needs richer lifecycle control than shelling out to services.py.

Desired user-grade install flow

For a Cloudflare/Docker-like local experience, the target should be:

  1. User opens AIWorkspace.dmg.
  2. User drags AIWorkspace.app to /Applications or ~/Applications.
  3. User launches the app.
  4. App shows service status and a Start at Login toggle.
  5. App registers/unregisters itself as a login item using SMAppService.
  6. App starts/stops workspace services through the service manager.

The existing shell scripts remain useful for development and bootstrap, but should not be the primary end-user experience once the app handles login item registration itself.

Current implementation state

  • AIWorkspace.app can be packaged from apps/mac/AIWorkspace/scripts/package-app.sh.
  • AIWorkspace.dmg can be built from apps/mac/AIWorkspace/scripts/build-dmg.sh.
  • The app UI includes a Start at Login toggle backed by SMAppService.mainApp.
  • LaunchAgent scripts remain as development fallbacks, not the preferred user path.

Why not LaunchDaemon now

The current services are user-context services:

  • Mattermost Desktop launching must happen in the user's GUI session.
  • Photo Inbox writes to user-owned folders and uses clipboard/notifications.
  • The MCP and proxy bind localhost ports and do not require root.

A root daemon would add unnecessary permission prompts and security risk. A per-user LaunchAgent is the correct production-leaning step for this stage.