Configure Apple Flow launchd services for auto-start.
Auto-Start Setup
This guide explains how to configure apple-flow to start automatically when your Mac boots.
One-Command Setup (Recommended)
Just run:
./scripts/setup_autostart.sh
This single script does everything:
- ✓ Creates virtual environment
- ✓ Installs apple-flow and all dependencies
- ✓ Launches
python -m apple_flow setupif.envis missing - ✓ Generates launchd plist with correct paths
- ✓ Installs and starts both launchd services (daemon + admin API)
- ✓ Pins connector command paths and runs fast readiness checks
- ✓ Shows you the Python binary path for Full Disk Access
Your only tasks:
- Complete the setup wizard if
.envis missing - Grant Full Disk Access (one-time macOS security requirement)
Advanced: Install-Only Script
If you've already set up the project (venv, dependencies, .env), use:
./scripts/install_autostart.sh
This only configures and installs the auto-start services.
Grant Full Disk Access
This step is REQUIRED - the daemon needs access to read the Messages database.
-
Open System Settings → Privacy & Security → Full Disk Access
-
Click the '+' button
-
Press Cmd+Shift+G and paste the Python binary path shown by the installer
- Example:
/opt/homebrew/Cellar/python@3.14/3.14.3_1/Frameworks/Python.framework/Versions/3.14/bin/python3.14
- Example:
-
Click 'Open' and enable the toggle
-
Restart both services:
launchctl stop local.apple-flow launchctl start local.apple-flow launchctl stop local.apple-flow-admin launchctl start local.apple-flow-admin
Verify It's Running
# Check service status (should show a PID number, not -)
launchctl list | grep apple-flow
# Watch logs in real-time
tail -f logs/apple-flow.log
# Check for errors
tail -f logs/apple-flow.err.log
Managing the Service
# Start manually
launchctl start local.apple-flow
launchctl start local.apple-flow-admin
# Stop manually
launchctl stop local.apple-flow
launchctl stop local.apple-flow-admin
# Check status
launchctl list | grep apple-flow
# Uninstall auto-start
./scripts/uninstall_autostart.sh
How It Works
The installation script:
- Follows symlinks to find the actual Python binary (not symlinks)
- Detects your Python version and site-packages location
- Generates a plist file with your specific paths
- Configures environment variables (PYTHONPATH, VIRTUAL_ENV, PATH including
~/.local/bin)
This means the setup is portable - it works regardless of:
- Your username or project location
- Your Python version (3.10, 3.11, 3.14, etc.)
- Homebrew Python updates that change version numbers
Troubleshooting
Service shows exit code (not running)
launchctl list | grep apple-flow
# Output: - 1 local.apple-flow (- means not running, 1 is exit code)
Check the error log:
tail -30 logs/apple-flow.err.log
Common issues:
- "unable to open database file" → Grant Full Disk Access to Python binary
- "ModuleNotFoundError" → Reinstall dependencies:
pip install -e .[dev] - "Operation not permitted" → Python binary doesn't have Full Disk Access
After Python update, service stops working
When Homebrew updates Python, the binary path changes. Re-run the installer:
./scripts/install_autostart.sh
Then re-grant Full Disk Access to the new Python binary path.
Service runs but doesn't respond to messages
Check that:
.envfile is configured with correctapple_flow_allowed_senders- Messages app is signed in to iMessage
- Database path is correct:
~/Library/Messages/chat.db
Security Notes
- Only the specific Python binary gets Full Disk Access
- The daemon runs as your user (not root)
- It can only access paths in
apple_flow_allowed_workspaces - Mutating operations require explicit approval via the approval workflow