From Recording to Follow-up: What a Local Meeting Pipeline Actually Taught Me
I built an on-device pipeline that turns meeting recordings into linked notes, tracked actions and drafted follow-ups. It worked on day one. Then it invented a meeting, filed a dozen companies as people, fired the morning brief at 2am in Boston, and lost a three-hour workshop entirely.
The pitch I made to myself was simple: most of the admin around a meeting is not thinking, it is transcription. Who was there, what we decided, what I promised to send. A machine can do that. The only hard constraint was that the transcripts could not leave the Mac — meeting recordings are the single most sensitive text I generate, and no amount of convenience justifies posting them to someone else's GPU. (that constraint turned out to shape every decision that followed)
I built the first working version on 19 July 2026, in a day. It ran, it produced notes, and I was briefly very pleased with myself. Everything genuinely interesting happened in the eight weeks after that, when it started being wrong in ways I had not thought to prevent.
What it does, in one paragraph
MacWhisper records a call and drops a transcript into a watched folder. A background job notices, hands the text to a model running on this machine, and writes a meeting note into an Obsidian vault: summary, decisions, actions, open questions, attendees as links. Every attendee accumulates their own page. Every action lands on one dashboard, linked back to the meeting it came from. At 22:00 a rollup threads the day's meetings into the relevant people and project pages. At 07:00 a brief tells me what is coming and what is outstanding. There are eight background jobs in total and the whole thing is plain markdown in a folder.
That is the part that works. Here is the part that taught me something.
A prompt is a suggestion. A guard is a rule.
The first thing to go wrong was the People/ folder. The instruction to the model was explicit and, I thought, unambiguous: attendees are real named individuals only — never teams, never companies, never product names. Within a week I had 19 pages for things that were not people. Platform teams. Partner companies. A persona invented for a demo, sitting in my vault with a page of its own like a colleague.
I tightened the prompt. Then the same class of failure appeared somewhere else entirely: the nightly rollup was creating a new project page for any named topic anyone mentioned. Two runs produced ten junk stubs — a feature name here, a demo name there — each a one-line file pretending to be an initiative.
Then it happened a third time, and this one was worse, because it was a fabrication rather than a filing error. The morning brief has a "Today" section fed by the calendar. On a day when the calendar genuinely returned nothing, the model looked at my recent notes, found some real dates and times in a travel note, and invented a meeting that did not exist. It was plausible. It was formatted correctly. It was completely made up.
Three times, in three different scripts, the pattern was identical: the prompt said don't, and the model did anyway. The fix was the same each time, and it was not a better prompt.
People/pages can now only be created for someone who passes a code-level check first.- The rollup can only update an existing project file. It cannot create one. Names it cannot match get surfaced for me to deal with instead.
- The brief runs through a function that strips a "Today" section outright when no calendar data came back, regardless of what the model wrote.
A prompt is a request to a system that is allowed to decline. A guard is a rule the system cannot route around. Anywhere the pipeline can create something rather than update something, it now needs the second one. I have stopped treating that as a belt-and-braces nicety and started treating it as the default for any generative step with write access.
The clock lies when you cross an ocean
In late July I flew to Boston, and the schedules quietly came apart. The 07:00 brief fired at 02:00 EDT. The 22:00 rollup started running mid-afternoon.
The cause is a genuinely good piece of trivia: macOS launchd computes a StartCalendarInterval as an absolute instant when the job is loaded, not as a wall-clock rule it re-evaluates. Change timezone and it keeps faithfully firing at the moment that used to be 7am. Worse, this Mac sleeps constantly — a job pinned to an exact minute simply misses its window if the lid is shut.
So none of the jobs are pinned to a clock any more. Each one wakes on a plain interval and asks itself a question — am I due? — by checking a marker file against the last time it should have run. Miss a window and it catches up on the next tick. Change continent and it re-reads the clock like anyone else would. There is also a small watcher on /etc/localtime that reloads every schedule when the timezone changes. Two failure modes, both gone, because the schedule stopped being a promise and became a check.
The expensive one was the fix I had already designed
On a Monday afternoon I recorded a three-hour strategy workshop — the kind with the whole leadership group in the room, the kind you cannot re-run. I started it with the global hotkey and never stopped it.
MacWhisper only writes a hotkey-started recording to its database when the recording stops. Nothing stopped it. There was no partial file, no cache, no sandbox temp directory holding a fragment. I searched all of them. The audio never existed anywhere on disk, and it is permanently gone.
The part that stings: on the day I built the pipeline, I had been asked directly whether I wanted a watchdog for exactly this — a job to notice a recording that had been running implausibly long — and I said no. It seemed like a solution to a problem I did not have.
There is now a job that checks every 15 minutes for a recording that has been running three or more hours, or is still going past 18:00, and shouts loudly. It can only warn — MacWhisper has no external stop API, so nothing can stop the recording for me. It is the weakest possible fix, it costs almost nothing, and it would have saved a three-hour workshop. (build the cheap watchdog; you are not as good at predicting your own failure modes as you think)
The bit that actually changed my week
Everything above is infrastructure. This is the part I would actually miss.
When a meeting is judged strategic, the nightly rollup writes a complete follow-up email into the bottom of that meeting's note — subject line, body, what was agreed, what happens next, drawn from what was actually said. So the morning after I have said "I'll send you a summary," the summary already exists. I read it, adjust the tone, send it.
What it does not do is send. That is deliberate and I do not intend to change it. Drafting removes the fifteen minutes of staring at an empty reply; sending would put my name on words I had not read. Those are not the same feature, and only one of them is worth having.
If you want to try this without any of the above
You do not need a local model or eight background jobs to get most of the value. Claude Code can run itself on a schedule and read and write the same folder of markdown, which means it can play the watcher, the model and the scheduled jobs all at once.
- Two folders: one where transcripts land, one for notes.
- An evening scheduled task: read new transcripts, write a meeting note with linked attendees, append actions to one file, draft follow-ups for anything that warrants one.
- A morning scheduled task: read the notes and actions, write a brief.
- Live with it for a fortnight before adding anything else.
Keep the folder layout and note format identical to what you would want long-term. Then moving the brain on-device later — which is what running models locally on this hardware made viable for me — is a change of address, not a rewrite. Everything downstream is just files.
The vault currently holds 221 notes across 28 meetings, 120 people and 8 projects, and none of it depends on the automation surviving. If all eight jobs stopped tonight, the vault would still open, read and search exactly as it does now. That is the test I would apply to anything like this before trusting it with three months of your working life — the notes have to outlive the machinery that wrote them.