Skip to content

README.md

127 lines · 5.7 KB · Markdown

@kody/morning-briefing

Composable daily briefing from calendar, weather, and optional inbox, health, or home signals. Delivered by email or a short notify-self message. No Discord.

Intent

Give any signed-in account one reliable morning update they can compose themselves. Calendar and weather are the default sources. Inbox, health (air quality), and home are optional and degrade to a skipped or warning section when auth or data is missing. Success is a structured report plus a dryRun preview that never sends mail until you choose an output channel and turn dry-run off.

This package is the generic official briefing. It does not post to Discord, and it does not ship Kent-specific Kit, YouTube, GitHub, Tesla, or apartment wiring.

What it does

  • Build today's briefing from the sources you have connected
  • Preview the email or notify payload with dryRun: true
  • Read a stored report for a date without rebuilding every source
  • Schedule a disabled-by-default 07:00 UTC job after you save config

Compose sources

Pass sources to choose what runs. Default is calendar and weather.

SourceDefaultWhat it readsAuth
calendaryesToday's events via @kody/google/calendarGoogle OAuth (account, default personal → integration google)
weatheryesDaily forecast + current conditions via Open-MeteoNone. Pass location (city or place name)
inboxnoUnread Gmail via @kody/google/gmailGoogle OAuth with Gmail read scopes (gmail.readonly)
healthnoUS AQI / PM2.5 via Open-Meteo Air QualityNone. Uses location (or health.location)
homenoCaller-supplied snapshot itemsNone in this package. Pass home.items, or skip until you have a home connector

Sources run independently. A missing integration becomes a warning or skipped section; the rest of the briefing still builds.

Prerequisites / setup

Calendar (Google OAuth). Connect the saved google integration:

https://kody.codes/connect/oauth?provider=google

Pass calendar.accounts using @kody/google aliases (personal, business, …). Every Calendar call needs an explicit account. Widen Calendar scopes from the connect UI when a mailbox has more than the primary calendar.

Weather and health (zero auth). Public Open-Meteo geocoding, forecast, and air-quality APIs. Attribute Open-Meteo (CC BY 4.0) when you reuse the data. Set location on the run or persist it in package config for the scheduled job.

Inbox (Google OAuth with Gmail read). Gmail read scopes are restricted — this package still exports the inbox source; do not hide it. Create a Google Cloud OAuth Web application client, register redirect https://kody.codes/connect/oauth, enable the Gmail API and Calendar API, publish the app to Production (Testing refresh tokens expire after seven days), then connect:

https://kody.codes/connect/oauth?provider=google&authorizeUrl=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Fv2%2Fauth&tokenUrl=https%3A%2F%2Foauth2.googleapis.com%2Ftoken&flow=confidential&scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.readonly&allowedHosts=www.googleapis.com%2Cgmail.googleapis.com&extraAuthorizeParams=%7B%22access_type%22%3A%22offline%22%2C%22prompt%22%3A%22consent%22%7D

Use the personal (or other) @kody/google account alias that matches that connection. A 403 / insufficient-scope error names gmail.readonly and this URL. See coding_guide_get({ guide: "provider_google" }).

Home. This official package does not call a personal home MCP or Discord. Pass home.items from your own home package, or omit home from sources.

This composer does not need an API-key secret. There is no /account/secrets/new step for calendar, weather, health, or email output.

Hosts
  • www.googleapis.com — Calendar
  • gmail.googleapis.com — inbox (BYO only)
  • geocoding-api.open-meteo.com, api.open-meteo.com, air-quality-api.open-meteo.com — weather and health (public)
Scopes
  • Calendar: https://www.googleapis.com/auth/calendar.readonly (or calendar.events.readonly)
  • Inbox: https://www.googleapis.com/auth/gmail.readonly (restricted; BYO client)

If Google returns 403 / insufficient-scope, the package throws (or records a warning section) naming the missing scope and the next connect URL. It does not fail silently.

Agents: see AGENTS.md for import paths, smoke checks, and delivery dry-runs.

Output: email or notify

output is email (default) or notify. Both use kody.emailSend to your own account address.

  • email — full markdown briefing
  • notify — short subject + callout-only body

dryRun: true builds and stores the report, returns preview.subject / preview.text, and does not send. The scheduled wrapper uses the same implementation; keep the job disabled until a dry-run looks right.

Persist config for the job

The no-argument job daily-morning-briefing loads JSON from package storage table config key briefing (same fields as the run input, minus dryRun). Save it once, invoke ./run-morning-briefing with no params to prove the scheduler contract, then enable the job.

Done when

  • Weather-only build-report returns sections without OAuth
  • Delivery dry-run returns preview and does not send mail
  • Optional Google sources warn or skip when auth is missing instead of aborting the whole briefing
  • daily-morning-briefing stays disabled until config is saved and a dry-run looks right

Jobs

daily-morning-briefing runs ./run-morning-briefing daily at 07:00 UTC. It is enabled: false. Enabling it is an operator choice after you save config and confirm a dry-run.