Field Notes

An AI morning brief from your Mac calendar and reminders

An AI morning brief on your Mac: every weekday at 8:30 it reads today's calendar and open reminders and lays out your whole day on one page.

A real run on a demo calendar and reminders list: the flow gathers the day, the model writes the plan, the page opens with the day laid out, and Got it ends the run.

The first ten minutes at the desk go the same way most mornings. Open Calendar, count the meetings, notice the 10:00 that moved. Open Reminders, scroll past the things that were due last Thursday, find the one that is due today. Then try to build a morning brief in your head from both lists while the inbox loads.

None of it is hard. It is two apps and some arithmetic about gaps, every weekday, and the reminder that matters is usually below the fold.

This flow does the reading for you. At 8:30 on weekdays it collects today's events and your open reminders, has a model turn them into a plan of under 120 words, and opens it as one page: today on a timeline, the model's suggestions sitting in the free slots, and your reminders marked overdue, today or later. Click Got it and it is gone until tomorrow.

The flow

Eight nodes in three Sections: gather, think, show. Sections change nothing about how it runs; they make the canvas read as its three jobs.

Fig. 1The morning brief on the canvas. Gather feeds Think, Think feeds Show, and the AI Prompt node's red Failure outlet has its own notification.

Gather

Schedule is in calendar mode: Days set to Weekdays, Time 8:30 AM.

Today's date is a Run Script node with one line: date '+%A, %B %-d, %Y'. The model needs to know what "today" and "overdue" mean, and the ISO stamps the other nodes emit (timestamp, rangeStartISO) are in UTC. In Tokyo or Sydney, 8:30 in the morning is still yesterday in UTC, so a model reading those stamps gets the day wrong. The script prints the local date, which arrives downstream as {{output}}.

List Calendar Events has Range set to Today and every calendar included. It emits events as a real array, eventCount, and eventsText, which is already one readable line per event (start, end, title, calendar name).

Apple Reminders runs the List Reminders operation on one list, with Show Completed off and Max Results at 25. Each reminder comes back in results with title, dueDate and priority.

Fig. 2Schedule in calendar mode: the Weekdays chips lit and the time at 8:30 AM.
Fig. 3Apple Reminders set to List Reminders, reading one named list with Max Results at 25.

Think

The AI Prompt node is renamed Plan the day. The prompt drops in all three things the Gather section produced:

Today is {{output}}.

My calendar for today:
{{eventsText}}

My open reminders, as JSON (dueDate is empty when a reminder has no due date):
{{results}}

and asks for the first fixed commitment, the reminders due today or overdue, and any gap of an hour or more with a reminder that fits it. Temperature is 0.3, and the system prompt forbids inventing a meeting, task or time.

Fig. 4The Plan the day inspector. The prompt pulls in the date, the calendar digest and the reminders, and Provider stays on Default, so it follows whatever this Mac uses by default.

Provider is blank in the download, which means your default provider. Pick deliberately, because privacy follows the provider: a cloud model receives your event titles, times, calendar names and reminder titles every weekday. Apple Intelligence runs on the Mac at no cost, and this prompt is small enough for its short context window. Ollama or LM Studio also keep it local.

Show

HTML Template builds the page. {{payload}} puts the whole payload into it as JSON, so the page has the events, the reminders and the plan as real data, and a short script in the page draws them: the day and date, three counts (events, reminders, free time), a timeline from 9 to 6 (wider when your day is) with each event where it falls, and the model's Gap … lines placed in those free slots. The rest of the plan is a list with its labels as tags, and each reminder is marked Overdue, Today or Someday against today's date. If the script cannot read the data, the plan still shows as plain text. Got it calls watchflows.emit(). Everything is inline: a page shown by HTML View cannot load anything from the network.

HTML View shows it with Window set to Window and Chrome set to None. The page's body is transparent and the page is one rounded element, so the window is the page's own edges. A window brings Watchflows forward, which is the point at 8:30: it is the first thing you read.

Fig. 5The page from the run in the video: the demo calendar on the timeline, the model's two suggestions in the free slots, and the reminders marked against today.
Fig. 6HTML View as a window with no chrome, and Give up after set to 240 minutes.

Permissions you will be asked for

Press Run on the canvas once after importing, so the prompts come up while you are watching and not at 8:30 tomorrow.

NodeWhat macOS asksIf you said no
List Calendar EventsFull access to CalendarsSystem Settings, Privacy & Security, Calendars
Apple RemindersWhether Watchflows may control Reminders (it is driven through AppleScript)System Settings, Privacy & Security, Automation
Brief failed (Notification)Whether Watchflows may send notifications, if you have not allowed it alreadySystem Settings, Notifications

The Calendars prompt only appears once. Deny it and the node cannot ask again; you switch it on in System Settings yourself.

What bites in practice

The Mac was asleep at 8:30. The Schedule node makes up a missed morning once, at the next wake, with catchUp set to true. Five slept-through mornings still produce one brief, not five.

Nobody clicks Got it. While the page is open, the flow cannot run again. Give up after is set to 240 minutes so a page left on a desk over a long weekend cannot block Monday. When the wait runs out the node fails and Execution History records a failed run. That is the price of not blocking.

Reminders reads one list. List Reminders takes a list by name, and the default here is Reminders. Change the List field to where your tasks live; a list that does not exist fails the node. The Today and Scheduled views in the Reminders app are smart lists and cannot be read this way. A second Apple Reminders node for another list would overwrite results, so pick the list that matters.

The node does not filter by date. It returns open reminders in the order the list holds them and stops at Max Results. That is why the model gets the date and picks what is due. Raise Max Results for a long list. dueDate is the text Reminders gives AppleScript, in your Mac's language and date format; models read it fine.

The provider is down. The Failure outlet on Plan the day is wired to a notification that says the plan could not be written and why, instead of the run failing where nobody is looking.

Variations

To build it from a sentence instead of importing it, paste this into the Flow Builder:

Paste into the Flow Builder

Every weekday at 8:30 AM, get today's date with a bash script, list today's events from Apple Calendar, and list my open reminders from the Reminders list in Apple Reminders. Have AI write a plan for today in under 120 words: my first meeting, the reminders due today or overdue, and any free hour. Show it in a window: today's events on a timeline with the free gaps and the plan's suggestions in them, and my reminders marked overdue, today or later, with a Got it button that gives up after 240 minutes. If the AI step fails, send me a notification with the error.

Node reference: Schedule, List Calendar Events, Apple Reminders, AI Prompt, HTML View, Sections.

What's in this flow

One trigger. Nodes are listed in the order a run reaches them; the canvas above shows where it branches.

Download this flow
  1. TriggerSchedule
  2. Run ScriptToday's date
  3. AppleList Calendar Events
  4. AppleApple Reminders
  5. AI PromptPlan the day
  6. TransformHTML Template
  7. NotificationBrief failed
  8. ActionHTML View

Run this one yourself

Download the flow, double-click it, and Watchflows opens it on the canvas. Everything in this note is on the 14-day free trial.