Oatmeal
A native Mac meeting notetaker that's invisible to screen sharing
not yet reviewed by publik
Oatmeal
open source · on publik
How to install Oatmeal
Every step written out, for people who have never opened a terminal. Pick the setup you have.
README
Open in GitHub🥣 Oatmeal
A native Mac meeting notetaker that's invisible to screen sharing.
Mic + system audio, transcribed on-device with Whisper, written up by a local language model — all inside a small floating window that never appears in Zoom, Meet, or any screen share. No bots joining calls. No accounts. No API keys. No cloud.
How it works
you, in a meeting ──► Oatmeal.app (invisible to screen share)
mic + system audio
│
▼
whisper.cpp transcribes live, on-device
│
▼
llama.cpp writes notes, on-device
│
▼
~/Library/Application Support/dev.oatmeal.app/recordings/
The recorder is a native window — NSWindow.sharingType = NSWindowSharingNone —
so it's excluded from every screen/window capture (Zoom, Discord, Loom,
QuickTime…) while staying fully visible on your own display. A title-bar pill
lets you flip it visible again when you actually want to share it. Nothing
about the meeting — audio, transcript, or notes — ever leaves the machine
except the one-time model downloads on first launch.
What it does
| Lane | How |
|---|---|
| Invisible window | NSWindow.sharingType = NSWindowSharingNone, flippable back to visible from the title bar. |
| Microphone + system audio | cpal for the mic, ScreenCaptureKit for a system-audio tap — no BlackHole or virtual driver. |
| Live transcript | whisper-rs (whisper.cpp, Metal GPU) streams lines into a floating window while you record. |
| Notes | A local instruct model (llama.cpp, Metal GPU) writes a summary once the meeting ends; you can also type your own notes as you go. |
| Calendar | Reads Apple Calendar (EventKit — iCloud, Google, Exchange, whatever your Mac already has) so upcoming meetings show on the home screen. |
Meetings are saved to
~/Library/Application Support/dev.oatmeal.app/recordings/<date>-<title>/ as
plain transcript.md and notes.md files next to the audio — nothing is
locked in a database.
Updating
Your meetings are not inside the app. They live under
~/Library/Application Support/dev.oatmeal.app/, so replacing Oatmeal in
/Applications never touches a recording, a transcript, or a note. Every write
to those files is atomic — a crash, or quitting the app to install a new
version, cannot leave a half-written note behind.
Oatmeal checks this repository's releases when it starts. A newer version shows a strip you can dismiss; occasionally a release is marked required, and then the app asks you to update before continuing (In app updates). If it can't reach GitHub it says nothing and carries on — you can always record offline.
One wrinkle worth knowing: builds are ad-hoc signed, so macOS treats each release as a new app identity and will ask for Microphone and Screen Recording again after an update.
Privacy
- Transcription and note-writing both run on-device — Whisper and the local language model, via whisper.cpp/llama.cpp on the Metal GPU. Audio is never stored or uploaded anywhere.
- The only network calls Oatmeal makes are the one-time model downloads — the Whisper and note-writing models on first launch — an update check that asks GitHub for this repository's release list when the app starts, and — if you're using the Calendar features — EventKit itself running in-process. The update check sends nothing but the request.
- Attaching a YouTube video to a note reaches the network twice more, and both
are worth knowing about. Pasting the link already contacts YouTube —
Oatmeal looks the video up to read its title and length before you press
Transcribe, so the request goes out as soon as you paste, not when you
confirm. And the first time you do this, Oatmeal downloads a third-party
helper program,
yt-dlp, from github.com and runs it on your machine; nothing else in Oatmeal does that. The version is pinned in the source, so the app never fetches whatever build happens to be newest. These requests tell Google which video you asked for and the IP address you're asking from, but send nothing about your meetings, notes, or transcripts, and none of it happens unless you paste a link. - Recording people has consent rules that vary by place. Tell attendees you're taking notes.
Alternative: browser recorder + your coding agent
This repo also ships a second, older way to run Oatmeal — a zero-dependency
local web server instead of a native app, meant to be driven by a coding
agent (Claude Code, Cursor, Codex…) rather than the app's own local model.
Transcripts land as plain Markdown in a meetings/ folder that your agent
reads, writes notes into, and can commit to git as a shared team knowledge
base. Cross-platform, but the window is not hidden from screen sharing.
git clone https://github.com/Cujoqt/oatmeal.git
cd oatmeal
npm install
npm start # recorder at http://localhost:4123
Then paste one line into your coding agent:
Read SKILL.md and set up Oatmeal for me.
The agent starts the recorder, opens http://localhost:4123, and tells you how
to record. (Claude Code auto-discovers the skill via .claude/skills/ —
mentioning meetings is enough.) When a meeting starts: hit Record, share
Entire screen with "share system audio" checked (window shares carry
no audio). When it ends, tell your agent:
write up my meeting
You get summary, key points, decisions, and action items — committed to git if the repo has a remote.
Claude Code superpowers for this path
| You type | What happens |
|---|---|
/meeting | Recorder starts (if needed) and opens in your browser |
/writeup | Latest transcript becomes polished notes: summary, decisions, action items — committed & pushed |
/recall what did we tell Acme about pricing? | Grounded answer from every meeting in the knowledge base, with file citations |
/prep akrit | Pre-meeting brief: what you discussed last time, open action items, promises made, suggested agenda |
- It notices unwritten meetings. A
SessionStarthook checks for transcripts with no notes — open Claude Code after a call and it offers the write-up before you ask. - MCP auto-registers.
.mcp.jsonexposeslist_meetings/search_meetings/get_meetingto any MCP client the moment you open the repo.
Other agents: the same flows work by asking in plain English — the commands
are just markdown files in .claude/commands/, readable
by anything.
Running as a background service (no agent, no terminal open)
node scripts/install-autostart.mjs
Registers the recorder as a real background service — a Startup-folder entry
on Windows, a LaunchAgent on macOS, systemd --user on Linux — with no admin
rights and no permission prompts. Starts at every login, keeps running.
Uninstall with node scripts/install-autostart.mjs --uninstall.
If your coding agent has (or can add) a Google/Outlook Calendar connector,
just ask it to wire your calendar into Oatmeal. No connector? Copy
oatmeal.config.example.json to oatmeal.config.json, paste your calendar's
ICS feed URL, and re-run the install script — it also installs a calendar
watcher that opens the recorder ~7 minutes before each meeting.
What's in the repo
| Path | What it is |
|---|---|
app/ | The native macOS app (Tauri + Rust) — invisible recorder window, on-device Whisper + local LLM |
SKILL.md | The product spec your coding agent follows for the browser-recorder path — setup, notes flow, knowledge base rules, calendar automation |
capture/ | Zero-dependency local server + recorder page for the browser-recorder path |
meetings/ | Transcripts + notes written by the browser-recorder path. Plain Markdown. |
scripts/mcp-server.mjs | Optional MCP server — expose meetings/ to any MCP client |
scripts/install-autostart.mjs | Registers the browser recorder (+ calendar watcher) as a background OS service |
scripts/calendar-watch.mjs | Standalone ICS calendar poller for the browser-recorder path |
.claude/skills/ | Auto-discovery so Claude Code picks up the skill on clone |
Contributing
PRs welcome.
Good first issues:
- Smarter meeting-title detection (from calendar or first few words)
- Calendar connector recipes for the browser-recorder path (Google, Outlook, Slack integration guides)
- Full multi-person diarization (mic vs system audio are already tagged "You"/"Room" — telling apart two+ people on the other end of the call would need Pyannote or similar)
- Better error messages (when Whisper fails, when git push fails, etc.)
Not in scope: cloud sync, accounts, compliance features (fine-grained audit logs), multi-language models beyond Whisper's baseline. Those belong in derivatives, not core.
License
MIT © Vedant Soni — free forever.