skills/within-7/aiter/scheduling

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

  1. Read pending tasks: Read .aiter/memory/tasks.md → find items with due ≤ now
  2. Check orchestrations: Read .aiter/memory/orchestration.md → check multi-project progress
  3. Check cron logs: aiter cron list → look for failed jobs
  4. Check channels: aiter message channels → verify channel connectivity
  5. Process due tasks:
    • Simple task → execute directly
    • Complex task → create orchestration plan or notify user
    • Recurring task → execute and compute next occurrence
  6. Update memory: Write results to tasks.md and journal.md
  7. 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/aiter
First Seen
12 days ago
Installed on
amp1
cline1
openclaw1
opencode1
cursor1
kimi-cli1