Daemon Mode
Last verified: 2026-05-14
Kai's daemon mode keeps the app running in the background on Android so that scheduled tasks, heartbeat checks, and email polling continue to execute even when the app is not in the foreground. On other platforms (desktop, iOS, web), daemon mode is a no-op.
Concepts
Daemon Controller
A platform-abstracted interface with start() and stop() methods. On Android, it manages an Android foreground service. On all other platforms, it does nothing.
Foreground Service
An Android service that runs with a persistent notification, preventing the system from killing the process. Kai's service uses the dataSync foreground service type and IMPORTANCE_LOW notification priority to minimize user disruption.
Service Lifecycle
- When daemon mode is enabled in settings, the foreground service is started
- The service creates a notification channel and displays a persistent "Daemon is running" notification
- The service starts the task scheduler, which owns its own process-lifetime scope
- The service returns
START_STICKY, so Android restarts it if the system kills it - When daemon mode is disabled, the service stops itself and removes the foreground notification
- On Android 12+, starting the service can silently fail with a
ForegroundServiceStartNotAllowedExceptionwhen the app isn't in the foreground; this is caught and ignored so the daemon can be retried later (e.g. on next app launch)
Auto-Start
Every time the main activity is brought to the foreground, if daemon mode is enabled in settings, the service is (re)started. This runs on app launch as well as on every subsequent return to the foreground, so the daemon recovers from situations where OEM battery managers or aggressive task killers have terminated the service while the app was in the background.
Background Work
The daemon's task scheduler polls every 60 seconds and handles four types of background work:
- Scheduled tasks — executes due tasks by sending their prompts through the AI pipeline
- Heartbeat checks — periodic self-checks during active hours (see heartbeat doc)
- Email polling — fetches new emails from configured accounts on a configurable interval
- SMS polling — checks for new incoming SMS messages on a configurable interval
Notification
- Channel: "Kai 9000 Background Service" with low importance
- Content: "Daemon is running" with a sync icon
- Tap action: Opens the app's main screen
- The notification is required by Android for foreground services and cannot be hidden
Permissions
The app declares two permissions in the Android manifest:
FOREGROUND_SERVICE— required for all foreground servicesFOREGROUND_SERVICE_DATA_SYNC— required for thedataSyncservice type
No wake locks or battery optimization exemptions are requested. The service relies on Android's standard process management with START_STICKY for restart behavior.
Settings UI
A toggle labeled "Daemon Mode" appears in the General tab of settings, only on Android. The description reads: "Keep Kai 9000 running in the background so scheduled tasks execute even when the app is not in the foreground." Toggling it starts or stops the foreground service and persists the preference. On Android 13+, turning the toggle on also requests the notification permission, since the foreground service's persistent notification cannot be displayed without it.
Key Files
| File | Purpose |
|---|---|
composeApp/src/commonMain/.../DaemonController.kt |
Platform-independent interface |
composeApp/src/androidMain/.../DaemonController.android.kt |
Android implementation, start/stop/auto-start logic |
composeApp/src/androidMain/.../DaemonService.kt |
Android foreground service, notification, task scheduler startup |
androidApp/src/main/.../MainActivity.kt |
Auto-start (and recovery) on every foreground transition via onStart |
androidApp/src/main/AndroidManifest.xml |
Service declaration and permissions |
composeApp/src/commonMain/.../data/TaskScheduler.kt |
Background poll loop started by the service |
composeApp/src/commonMain/.../data/AppSettings.kt |
Daemon enabled state persistence |
composeApp/src/commonMain/.../ui/settings/SettingsScreen.kt |
Daemon mode toggle UI |