Skip to content

macOS menu bar app that tracks your Find My friends/family locations and publishes them to Home Assistant via MQTT auto-discovery

License

Notifications You must be signed in to change notification settings

bytePatrol/FindMyFriends

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FindMyFriends

A native macOS menu bar application that bridges Apple's Find My friend locations to Home Assistant via MQTT auto-discovery.

Apple's Find My app can track shared friend and family locations, but no existing Home Assistant integration can access this data. Integrations like iCloud3 and FindMySync only support your own devices and AirTags via cache files. Since macOS 14.4+, even those cache files are encrypted.

FindMyFriends solves this by reading location data directly from the Find My app using macOS Accessibility APIs, geocoding addresses to GPS coordinates, and publishing real-time location updates to Home Assistant.

macOS Swift License


Features

Location Tracking

  • Multi-person tracking — track any number of friends/family members simultaneously
  • Sequential polling with configurable intervals (per-cycle randomization to avoid detection patterns)
  • Movement detection — only publishes updates when a person moves beyond a configurable threshold
  • Address extraction — reads full street addresses from Find My's detail panel, not just city-level data

Home Assistant Integration

  • MQTT auto-discovery — tracked people automatically appear as device_tracker entities in Home Assistant
  • Zone-aware states — configurable zones (Home, Work, etc.) determine home / not_home / zone name states
  • Full attribute publishing — latitude, longitude, GPS accuracy, street address, location label, and timestamps
  • Retained messages — location data persists across Home Assistant restarts

AI-Enhanced Location (Optional)

When Find My shows only a neighborhood name (e.g., "Northwest Los Angelas, Los Angelas, CA") instead of a street address, Nominatim geocoding can be off by 1000+ meters. The optional AI vision feature:

  • Captures a screenshot of the Find My map window
  • Sends it to the Anthropic API where the AI reads visible street names and the pin position
  • Returns GPS coordinates or an intersection — coordinates bypass geocoding entirely for maximum accuracy
  • Falls back gracefully if disabled, unconfigured, or if the API call fails
  • Supports Haiku 4.5 ($0.002/call) and Sonnet 4.5 ($0.01/call)

Other Features

  • Menu bar app — lives in your menu bar, keeps running when the window is closed
  • Sleep schedule — automatically pauses tracking during configured hours
  • Export/Import — backup and restore all settings as JSON
  • Live log viewer — real-time activity log with filtering, search, and file logging
  • Geocoding cache — minimizes Nominatim API calls with in-memory and on-disk caching

Screenshots

Main Window

The main window shows tracked people on the left with tracking controls and a live log on the right.


Requirements

  • macOS 13.0 (Ventura) or later
  • Apple's Find My app with at least one shared friend/family contact
  • Home Assistant with an MQTT broker (Mosquitto, EMQX, etc.)
  • Anthropic API key (optional, only for AI-enhanced location feature)

Installation

Download the Pre-Built App

  1. Download FindMyTracker.app.zip from the latest release
  2. Unzip and move FindMyTracker.app to your Applications folder
  3. Important: The app is not code-signed or notarized. On first launch:
    • Right-click the app and select Open (do not double-click)
    • Click Open in the Gatekeeper dialog
    • Alternatively, go to System Settings > Privacy & Security and click Open Anyway after the first blocked attempt

Build from Source

git clone https://github.com/bytePatrol/FindMyFriends.git
cd FindMyFriends
./build-app.sh
open FindMyTracker.app

Requires Xcode or Xcode Command Line Tools (for the Swift toolchain).


Permissions

FindMyFriends requires specific macOS permissions to function. The app will guide you through granting each one on first launch.

Required Permissions

Permission Why It's Needed How to Grant
Accessibility Read UI elements from the Find My app (sidebar entries, address labels) System Settings > Privacy & Security > Accessibility > Enable FindMyTracker
Automation (Find My) Send AppleScript commands to Find My (click sidebar entries, open detail panels) Granted automatically on first use via system prompt

Optional Permission

Permission Why It's Needed How to Grant
Screen Recording Capture the Find My map window for AI-enhanced location (only if AI feature is enabled) System Settings > Privacy & Security > Screen Recording > Enable FindMyTracker

Note: After granting Accessibility or Screen Recording permissions, you may need to restart the app for changes to take effect.


Setup

1. Grant Permissions

On first launch, the app displays a permissions screen. Click the buttons to open System Settings and grant each permission. The app checks permissions in real time and proceeds automatically once both are granted.

2. Configure MQTT

