Skip to content

Scheduler

Mia includes a built-in task scheduler that runs cron-based AI tasks automatically. Set up daily standups, weekly summaries, or any recurring prompt.

The scheduler uses node-cron for timing and persists task definitions to ~/.mia/scheduled-tasks.json. Tasks survive daemon restarts.

┌─────────────────────┐
│ scheduled-tasks │
│ .json │
└─────────┬───────────┘
│ load on startup
┌─────────────────────┐
│ node-cron jobs │◄─── cron trigger
└─────────┬───────────┘
┌─────────────────────┐
│ Plugin Dispatch │──► AI generates response
└─────────┬───────────┘
┌─────────────────────┐
│ P2P Broadcast │──► Results sent to mobile
└─────────────────────┘
Terminal window
# Standup every weekday at 9am
mia scheduler add "0 9 * * 1-5" "Write a standup report for recent commits"
# Weekly changelog every Friday at 5pm
mia scheduler add "0 17 * * 5" "Generate a changelog for this week's changes"
# Daily code review reminder at 2pm
mia scheduler add "0 14 * * *" "Check for open PRs that need review"
Terminal window
mia scheduler list

Shows all tasks with their status, last run time, and next scheduled run.

Terminal window
mia scheduler start <id> # Enable a disabled task
mia scheduler stop <id> # Disable without deleting
mia scheduler delete <id> # Permanently remove
mia scheduler test <id> # Run immediately (ignores schedule)
interface ScheduledTask {
id: string // Unique identifier
name: string // Human-readable name
cronExpression: string // Cron schedule (e.g., "0 9 * * MON")
task: string // Prompt to dispatch to AI
enabled: boolean // Whether the task is active
createdAt: number // Creation timestamp
lastRun?: number // Last execution timestamp
nextRun?: string // Human-readable next run time
nextRunMs?: number // Next run as epoch milliseconds
runCount: number // Total times executed
timeoutMs?: number // Per-task timeout override
consecutiveSkips?: number // Times skipped due to overlap
}

If a task is still running when its next cron trigger fires, the new execution is skipped rather than queued. The consecutiveSkips counter tracks how often this happens — useful for identifying tasks that need longer timeouts or less frequent schedules.

Each task has a configurable timeout:

  • Default: 5 minutes (300,000ms)
  • Global override: scheduler.defaultTimeoutMs in config
  • Per-task: Set timeoutMs on individual tasks

If a task exceeds its timeout, the dispatch is aborted.

Scheduled tasks are fully accessible from the mobile app:

  • View all tasks with status and next run time
  • Create new tasks
  • Enable/disable tasks
  • Delete tasks
  • View task results (synced via P2P)
ExpressionSchedule
* * * * *Every minute
0 * * * *Every hour
0 9 * * *Daily at 9am
0 9 * * 1-5Weekdays at 9am
0 9 * * MONEvery Monday at 9am
0 */6 * * *Every 6 hours
0 9,17 * * *9am and 5pm daily
0 0 1 * *First of each month