Apple Flow

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.

Easiest Method: Dashboard App

For a GUI-based setup without using the terminal:

  1. Download AppleFlowApp-macOS.zip from the latest release
  2. Extract AppleFlowApp.app and move it to your Applications folder
  3. Launch the app and follow the setup wizard
  4. The app will handle daemon configuration and auto-start for you

See dashboard-app/README.md for detailed instructions.

One-Command Setup (Terminal Method)

For terminal-based setup, run:

./scripts/setup_autostart.sh

This single script does everything:

  1. ✓ Creates virtual environment
  2. ✓ Installs apple-flow and all dependencies
  3. ✓ Launches python -m apple_flow setup if .env is missing
  4. ✓ Generates launchd plist with correct paths
  5. ✓ Installs and starts both launchd services (daemon + admin API)
  6. ✓ Pins connector command paths and runs fast readiness checks
  7. ✓ Shows you the Python binary path for Full Disk Access

Your only tasks:

  • Complete the setup wizard if .env is 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.

  1. Open System SettingsPrivacy & SecurityFull Disk Access

  2. Click the '+' button

  3. 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
  4. Click 'Open' and enable the toggle

  5. 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:

  1. .env file is configured with correct apple_flow_allowed_senders
  2. Messages app is signed in to iMessage
  3. Database path is correct: /Users/<you>/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