macsync/README.md

97 lines
4.2 KiB
Markdown
Raw Normal View History

# @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.