Click the network icon in the bottom toolbar to open MQTT settings:

  • Broker — hostname or IP of your MQTT broker
  • Port — default 1883 (or 8883 for TLS)
  • Username / Password — your MQTT credentials
  • TLS — enable if your broker requires it
  • Topic Prefix — default homeassistant (matches HA's MQTT discovery prefix)

Use Test Connection to verify connectivity before saving.

3. Discover People

Click Scan People to discover all contacts visible in Find My's People tab. The app reads the sidebar and lists everyone it finds. Use the checkboxes to select who you want to track.

4. Configure Zones

Click the map pin icon to add known locations (zones). Each zone has a name, GPS coordinates, and radius. When a tracked person is within a zone's radius, their Home Assistant state reflects the zone name instead of not_home.

5. Start Tracking

Click Start to begin. The app will:

  1. Connect to your MQTT broker
  2. Publish auto-discovery configs for each tracked person
  3. Poll each person sequentially, extracting their location from Find My
  4. Geocode addresses to GPS coordinates
  5. Publish state and attribute updates to Home Assistant

6. AI-Enhanced Location (Optional)

Click the brain icon to configure AI vision:

  1. Enable the feature
  2. Enter your Anthropic API key
  3. Select a model (Haiku 4.5 recommended for cost)
  4. Grant Screen Recording permission if prompted
  5. Use Test AI Vision to verify it's working

The AI feature only activates when Find My shows a neighborhood name instead of a street address. Street addresses are geocoded normally without using the AI.


Home Assistant

Once tracking starts, each person appears as a device_tracker entity:

# Entity: device_tracker.findmy_john
state: home          # or "not_home", or a zone name
attributes:
  latitude: 33.8752
  longitude: -117.5664
  gps_accuracy: 50
  source_type: gps
  address: "251 E 6th St, Los Angeles, CA 90014"
  location_label: "Home"
  time_ago: "1 minute ago"
  friendly_name: "FindMy John"

Use these entities in automations, presence detection, or the Home Assistant map.


Project Structure

FindMyFriends/
├── Package.swift                          # SPM manifest (CocoaMQTT dependency)
├── build-app.sh                           # Build script → .app bundle
├── Sources/FindMyTracker/
│   ├── App/
│   │   ├── FindMyTrackerApp.swift         # @main entry, menu bar setup
│   │   ├── AppDelegate.swift              # NSApplicationDelegate lifecycle
│   │   └── ServiceContainer.swift         # Dependency injection container
│   ├── Models/
│   │   ├── AppState.swift                 # Observable app state, persistence
│   │   ├── TrackedPerson.swift            # Person model with location data
│   │   ├── KnownLocation.swift            # Zone model (name, coords, radius)
│   │   ├── MQTTConfig.swift               # MQTT connection configuration
│   │   └── LogEntry.swift                 # Log entry model with levels
│   ├── Services/
│   │   ├── FindMyService.swift            # AppleScript/Accessibility extraction
│   │   ├── TrackingEngine.swift           # Main polling loop orchestrator
│   │   ├── GeocodingService.swift         # Nominatim geocoding with cache
│   │   ├── MQTTService.swift              # CocoaMQTT wrapper, auto-discovery
│   │   ├── VisionLocationService.swift    # AI screenshot analysis (optional)
│   │   └── PermissionsService.swift       # macOS permission checks
│   ├── Views/
│   │   ├── MainWindowView.swift           # Split view layout
│   │   ├── PeopleListView.swift           # Sidebar with person list
│   │   ├── TrackingControlsView.swift     # Start/Pause/Stop controls
│   │   ├── LogView.swift                  # Live log with filtering
│   │   ├── PermissionsView.swift          # First-launch permission guide
│   │   ├── MQTTSettingsView.swift         # MQTT configuration sheet
│   │   ├── ZonesSettingsView.swift        # Zone editor sheet
│   │   ├── SleepSettingsView.swift        # Sleep schedule sheet
│   │   ├── AISettingsView.swift           # AI vision configuration sheet
│   │   └── MenuBarView.swift              # Menu bar dropdown
│   ├── Utilities/
│   │   ├── AppLogger.swift                # Thread-safe logger (UI + file)
│   │   ├── Haversine.swift                # GPS distance calculation
│   │   └── ExportImport.swift             # JSON settings export/import
│   └── Resources/
│       ├── Info.plist                     # App metadata and usage descriptions
│       └── FindMyTracker.entitlements     # Non-sandboxed + AppleEvents

How It Works

FindMyFriends uses a three-step extraction method via macOS Accessibility APIs:

  1. Click the person's name in the Find My sidebar (clicks the static text element directly)
  2. Click "More Info" on the map callout to open the detail panel
  3. Read the detail panel labels via AXIdentifier attributes (PrimaryLabel, SecondaryLabel, SecondaryTitleLabel, TertiaryLabel)

This yields the full street address (e.g., "1436 S Lombard Dr, Fullerton, CA 92832") rather than just city-level data. The address is then geocoded via OpenStreetMap's Nominatim API with a multi-strategy fallback system.

Why Accessibility APIs? Friend/family locations are only available in Find My's UI. They are not stored in any cache file, plist, or API endpoint accessible to third-party apps. Screen scraping via Accessibility is the only viable approach.


Configuration Files

All data is stored in ~/.config/findmy-tracker/:

File Purpose
tracker.log Application log file
geocode_cache.json Geocoding results cache (5-minute TTL)

App settings (tracked people, MQTT config, zones, polling intervals) are stored in macOS UserDefaults.


Troubleshooting

Issue Solution
App blocked by Gatekeeper Right-click > Open, or System Settings > Privacy & Security > Open Anyway
"No people discovered" Ensure Find My is open with the People tab selected before scanning
Accessibility permission not working Restart the app after granting permission in System Settings
MQTT connection fails Verify broker address, port, and credentials; use Test Connection
Geocoding returns wrong location This happens with neighborhood-level addresses; enable AI-enhanced location for better accuracy
AI Vision screenshot fails Grant Screen Recording permission and restart the app
Find My shows "No location found" The contact has stopped sharing their location or their device is offline

Privacy & Security

  • No data leaves your Mac except MQTT messages to your broker and Nominatim geocoding requests
  • API keys and passwords are stored locally in macOS UserDefaults, never transmitted elsewhere
  • AI screenshots are sent to the Anthropic API only when the feature is explicitly enabled and configured
  • No telemetry, analytics, or tracking of any kind
  • The app is not sandboxed (required for Accessibility API access)

License

MIT License. See LICENSE for details.

About

macOS menu bar app that tracks your Find My friends/family locations and publishes them to Home Assistant via MQTT auto-discovery

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published