# @mac-sync Unified macOS sync agent. One menu-bar app on the Mac, one Bun/Hono server on the LAN, one React SPA in the browser — six personal data domains kept in step: Messages, Photos, Mail, Calendar, Reminders, Notes. `@mac-sync` collapses what used to be three separate agents (`mac-imessage-sync`, `mac-iphoto-sync`, `mac-imail-sync`) into a single Swift package with one `BaseSyncManager` lifecycle, one `SendQueueClient` outbound poller, one `AppleScriptEscape` helper, and one Postgres schema (`icloud.*`). ## At a glance | Module | Direction | OS surface | Read interval | Outbound interval | |--------------|------------------|----------------------------------|--------------:|------------------:| | iMessage | bidirectional | `~/Library/Messages/chat.db` | 30s | 30s | | iPhoto | read-only | Photos.framework | 300s | — | | iMail | read-only (*) | Mail.app via AppleScript | 300s | — | | iCal | bidirectional | EventKit | 300s | 60s | | iReminders | bidirectional | EventKit | 300s | 60s | | iNotes | bidirectional | Notes.app via AppleScript | 600s | 60s | (*) `IMailSync.SyncManager.sendEmail` exists but is unwired; see [known limitations](./docs/known-limitations.md). Intervals verified in `BaseSyncManager` `super.init(...)` calls and `SendQueueClient(label:..., interval:)` constructions; see [architecture](./docs/architecture.md) for citations. ## Repository layout ``` @packages/ shared/ MacSyncShared SwiftPM target Sync/ BaseSyncManager, SendQueueClient, SyncConnectionError Storage/ ActivityLog, ConfigFile Transport/ Shared (server URL resolution), DeviceRegistration Util/ AppleScriptEscape, ContentTypeMapping, PhoneUtils WebServer/ LocalWebServer (localhost:8765, settings + SPA) imessage/ IMessageSync (bidirectional, legacy icloud.send_queue table) iphoto/ IPhotoSync (read-only Mac to server, with binary uploads) imail/ IMailSync (Mail.app AppleScript reader; Sender unwired) ical/ ICalSync (bidirectional, EventKit + calendar_send_queue) ireminders/ IReminderSync (bidirectional, EventKit + reminder_send_queue) inotes/ INoteSync (bidirectional, AppleScript + note_send_queue) src/client/ MacSyncApp (executable menu-bar app) src/server/ Bun + Hono + PostgreSQL (TypeScript) web/ React SPA dashboard (Vite, react-query) deploy/ install.sh, deploy-remote.sh, systemd units, nginx config ``` (See `Package.swift:21-157` for the canonical target list.) ## Get started - Set up a dev environment: [docs/dev-setup.md](./docs/dev-setup.md) - Tour the system: [docs/architecture.md](./docs/architecture.md) - Trace a sync end-to-end: [docs/data-flow.md](./docs/data-flow.md) - Add a 7th module: [docs/adding-a-module.md](./docs/adding-a-module.md) - Ship a release: [docs/release.md](./docs/release.md) - Known gotchas: [docs/known-limitations.md](./docs/known-limitations.md) Per-module deep dives: - [Messages (iMessage)](./docs/modules/imessage.md) - [Photos (iPhoto)](./docs/modules/iphoto.md) - [Mail (iMail)](./docs/modules/imail.md) - [Calendar (iCal)](./docs/modules/ical.md) - [Reminders (iReminders)](./docs/modules/ireminders.md) - [Notes (iNotes)](./docs/modules/inotes.md) ## Build & test ```sh make build # swift build --product MacSyncApp (Makefile:60-61) make test # swift test (Makefile:71-73) make run # build then run .build/debug/MacSyncApp ``` Server: ```sh cd src/server && bun run dev # src/server/package.json:7 ``` Web: ```sh cd web && bun run dev # vite --port 5200 (web/package.json:7) ``` ## Safety - NEVER commit — an external service handles commits (`CLAUDE.md:46`). - NEVER `pkill node` / `killall node` — kills Claude Code sessions. - NEVER use `file:` or `link:` in `package.json` — edit source, publish, bump.