Sync meeting transcripts, notes, and AI summaries from MacParakeet and Fellow into your vault.
Obsidian plugin that syncs your meeting transcripts, notes, and AI summaries into your vault — from MacParakeet and Fellow, one folder per meeting. A meeting recorded by both sources merges into a single folder instead of duplicating.
Summary (MacParakeet).md
, Summary (Fellow).md
), so a meeting captured by both stays unambiguous.merge-confidence: low
for review.
Meetings/2026/06 - June/2 - Weekly Standup - Jun 11th/
2 - Weekly Standup - Jun 11th.md ← index: macparakeet-id + fellow-id + interval
Summary (MacParakeet).md
Transcript (MacParakeet).md
Notes.md
Summary (Fellow).md
Action Items (Fellow).md
Transcript (Fellow).md
Each source is toggled independently; a disabled source is completely inert — no requests, writes, or notices.
Reads meetings from macparakeet-cli
(no network, no accounts, no database access). Requires macOS with MacParakeet installed (the CLI ships inside the app) or the standalone CLI (brew install moona3k/tap/macparakeet-cli
), and Obsidian desktop. The plugin auto-detects the CLI (Homebrew paths, then the app bundle); override the path in settings if needed, and the health check confirms it. Enable it in Settings → Meeting Notes Sync.
Polls Fellow's REST Developer API for cloud AI recaps. Setup:
acme
in acme.fellow.app
) and ⚠️ The Fellow key is stored in plaintext in
data.json
(standard for API-backed plugins). If your vault is in git or a synced folder, exclude that file and treat the key as a secret; revoke it in Fellow if it leaks.
Pending community-store review — until it lands there, install via BRAT (Add beta plugin → andreagrandi/obsidian-meeting-notes-sync
), or manually drop main.js
manifest.json
from a release into <vault>/.obsidian/plugins/meeting-notes-sync/
and enable the plugin. To build from source:
git clone https://github.com/andreagrandi/obsidian-meeting-notes-sync
cd obsidian-meeting-notes-sync && npm install && npm run build
If you used an earlier build under the macparakeet-sync
id: quit Obsidian, rename <vault>/.obsidian/plugins/macparakeet-sync/
→ meeting-notes-sync/
, reopen, and re-enable. This keeps data.json
(numbering, snapshots, file ownership) so the next sync is a no-op instead of re-importing. Existing folders keep their names; only new artifacts get the source suffix.
Sync runs shortly after launch and every 30 minutes (configurable; 0
disables), or on demand via the ribbon icon / Sync now. The main settings:
Meetings/…
is the root).{year}
· {month}
· {monthName}
(June) · {monthShort}
(Jun) · {day}
· {dayOrdinal}
(2nd) · {date}
(YYYY-MM-DD) · {n}
(per-month number) · {title}
. Unknown tokens are left as-is.
Default: Meetings/{year}/{month} - {monthName}/{n} - {title} - {monthShort} {dayOrdinal}
→ Meetings/2026/06 - June/4 - Core sync-discovery - Jun 2nd
. The trailing date disambiguates recurring meetings that share a title.
Overlap threshold (fraction of the shorter meeting, default 0.5) and minimum overlap (minutes) govern when two sources' meetings are treated as one. Raise them to merge more conservatively.
| Command | What it does |
|---|---|
Sync now |
|
Sync enabled sources; reports X new, Y updated, Z unchanged |
|
Check connection |
|
Verify macparakeet-cli is reachable (Fellow's check lives in settings) |
|
Force re-sync |
|
| Re-process all in-scope meetings (picks up in-place regenerated summaries) |
{n}
) and the folder name are frozen on first import and never change — a later source merges in without renumbering.Each source sits behind a common adapter and a source-agnostic engine: MacParakeet via macparakeet-cli
(meetings list/show/results list --json
), Fellow via its REST API (/me
, /recordings
, /recording/{id}
, /note/{id}
) with updated_at
change detection. Meetings are merged across sources by interval overlap, and sync state (numbering, per-file ownership, per-source snapshots) lives in data.json
. Details in PLAN.md.
npm install
npm run dev # esbuild watch
npm test # vitest
npm run build # typecheck + production bundle
CI runs build + tests on every push and PR.
Live Fellow test — npx -y tsx scripts/fellow-live-test.mts
runs the real engine (local CLI + live Fellow API) into a temp vault. It reads FELLOW_SUBDOMAIN
/ FELLOW_API_KEY
from .env
(see .env.example
) for the harness only; the plugin itself never reads the environment — end users configure the subdomain and key in the settings UI.
Releasing — npm run release <major.minor.patch>
(e.g. npm run release 0.3.1
) bumps package.json
, manifest.json
, versions.json
, and the lockfile, then commits and creates the unprefixed X.Y.Z
tag. Push it (git push origin master && git push origin <version>
) to trigger .github/workflows/release.yml
, which attests main.js
's build provenance and attaches main.js
manifest.json
to a GitHub release (Obsidian downloads only those two; versions.json
is read from the repo). A plain npm run
script is used (not the npm version
lifecycle hook) so it works regardless of a global ignore-scripts=true
. Community-store submission to obsidianmd/obsidian-releases is a one-time manual step after the first release.