Guide
Email Yourself a Daily Calendar Agenda
Every morning, pull today's calendar events, format them into a readable list with jq, and email the summary to yourself or a team. This guide builds the whole pipeline as one script you drop on a cron — no calendar app open before coffee.
Written by Pouya Sanooei Software Engineer
Reviewed by Qasim Muhammad
Why email a daily agenda instead of opening a calendar app?
A daily agenda email is a single message, sent each morning, that lists every event on your calendar for that day. It removes the context switch of opening a calendar UI: the day's 4 or 5 meetings arrive in the same inbox you already check first thing. For a shared team calendar, one send keeps everyone aligned.
Many knowledge workers check email within minutes of waking, before a calendar tab is ever opened. A calendar app is a separate tab nobody opens until the first meeting is already starting. Pushing the agenda into email meets people where they already are. The same pipeline scales from one person to a 12-person team by changing a single --to address. Because the CLI authenticates with an OAuth grant, no SMTP server, app password, or calendar export step sits between the events and the inbox.
How do I pull today's events as JSON?
The nylas calendar events list command reads your primary calendar and prints events as structured JSON when you pass --json. The --days 1 flag limits the window to today, so a 30-second query returns only the events the agenda needs.
Each event in the output carries a title, a when.start_time and when.end_time as Unix timestamps, and a participants array. All-day events use when.date instead of timestamps. The default limit is 10 events; raise it with --limit for a packed day.
# Today's events on the primary calendar, as JSON
nylas calendar events list --days 1 --limit 50 --jsonHow do I format the events into a readable agenda with jq?
You shape the raw JSON into a plain-text agenda with jq, which sorts events by start time and prints one line each. Converting the Unix start_time with strflocaltime gives a 24-hour clock label like 14:00, so a 5-meeting day collapses into 5 readable lines.
The expression below sorts by when.start_time, formats each timestamp, and falls back to a label when an event has no title. jq does the date math inline, so no second tool is needed. An event at epoch 1749632400 (09:00 UTC) renders as 05:00 with America/New_York. Set TZ before the command to render local time.
# Sort by start time, print "HH:MM Title" per event
TZ="America/New_York" nylas calendar events list --days 1 --limit 50 --json \
| jq -r 'sort_by(.when.start_time)
| .[]
| "\(.when.start_time | strflocaltime("%H:%M")) \(.title // "(no title)")"'How do I send the formatted agenda as an email?
The nylas email send command takes the jq output as its --body and delivers it through your OAuth grant. The --yes flag skips the interactive confirmation, which is required for unattended cron runs.
Capture the agenda into a shell variable, then pass it to the send. The same body goes to one address or a comma-separated team list. A typical agenda email is under 500 bytes and sends in roughly 1 second. For a richer layout, wrap the lines in HTML in the body — the --body flag accepts HTML or plain text and the CLI auto-detects it, so the message renders with line breaks instead of running together. Provider delivery latency typically stays under 2 seconds for a single recipient.
AGENDA=$(TZ="America/New_York" nylas calendar events list --days 1 --limit 50 --json \
| jq -r 'sort_by(.when.start_time) | .[]
| "\(.when.start_time | strflocaltime("%H:%M")) \(.title // "(no title)")"')
nylas email send \
--to me@example.com \
--subject "Today's agenda" \
--body "$AGENDA" \
--yesHow do I run the agenda automatically every morning?
You schedule the agenda with cron, the Unix job scheduler defined in crontab(5). A single crontab line runs the script at a fixed time each day, so the agenda email is waiting before the workday starts. The five-field cron syntax 0 7 * * 1-5 means 07:00, Monday through Friday.
Cron runs with a minimal environment, so set NYLAS_DISABLE_KEYRING and point the CLI at API-key auth for headless runs — the interactive keyring is unavailable without a desktop session. The full script below handles an empty calendar, sends a “nothing scheduled” note instead of a blank email, and exits 0 either way so cron never logs a failure for a quiet day.
#!/usr/bin/env bash
set -euo pipefail
export NYLAS_DISABLE_KEYRING=1
export TZ="America/New_York"
EVENTS=$(nylas calendar events list --days 1 --limit 50 --json)
COUNT=$(echo "$EVENTS" | jq 'length')
if [ "$COUNT" -eq 0 ]; then
BODY="Nothing scheduled today. Enjoy the open calendar."
else
BODY=$(echo "$EVENTS" | jq -r 'sort_by(.when.start_time) | .[]
| "\(.when.start_time | strflocaltime("%H:%M")) \(.title // "(no title)")"')
fi
nylas email send \
--to me@example.com \
--subject "Today's agenda ($COUNT events)" \
--body "$BODY" \
--yesSave the script, make it executable, and add the crontab entry. Install the CLI first with brew install nylas/nylas-cli/nylas (see getting started for other install methods).
chmod +x ~/bin/daily-agenda.sh
( crontab -l 2>/dev/null; echo "0 7 * * 1-5 ~/bin/daily-agenda.sh" ) | crontab -Next steps
- Automate Scheduling and Email Follow-Ups — Find a shared slot, send the calendar invite, and chase…
- Automate email reports from the terminal — the same cron-plus-send pattern for scheduled inbox digests
- Manage your calendar from the terminal — create, list, update, and delete events from the command line
- Check calendar availability — find open slots across people instead of just listing events
- Set calendar working hours — bound the agenda to the hours you actually work
- Build a calendar AI assistant — turn the agenda into a natural-language daily briefing
- Command reference — every flag, subcommand, and example
- crontab(5) man page — the five-field schedule syntax used above
- jq manual — the strftime, sort_by, and string-interpolation reference
- Google Calendar API: events.list — the event fields behind a Google calendar agenda
- Microsoft Graph: list events — the equivalent for Outlook and Microsoft 365