Daily email summarizing calendar, weather, and personalized insights. Runs via Forgejo Actions cron at configurable times (5am PT for work days, 8am PT for off-days).
What It Does
Core sections:
- Calendar summary (today + upcoming events)
- Weather forecast (current conditions + 3-day outlook)
- Contextual insights based on calendar data
Sunday special: Includes Weekly Listening Digest with genre charts, album art, and discovery recommendations from Last.fm data.
Architecture
graph LR A[Forgejo Cron] --> B[briefing.py] B --> C[CalDAV API] B --> D[Weather API] B --> E[Last.fm API] C --> F[Email Template] D --> F E --> F F --> G[SMTP Send] G --> H[Zoho Mail]
Repo: agent/morning-briefing (git.brads.house)
Deploy: Forgejo Actions (not in commune/skills — this is Brad-specific)
Implementation
Scripts
briefing.py— main briefing generatorweekly_digest.py— Sunday listening summarysend.py— email utility (reusable)
Credentials
All via rbw:
- Calendar:
rbw get --raw "Calendar" - SMTP:
rbw get --raw "Zoho Email for Clawd" - Last.fm:
rbw get --field API_KEY "LastFM API Key"
CI Schedule
Two workflows:
work-day.yml— runs at 5am PT on Mon-Frioff-day.yml— runs at 8am PT on Sat-Sun
Hold vs Confirmed: Work calendar distinguishes between “HOLD” (reserved, client has first refusal) and “CONFIRMED” (committed shoot day). Only CONFIRMED counts as a work day in morning briefing logic.
Email Format
Plain HTML with inline CSS (Gmail-compatible):
- Clean typography (system fonts)
- Responsive layout
- Album art thumbnails (Last.fm digest)
- Genre charts with emoji icons
Related Projects
Built on patterns from Concert Radar — both do multi-source data aggregation, credential management, and automated delivery.
The email utility (send.py) is generic enough to extract into commune/skills if other agents need SMTP sending.
Related
- Last.fm API — data source for Sunday listening digest
- Concert Radar — similar multi-source aggregation pattern
- Credential Management — how API keys are accessed
- Forgejo — the cron runner
- Agent Projects for other examples