scheduling
SKILL.md
Scheduling & Heartbeat Automation
Cron Job Management
Create a cron job
aiter cron add \
--name "Job Name" \
--projectId project-123 \
--command "echo 'Hello from cron'" \
--expression "*/30 * * * *" \
--notify true \
--notifyChannelId channel-abc
Parameters:
| Param | Required | Description |
|---|---|---|
name |
Yes | Human-readable job name |
projectId |
Yes | Project whose terminal runs the command |
command |
Yes | Shell command to execute |
expression |
Yes | Cron expression (see below) |
notify |
No | Send notification when job runs |
notifyChannelId |
No | IM channel for notifications |
Cron Expression Reference
┌─────── minute (0-59)
│ ┌───── hour (0-23)
│ │ ┌─── day of month (1-31)
│ │ │ ┌─ month (1-12)
│ │ │ │ ┌ day of week (0-7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *
| Expression | Meaning |
|---|---|
*/5 * * * * |
Every 5 minutes |
*/30 * * * * |
Every 30 minutes |
0 * * * * |
Every hour |
0 9 * * * |
Daily at 9:00 AM |
0 9 * * MON |
Every Monday at 9:00 AM |
0 9 * * MON-FRI |
Weekdays at 9:00 AM |
0 2 * * * |
Daily at 2:00 AM (off-hours) |
0 9,18 * * * |
At 9:00 AM and 6:00 PM |
0 0 1 * * |
First day of each month |
List, pause, resume, trigger
# List all cron jobs
aiter cron list
# List jobs for a specific project
aiter cron list --projectId project-123
# Pause a job (keeps config, stops execution)
aiter cron pause --id cron-789
# Resume a paused job
aiter cron resume --id cron-789
# Manually trigger a job right now
aiter cron trigger --id cron-789
# View execution logs
aiter cron logs --id cron-789 --lines 20
# Remove a job permanently
aiter cron remove --id cron-789
Heartbeat Pattern
The heartbeat is the core mechanism that makes the agent proactive. A cron job periodically triggers the AI CLI to check for pending tasks.
How it works
1. Cron fires (e.g., every 30 min)
↓
2. Cron executes command in project terminal
Command: echo "[HEARTBEAT] Check pending tasks at $(date)"
↓
3. Output appears in terminal
↓
4. If AI CLI is running in that terminal:
→ PostToolUse hook detects [HEARTBEAT] marker
→ Hook triggers heartbeat-scheduler agent
→ Agent reads tasks.md, processes due items
→ Agent updates memory, sends notifications
↓
5. If AI CLI is NOT running:
→ Cron --notify flag sends OS notification
→ User sees "Heartbeat: pending tasks" notification
→ User can open terminal to process tasks
Setting up the heartbeat
# Get the current project ID
PROJECT_ID=$(aiter project list | jq -r '.data[0].id')
# Create the heartbeat cron job
aiter cron add \
--name "Agent Heartbeat" \
--projectId $PROJECT_ID \
--command "echo '[HEARTBEAT] Check pending tasks at $(date +%Y-%m-%dT%H:%M:%S)'" \
--expression "*/30 * * * *" \
--notify true
# Verify it was created
aiter cron list | jq '.data[] | select(.name == "Agent Heartbeat")'
What the heartbeat agent does when triggered
- Read pending tasks:
Read .aiter/memory/tasks.md→ find items withdue≤ now - Check orchestrations:
Read .aiter/memory/orchestration.md→ check multi-project progress - Check cron logs:
aiter cron list→ look for failed jobs - Check channels:
aiter message channels→ verify channel connectivity - Process due tasks:
- Simple task → execute directly
- Complex task → create orchestration plan or notify user
- Recurring task → execute and compute next occurrence
- Update memory: Write results to tasks.md and journal.md
- Notify: If any actions taken → send summary notification
Heartbeat frequency recommendations
| Use Case | Expression | Frequency |
|---|---|---|
| Light monitoring | 0 * * * * |
Every hour |
| Standard assistant | */30 * * * * |
Every 30 min |
| Active development | */15 * * * * |
Every 15 min |
| Critical monitoring | */5 * * * * |
Every 5 min |
| Business hours only | */30 9-18 * * MON-FRI |
Every 30 min, 9-6 weekdays |
Scheduled Task Patterns
One-time future task
Create a task in memory with a due date. The heartbeat will pick it up:
### [NORMAL] Deploy v2.1 to staging
- due: 2024-01-15 14:00
- assigned: heartbeat
- created: 2024-01-14
- tags: deployment
- action: Run `npm run deploy:staging` in project ecommerce-backend
Recurring task with cron
Create both a cron job and a memory entry:
# Create the cron job
CRON_RESULT=$(aiter cron add \
--name "Weekly Report" \
--projectId $PROJECT_ID \
--command "echo '[HEARTBEAT] Generate weekly report'" \
--expression "0 9 * * MON")
CRON_ID=$(echo $CRON_RESULT | jq -r '.data.id')
Then add to tasks.md:
### [NORMAL] Generate weekly report
- due: 2024-01-15 09:00 (recurring: 0 9 * * MON)
- assigned: heartbeat
- cronJobId: cron-abc123
- tags: reporting, weekly
- action: Gather git log, test results, and metrics. Format as report and send to Slack.
Conditional scheduled task
A task that only runs if a condition is met:
### [NORMAL] Check and merge approved PRs
- due: 2024-01-15 12:00 (recurring: 0 12 * * MON-FRI)
- assigned: heartbeat
- tags: git, automation
- condition: Only if there are approved PRs waiting
- action: Run `gh pr list --state open --json reviews` and merge any with 2+ approvals
Managing Scheduled Tasks
List active schedules
Combine cron jobs and memory tasks for a full picture:
# Cron jobs
aiter cron list | jq '.data[] | {name, expression, enabled, lastRun}'
# Memory tasks with due dates
# Use Grep to search tasks.md for "due:" entries
Cancel a scheduled task
# Remove the cron job
aiter cron remove --id cron-789
# Update tasks.md — remove or mark as cancelled
# Use Edit tool to update the task entry
Modify schedule frequency
# Remove old job and create new one with different expression
aiter cron remove --id cron-789
aiter cron add --name "Same Job" --projectId $PID --command "..." --expression "0 * * * *"
Weekly Installs
1
Repository
within-7/aiterFirst Seen
12 days ago
Security Audits
Installed on
amp1
cline1
openclaw1
opencode1
cursor1
kimi-cli1