Skill: ivangdavila/schedule (version 1.0.2)

--- name: Schedule slug: schedule version: 1.0.2 description: Program recurring or one-time tasks. User defines what to do, skill handles when. changelog: Clarified user-driven execution model, removed assumed access patterns metadata: {"clawdbot":{"emoji":"📅","requires":{"bins":[]},"os":["linux","darwin","win32"]}} --- ## Data Storage ``` ~/schedule/ ├── jobs.json # Job definitions ├── preferences.json # Timezone, preferred times └── history/ # Execution logs └── YYYY-MM.jsonl ``` Create on first use: `mkdir -p ~/schedule/history` ## Scope This skill: - ✅ Stores scheduled job definitions in ~/schedule/ - ✅ Triggers jobs at specified times - ✅ Learns timezone and time preferences from user **Execution model:** - User explicitly defines WHAT the job does - User grants any permissions needed for the job - Skill only handles WHEN, not WHAT This skill does NOT: - ❌ Assume access to any external service - ❌ Modify system crontab or launchd - ❌ Execute jobs without user-defined instructions ## Quick Reference | Topic | File | |-------|------| | Cron expression syntax | `patterns.md` | | Common mistakes | `traps.md` | | Job format | `jobs.md` | ## Core Rules ### 1. User Defines Everything When user requests a scheduled task: 1. **WHAT**: User specifies the action (may require other skills/permissions) 2. **WHEN**: This skill handles timing 3. **HOW**: User grants any needed access explicitly Example flow: ``` User: "Every morning, summarize my emails" Agent: "I'll schedule this for 8am. This will need email access — do you want me to use the mail skill for this?" User: "Yes" → Job stored with explicit reference to mail skill ``` ### 2. Simple Requests | Request | Action | |---------|--------| | "Remind me to X at Y" | Store job, confirm | | "Every morning do X" | Ask time, store job | | "Cancel X" | Remove from jobs.json | ### 3. Confirmation Format ``` ✅ [what user requested] 📅 [when] ([timezone]) 🔧 [permissions/skills needed, if any] 🆔 [id] ``` ### 4. Job Persistence In ~/schedule/jobs.json: ```json { "daily_review": { "cron": "0 9 * * 1-5", "task": "User-defined task description", "requires": ["mail"], "created": "2024-03-15", "timezone": "Europe/Madrid" } } ``` The `requires` field explicitly lists any skills/access the job needs. ### 5. Execution When scheduled time arrives: - Agent executes the user-defined task - Uses only permissions user explicitly granted - Logs result to history/ ### 6. Preferences After first job, store in preferences.json: - Timezone - Preferred "morning" / "evening" times - Default notification style

path: jobs.md
content: # Job Storage Format

Jobs are stored in ~/schedule/jobs.json. Each job captures what the USER requested.

## Format

```json
{
  "job_id": {
    "task": "User's exact request",
    "cron": "cron expression or ISO timestamp",
    "timezone": "Europe/Madrid",
    "requires": ["skill1", "skill2"],
    "created": "2024-03-15",
    "status": "active"
  }
}
```

## Fields

| Field | Required | Description |
|-------|----------|-------------|
| task | Yes | What user asked to do (their words) |
| cron | Yes | When to run (cron expr or ISO for one-shot) |
| timezone | Yes | User's timezone |
| requires | No | Skills/permissions this job needs |
| created | Yes | When job was created |
| status | Yes | active, paused, or completed |

## Example Jobs

```json
{
  "morning_reminder": {
    "task": "Remind me to check calendar",
    "cron": "0 8 * * *",
    "timezone": "Europe/Madrid",
    "requires": [],
    "created": "2024-03-15",
    "status": "active"
  },
  "weekly_summary": {
    "task": "Summarize my week and send to my email",
    "cron": "0 18 * * 5",
    "timezone": "Europe/Madrid",
    "requires": ["mail"],
    "created": "2024-03-15",
    "status": "active"
  }
}
```

## Notes

- `requires` is populated when user explicitly grants access
- Empty `requires` = notification/reminder only
- Jobs with `requires` will use those skills when executing


path: patterns.md
content: # Cron Patterns Reference

Consult when building schedules. Always include timezone.

## Quick Reference

| Intent | Cron | Notes |
|--------|------|-------|
| Every day 9am | `0 9 * * *` | |
| Weekdays 9am | `0 9 * * 1-5` | Mon-Fri |
| Weekends 10am | `0 10 * * 0,6` | Sat-Sun |
| Monday 9am | `0 9 * * 1` | Weekly |
| First of month | `0 9 1 * *` | |
| Last Friday | `0 17 * * 5L` | Non-standard |
| Every 2 hours | `0 */2 * * *` | On the hour |
| Every 30 min | `*/30 * * * *` | |

## Interval vs Cron

| Use interval (`every`) when | Use cron when |
|----------------------------|---------------|
| Simple repetition (every 2h) | Specific times (9am) |
| Duration-based (every 30min) | Day-based (weekdays) |
| No clock alignment needed | Clock alignment needed |

## Format

```
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sun-Sat)
│ │ │ │ │
* * * * *
```

## Examples with Timezone

```json
{ "kind": "cron", "expr": "0 9 * * 1-5", "tz": "Europe/Madrid" }
{ "kind": "every", "everyMs": 3600000 }  // 1 hour
{ "kind": "at", "at": "2026-02-15T09:00:00+01:00" }  // one-shot
```

## Common Mistakes

- `0 9 * * *` without tz → runs at 9 UTC, not local
- `* 9 * * *` → runs every MINUTE of 9am hour (60 times!)
- `0 0 31 * *` → skips months without 31 days


path: traps.md
content: # Scheduling Traps

Check before creating any job. Prevent common failures.

## Timezone Hell

| Trap | Fix |
|------|-----|
| ISO without TZ = UTC | Always append zone: `2026-02-15T09:00:00+01:00` |
| "Tomorrow" ambiguous | Confirm exact date: "Tuesday Feb 18" |
| DST shift (March/October) | Jobs at 02:00-03:00 may skip or double |
| User travels | Ask if schedule should follow them or stay fixed |

## Persistence

| Trap | Fix |
|------|-----|
| Stored in memory only | Write to ~/schedule/jobs.json |
| Session reset loses jobs | Always persist to file, never rely on context |
| "I'll remember" | You won't. Save to jobs.json. |

## Confirmation

| Trap | Fix |
|------|-----|
| "Reminder set" | Show WHEN: date, time, timezone |
| "Tomorrow at 9" | Show: "Tuesday Feb 18 at 09:00 (Europe/Madrid)" |
| No ID | Always give ID for cancel/edit |
| Generic message | Include WHAT: "Reminder: call dentist" |

## Execution

| Trap | Fix |
|------|-----|
| Silent failure | Always notify if job fails |
| Duplicate jobs | Check existing before creating |
| Overlapping runs | Use locks for long-running jobs |
| Never ends | Set max retries, notify on repeated failure |

## Recurrence

| Trap | Fix |
|------|-----|
| "Every day" forever | Ask about end date or review period |
| Holiday runs | Ask if holidays should skip |
| Weekend noise | Clarify: include weekends? |

## Before Creating

Checklist:
```
□ Timezone explicit?
□ Exact date/time confirmed?
□ Saved to ~/schedule/jobs.json?
□ Unique ID assigned?
□ Confirmation includes WHAT + WHEN + ID?
```


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)