Generates a warm, compact daily briefing with weather, calendar, reminders, birthdays, and important emails for cron or chat delivery.
Generates a compact, warm daily message suitable for cron delivery (stdout/chat reply). Always succeeds even with minimal context.
This skill uses the System Skill pattern for execution on macOS. The agent must:
curl for weather).Quick reference:
# Invoke data gatherer (waits for completion)
"{baseDir}/skills/daily-briefing/bin/run_daily_briefing.sh"
# Read output
cat /tmp/daily_briefing_data.json
CRITICAL: Output only the briefing text. No prefaces, no explanations, no "Done", no file paths, no tool output, no markdown code fences around the briefing.
Line 1 must begin exactly with the time-appropriate greeting:
Good {time_of_day} - Today is {Weekday}, {Month} {D}, {YYYY}. {Skies sentence}.
🎉 Happy Birthday! Today is {Weekday}, {Month} {D}, {YYYY}. {Skies sentence}.
| Time Range | Greeting |
|---|---|
| 05:00–11:59 | Good morning |
| 12:00–16:59 | Good afternoon |
| 17:00–21:59 | Good evening |
| 22:00–04:59 | Good night |
| Unknown | Good morning (default) |
If weather is usable:
{Conditions} skies, around {TEMP}°{time_clause}{low_clause}{precip_clause}.
, with a low around {LOW}°, and a {CHANCE}% chance of {rain/snow/precipitation}If weather is not usable: Use exact fallback:
I can't access weather right now.
{Line 1: Greeting with skies sentence}
{Birthdays section - only if any today or upcoming}
{Calendar events section - only if any}
{Reminders section - only if any}
{Important emails section - only if enabled and any}
{Anchors - only if real priorities from context}
{Closing line - always required}
If interactive AND missing critical info (location/timezone/units):
emails.enabled in config; note iCloud Mail requires an app-specific password (emails.icloudPassword).If non-interactive (cron/automation):
"{baseDir}/skills/daily-briefing/bin/run_daily_briefing.sh"
scripts/daily_briefing_orchestrator.sh.After the app completes, read:
/tmp/daily_briefing_data.json
JSON structure:
{
"generated_at": "ISO timestamp",
"system": {
"timezone": "America/New_York",
"local_time": "2024-02-03T08:30:00",
"hour": 8
},
"config": {
"location": "New York, NY",
"units": "C",
"birthdays_enabled": true,
"birthdays_lookahead": 14,
"calendar_google_enabled": true,
"calendar_icloud_enabled": true,
"calendar_lookahead": 0,
"reminders_enabled": true,
"reminders_due_filter": "today",
"reminders_include_past_due": true,
"emails_enabled": false,
"emails_limit": 10,
"emails_sort_newest": true,
"emails_starred_first": true,
"emails_unread_only": true
},
"birthdays": {
"available": true,
"user_birthday_today": false,
"data": [
{"name": "Jane Doe", "date": "2024-02-03", "days_until": 0},
{"name": "John Smith", "date": "2024-02-05", "days_until": 2}
]
},
"calendar": {
"available": true,
"data": [
{"title": "Team standup", "start": "09:00", "end": "09:30", "all_day": false, "date": "2024-02-03", "source": "google"},
{"title": "Doctor appointment", "start": null, "end": null, "all_day": true, "date": "2024-02-03", "source": "icloud"}
]
},
"reminders": {
"available": true,
"data": [
{"title": "Pick up prescription", "due": "2024-02-03"}
]
},
"emails": {
"available": true,
"data": [
{"id": "abc123", "from": "Amazon", "from_email": "[email protected]", "subject": "Your order has shipped", "preview": "Your package is on its way...", "starred": false, "unread": true, "date": "2024-02-03T07:30:00Z", "source": "gmail"},
{"id": "def456", "from": "Chase", "from_email": "[email protected]", "subject": "Payment received", "preview": "We received your payment of...", "starred": true, "unread": true, "date": "2024-02-03T06:15:00Z", "source": "icloud"}
]
},
"contacts": {
"available": true,
"data": [
{"name": "Jane Doe", "email": "[email protected]"},
{"name": "John Smith", "email": "[email protected]"}
]
}
}
The agent must fetch weather directly using curl (not via orchestrator):
curl -fsSL --max-time 12 "https://wttr.in/{ENCODED_LOCATION}?format=j1"
config.location from gathered data; if empty/null, weather is unavailable.Parse from JSON response:
current_condition[0].weatherDesc[0].valuecurrent_condition[0].temp_Ccurrent_condition[0].temp_Fweather[0].maxtempCweather[0].maxtempFweather[0].mintempCweather[0].mintempFweather[0].hourly[*].chanceofrain (as integers)Units: Use config.units ("C" or "F"). Default to Celsius if unknown.
CRITICAL: Do NOT output raw curl/tool output. Do NOT use wttr.in one-line formats.
Only if config.emails_enabled is true and emails.available is true.
For each email in emails.data, use the agent's own semantic analysis to determine importance.
Important Email Criteria (any match qualifies):
Exclusions: The following are never important, even if matching other criteria:
Failure behavior: If semantic analysis fails, silently omit the entire email section.
Apply filters and sorting:
emails_unread_only if trueemails_starred_first is true, starred emails firstemails_sort_newestemails_limitUsing all gathered and processed data, compose the briefing text following the Output Contract.
Section Formats:
Birthdays:
🎂 **Birthdays:**
• Today: Name
• Feb 5: Name
Calendar Events:
📅 **Today's schedule:**
• All-day: Event title
• 9:00 AM: Event title
Reminders:
✅ **Reminders:**
• Pick up prescription
Important Emails:
📧 **Emails needing attention:**
• Amazon: Your order has shipped
• Chase: Payment received
• Sender: Subject (truncated if needed)Anchors:
Closing Line:
quote field from the gathered JSON data.Return only the briefing text. Nothing else.
Configuration is read from ~/.openclaw/openclaw.json at path skills.entries.daily-briefing.config:
{
"skills": {
"entries": {
"daily-briefing": {
"config": {
"location": "New York, NY",
"timezone": "America/New_York",
"units": "C",
"birthdays": {
"enabled": true,
"lookahead": 14,
"sources": ["contacts", "google"]
},
"calendar": {
"enabled": true,
"lookahead": 0,
"sources": ["google", "icloud"]
},
"reminders": {
"enabled": true
},
"emails": {
"enabled": false,
"icloudPassword": "",
"limit": 10,
"sortNewest": true,
"starredFirst": true,
"unreadOnly": true
}
}
}
}
}
}
| Option | Type | Default | Description |
|---|---|---|---|
location | string | "" | Location for weather (e.g., "New York, NY") |
timezone | string | system | Timezone (e.g., "America/New_York") |
units | string | "C" | Temperature units: "C" or "F" |
birthdays.enabled | bool | true | Enable birthday tracking |
birthdays.lookahead | int | 14 | Days ahead to show upcoming birthdays |
birthdays.sources | array | ["contacts"] | Sources: "contacts" (iCloud), "google" |
calendar.enabled | bool | true | Enable calendar events |
calendar.lookahead | int | 0 | Days ahead (0 = today only) |
calendar.sources | array | ["google", "icloud"] | Calendar sources |
reminders.enabled | bool | true | Enable Apple Reminders |
reminders.dueFilter | string | "today" | Due date filter: "today", "week", or "all" |
reminders.includePastDue | bool | true | Include overdue/past-due reminders |
emails.enabled | bool | false | Enable important emails feature |
emails.icloudPassword | string | "" | iCloud Mail app-specific password |
emails.limit | int | 10 | Maximum emails to show |
emails.sortNewest | bool | true | Sort newest first |
emails.starredFirst | bool | true | Prioritize starred emails |
emails.unreadOnly |
Required:
curl — for weather fetchingbash — for orchestrator scriptOptional:
gog — brew install steipete/tap/gogcli (Google Calendar, Gmail, Contacts)icalpal — brew install ajrosen/tap/icalpal (iCloud Calendar)himalaya — brew install himalaya (iCloud Mail via IMAP)daily-briefing/
├── SKILL.md
├── README.md
├── install.sh
├── scripts/
│ └── daily_briefing_orchestrator.sh
└── bin/
└── run_daily_briefing.sh (created by install.sh)
Good morning - Today is Saturday, February 3, 2024. Partly cloudy skies, around 45°F this afternoon, with a low around 32°F.
🎂 **Birthdays:**
• Today: Jane Doe
• Feb 5: John Smith
📅 **Today's schedule:**
• All-day: Doctor appointment
• 9:00 AM: Team standup
✅ **Reminders:**
• Pick up prescription
📧 **Emails needing attention:**
• Amazon: Your order has shipped
• Chase: Payment received
Take things one step at a time today—you've got this.
"{baseDir}/skills/daily-briefing/bin/run_daily_briefing.sh" --cleanup
| bool |
| true |
| Only show unread emails |