Bridge Apple Find My friends to Home Assistant — automatically, privately, no cloud required.
FollowMyFriends is a native macOS menu-bar app that reads your friends' locations directly from the Apple Find My database on your Mac and publishes them to Home Assistant via MQTT. No third-party accounts, no location-sharing APIs, no cloud relay — just your local network.
Tracker — live location cards with GPS accuracy, motion state, location label, and MQTT publish status
People — manage tracked contacts, assign avatar colours, and view the live map + MQTT payload preview in the detail panel
Settings — MQTT connection, polling schedule with randomisation, Find My wait time, and night mode
Apple's Find My app stores your friends' GPS locations in an encrypted SQLite database at:
~/Library/Group Containers/group.com.apple.findmy.findmylocateagent/
Library/Application Support/LocalStorage.db
FollowMyFriends:
- Decrypts the database using a locally-stored AES-256 key (extracted once with findmy-key-extractor)
- Merges the WAL (Write-Ahead Log) to get the freshest location data —
findmylocateagentwrites here every ~20 minutes - Parses the binary plist location payload for each friend
- Publishes to Home Assistant via MQTT using the MQTT Device Tracker integration with auto-discovery
- Reads GPS coordinates, accuracy radius, altitude, speed, and motion state (stationary/moving) for every Find My friend
- Detects and publishes
locationLabel— Home Assistant location names like Home, Work, or custom places - Publishes
home/not_homestate per the Home Assistant device tracker spec
- WAL file watcher: instantly reacts when
findmylocateagentwrites new location data — no fixed poll interval required - Configurable poll schedule: set min/max intervals with optional randomisation to prevent predictable patterns
- Night mode: automatically pause tracking during configurable quiet hours to reduce unnecessary activity
- Manual refresh: trigger an immediate read at any time with one click
- Publishes MQTT discovery payloads so device trackers appear in Home Assistant automatically — zero manual YAML
- Attributes published per person:
latitude,longitude,gps_accuracy,motion_state,location_label,last_update,location_timestamp - Configurable topic prefix (default:
homeassistant/device_tracker/) - Retained discovery and attribute messages survive MQTT broker restarts
- Re-publishes discovery on every reconnect
- All data stays on your local network — no cloud services, no external APIs
- AES-256 encryption key stored locally on your Mac (never transmitted)
- MQTT credentials stored securely in macOS Keychain
- No app sandbox — required to access Find My's protected database directory via user-granted folder access (NSOpenPanel)
- macOS Sequoia blocks Full Disk Access for ad-hoc signed apps — FollowMyFriends works around this by requesting user-intent access to the Find My Application Support folder via a standard file picker dialog
- One-time grant; persists across launches
- No SIP bypass, no scripting additions, no privileged helpers
- Colour-coded live log with categories: INFO, MQTT, DECRYPT, WAL, ERROR
- GPS fix freshness indicator — shows exactly how old Apple's data is and highlights when a new fix arrives (★)
- Searchable and filterable by category
- Export to file for debugging
- MQTT host, port, username, password, topic prefix
- Poll intervals (min/max) with randomisation toggle
- Find My wait time (how long to keep Find My open per poll cycle)
- Night mode start/end times
- "Grant FindMy Folder Access" button always accessible
- One-click connection test
- Register as a Login Item via standard macOS
SMAppServiceAPI - Optionally opens Find My invisibly in the background (
activates: false, hides: true) each poll cycle to triggerfindmylocateagentserver polls
| Requirement | Details |
|---|---|
| macOS | 14.0 Sonoma or later |
| Find My | Must have at least one friend sharing location with you |
| AES Key | 32-byte key extracted from findmylocateagent (one-time setup) |
| MQTT Broker | Any MQTT 3.1.1 broker (Mosquitto, EMQX, Home Assistant Mosquitto add-on) |
| Home Assistant | Any recent version with MQTT integration enabled |
- Download
FollowMyFriends-1.0.dmgfrom the latest release - Open the DMG and drag FollowMyFriends to your Applications folder
- Launch the app — it will prompt you to grant folder access on first run
Prerequisites: Xcode 16+, XcodeGen
# Clone the repo
git clone https://github.com/bytePatrol/FollowMyFriends.git
cd FollowMyFriends
# Generate the Xcode project
xcodegen generate
# Build
xcodebuild -project FollowMyFriends.xcodeproj \
-scheme FollowMyFriends \
-configuration Release \
buildFollowMyFriends needs a 32-byte AES key to decrypt the Find My database. Extract it once while Find My is open using findmy-key-extractor:
# Follow the instructions in that repo — it uses lldb to intercept sqlite3_key_v2()
# The result is a 32-byte binary file, e.g. LocalStorage.keySave the key file somewhere permanent on your Mac (e.g. ~/Documents/LocalStorage.key).
- Launch FollowMyFriends
- Go to Settings → Application and click "Grant FindMy Folder Access…" — select the folder:
~/Library/Group Containers/group.com.apple.findmy.findmylocateagent/Library/Application Support/ - In Settings → Key File, point to your
LocalStorage.key - In Settings → MQTT Connection, enter your broker host, port, username, and password
- Click Test Connection to verify
- Click Save, then Start Tracking on the dashboard
Ensure the MQTT integration is set up. Device trackers will appear automatically under Settings → Devices & Services → MQTT within seconds of the first publish.
Discovery topic: homeassistant/device_tracker/{slug}/config (retained)
State topic: {prefix}{slug}/state → "home" or "not_home"
Attributes topic: {prefix}{slug}/attributes (retained)
{
"latitude": 37.334900,
"longitude": -122.009020,
"gps_accuracy": 4.2,
"motion_state": "Stationary",
"location_label": "Home",
"last_update": "2026-03-03T19:30:00Z",
"location_timestamp": "2026-03-03T19:12:44Z"
}Slug format: display name → lowercase, spaces →
_,@→_at_Example:"Mom"→mom,"John Smith"→john_smith
FollowMyFriends/
├── App/ # Entry point, assets, app icon
├── Models/ # AppSettings, TrackedPerson, LocationUpdate, LogEntry
├── Services/
│ ├── FindMyDecryptor # AES-256-CBC-XOR page decryption
│ ├── WALMerger # SQLite WAL frame parsing and merge
│ ├── WALWatcher # kqueue file-system watcher for live WAL updates
│ ├── BplistParser # Binary plist location payload decoder
│ ├── DatabaseReader # Full read pipeline (DB + WAL → friends + locations)
│ ├── MQTTService # CocoaMQTT wrapper, discovery, state, attributes
│ ├── TrackingScheduler # Interval/randomisation/night-mode logic
│ ├── FindMyLauncher # Opens Find My invisibly to trigger server polls
│ ├── KeychainHelper # Secure credential storage
│ ├── LoginItemService # SMAppService launch-at-login
│ └── NotificationService # macOS user notifications
├── ViewModels/
│ └── AppState # @Observable root ViewModel, owns all services
└── Views/
├── MainWindow # NavigationSplitView shell
├── Sidebar/ # Nav + MQTT status badge
├── Dashboard/ # Person cards, tracking controls
├── Detail/ # Map + location detail panel
├── People/ # People management list
├── Settings/ # Full settings form
├── Logs/ # Live log viewer
└── Shared/ # Color tokens, reusable components
Key design decisions:
@Observable @MainActor AppStateis the single root ViewModel — no global singletons- Swift 6 strict concurrency throughout — all actor isolation verified at compile time
- WAL frames always override main DB pages (last-frame-per-page-wins merge)
- WAL read is an atomic snapshot (
Data(contentsOf:)) to prevent checkpoint races
| Package | Purpose |
|---|---|
| CocoaMQTT | MQTT 3.1.1 client (Swift Package Manager) |
All decryption, WAL parsing, and bplist decoding is implemented natively — no SQLCipher, no Python, no external crypto libraries.
MIT — see LICENSE
- findmy-key-extractor by manonstreet — for the lldb-based key extraction technique
- Apple's
findmylocateagentfor doing the heavy lifting of polling Apple's servers