The scheduler automatically executes:
- due calendar notifications
- one-time and recurring direct messages
- due/overdue task reminders (for tasks with
dueDate) - recurring app sync jobs for analytics, finance, and ads
- due scheduled social posts
- due scheduled CMS publishes
termlings schedulerChecks for due work once and exits.
termlings scheduler --daemonRuns continuously in the background, checking every 60 seconds for due work.
- Checks calendar events - Reads
.termlings/store/calendar/calendar.json - Checks scheduled messages - Reads
.termlings/store/message-schedules/schedules.json - Checks task due dates - Reads
.termlings/store/tasks/tasks.jsonand tracks reminder state in.termlings/store/tasks/scheduler-state.json - Checks app schedules - Reads
.termlings/store/app-schedules/schedules.json - Executes due items - Sends event notifications, scheduled DMs, task reminders, app sync jobs, social publishes, and CMS publishes
- Marks completed work - Calendar and one-time schedules disable themselves after execution
When an event is due, agents receive a message:
New event: "Daily Standup"
Start: 2026-03-02 09:00 UTC
End: 2026-03-02 09:30 UTC
They see this in:
- Web UI message stream
termlings list-agents(recent activity)
Scheduled messages are useful for delayed DMs, recurring check-ins, and lightweight team automation.
In the TUI, type:
/schedule
You can also prefill it directly:
/schedule @Jordan Check in on blockers
The /schedule form supports:
Totarget selectionMessageRecurrence: one-time (nonein the UI),hourly,daily,weeklyDatefor one-time schedulesWeekdayfor weekly schedules- segmented
Timeediting - searchable
Timezoneselection
When due, the scheduler sends the DM from Scheduler to the target thread. Offline agent targets are queued and delivered when that agent comes back online.
If you launch the workspace with termlings, the scheduler daemon is auto-started for you.
Add to your shell initialization file (~/.bashrc, ~/.zshrc, etc.):
# Start scheduler daemon on shell launch
termlings scheduler --daemon &Or run once at project startup:
# Start scheduler for this session
termlings scheduler --daemon-
Owner creates calendar events
termlings calendar create tl-alice tl-bob "Daily Standup" "2026-03-02T09:00:00Z" "2026-03-02T09:30:00Z" daily
-
Scheduler runs (automatically or daemon)
- Checks every 60 seconds
- Sends notifications when events start
- Sends scheduled DMs when their run time arrives
-
Agents receive notifications
- See in workspace TUI
- Can check calendar for details
termlings calendar show <event-id>
-
Scheduled messages are checked
- Scheduled DMs can target
agent:<slug>,human:default, or@everyonefrom the TUI - Hourly, daily, and weekly schedules are re-queued automatically after delivery
- One-time schedules disable themselves after delivery
- Scheduled DMs can target
-
Task reminders are checked
- For tasks with
dueDate, scheduler sends: - One upcoming reminder in the 24h pre-due window
- One due-now reminder when due time is reached
- Overdue reminders every 24h while task remains incomplete
- Target is task assignee (
agent:<slug>) when assigned, otherwise task creator
- For tasks with
-
App sync schedules are checked
analytics,finance, andadscan create recurring sync jobs through the shared scheduler- Schedules are stored in
.termlings/store/app-schedules/schedules.json - Scheduler executes the due sync and appends shared activity entries for success/failure
-
Scheduled social posts are checked
socialcreates one-time queued posts under.termlings/store/social/posts/*.json- When due, the scheduler publishes them through the configured platform webhook
- If the post has a linked calendar event, the scheduler disables it after the publish attempt
-
Scheduled CMS entries are checked
cmscreates scheduled entries under.termlings/store/cms/entries/<collection>/*.json- When due, the scheduler publishes markdown and JSON outputs under
.termlings/store/cms/publish/<collection>/ - Publish success/failure is recorded in CMS history and the shared app activity feed
Use the app-specific schedule subcommands to register recurring sync jobs:
printf '%s\n' '{"action":"sync","recurrence":"daily","time":"07:00","last":"30d"}' \
| termlings analytics schedule create --stdin-json --json
printf '%s\n' '{"action":"sync","recurrence":"daily","time":"08:00","last":"30d"}' \
| termlings finance schedule create --stdin-json --json
printf '%s\n' '{"action":"sync","recurrence":"weekly","time":"09:00","weekday":"mon","last":"7d"}' \
| termlings ads schedule create --stdin-json --jsonList or remove schedules:
termlings analytics schedule list --json
termlings finance schedule remove --params '{"id":"finance_schedule_abc123"}' --jsonCurrently the scheduler checks every 60 seconds (hard-coded). To change, edit the scheduler code:
src/commands/scheduler.ts
✅ DO:
- Run scheduler daemon during work sessions
- Use recurring events for regular meetings
- Use
/schedulefor one-time follow-ups and recurring operator-driven check-ins - Test calendar creation before relying on scheduler
- Use
dueDateon tasks that need time-based reminders
❌ DON'T:
- Create event times in the past (won't trigger)
- Rely on exact timing (60-second granularity)
- Leave old events enabled if no longer needed
"Scheduler not sending notifications"
-
Check scheduler is running:
ps aux | grep scheduler -
Verify calendar events exist:
termlings calendar list
-
Verify scheduled DMs exist:
cat .termlings/store/message-schedules/schedules.json
-
Check event times are in the future:
termlings calendar show <event-id>
-
Manually trigger check:
termlings scheduler # Runs once -
Verify due task metadata:
- Task must include a valid
dueDatetimestamp - Task status must not be
completed
- Task must include a valid
"Getting duplicate notifications"
This shouldn't happen - notifications are tracked. If it does, check that .termlings/store/calendar/calendar.json hasn't been corrupted.
- CALENDAR.md - Calendar event management
- MESSAGING.md - How notifications are sent