# Show HN: Meeting Notes Sync – import transcripts and AI summaries into Obsidian

> Source: <https://community.obsidian.md/plugins/meeting-notes-sync>
> Published: 2026-06-18 08:34:11+00:00

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](https://macparakeet.com) and [Fellow](https://fellow.app), 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](https://macparakeet.com) 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](https://github.com/TfTHacker/obsidian42-brat) (*Add beta plugin* → `andreagrandi/obsidian-meeting-notes-sync`

), or manually drop `main.js`

+ `manifest.json`

from a [release](https://github.com/andreagrandi/obsidian-meeting-notes-sync/releases) 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
# copy main.js + manifest.json into <vault>/.obsidian/plugins/meeting-notes-sync/
```

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](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](https://github.com/obsidianmd/obsidian-releases) is a one-time manual step after the first release.
