MarketingOS ← Library  ·  AI-OS cookbook · 01
Team — save · battle-tested at Passion.io / YouAI

The Meeting Intelligence Stack

Every call you've ever recorded becomes a structured, queryable AI brain — auto-classified, searchable, wired into Claude Code. Feed this one page to Claude Code and skip the 6 production bugs it took me to get here.

Agentic hire · Knowledge Manager Ships with the code — scripts bundle included 2–3 h with this · 2 weeks without Claude Code · Fathom · Supabase · Obsidian ~$40–80/month total
What this builds

From rotting recordings to a business brain

You're in 30–50 calls a month. Strategy, clients, board, sales. 48 hours later the gold is gone — and your AI assistant knows none of it.

Before

Calls rot in Fathom. Nobody rewatches them. Your AI gives generic advice because it has zero context about what actually happened in your business last week.

After

You open Claude Code and ask "Top 3 themes in my client calls this month?" or "Who haven't I spoken to in 60 days?" — and it answers from real transcripts. Automatically. Nothing to do after each call.

→ Hand this to Claude Code with this prompt

"Read this document as my full briefing. Build the Meeting Intelligence Stack end-to-end. Don't deviate from the architecture. Before you start, ask me for: my Supabase URL + service_role key, my exact Fathom name, my clients, my team, my Obsidian vault path, and meeting types to flag. Then generate the schema, the Fathom sync, the bucketing trigger, the iCloud-safe Obsidian export, and a CLAUDE.md. Smoke-test 10 meetings before the full backfill."

Turnkey option: this cookbook ships with the scripts bundle — get it in three steps at the end ↓ : the real production sync + export scripts (sanitized, keys as __PLACEHOLDER__s) plus a 3-section bucketing template and a SETUP-FOR-CLAUDE.md. Your Claude personalizes instead of rewriting.
Architecture — read first

One source of truth, three surfaces

   Every call recorded
          │
     Fathom (recorder)  ──── MCP · OAuth ────┐
                                            ▼
                                  Supabase (Postgres)
                                  ├─ meetings        + auto-classify trigger
                                  └─ transcript_segments
                                            │
            ┌───────────────────────────────┼───────────────────────────────┐
            ▼                               ▼                               ▼
     Obsidian vault                 Claude Code                  Scheduled agent
     second brain ·                CLAUDE.md = full              same creds in memory
     linked notes                  business context              → weekly analyses
Key principle: Supabase is the source of truth. Obsidian is the search surface. Claude Code is the reasoning surface. Never edit the surfaces by hand — re-derive them.
Prerequisites

What you need before you start

01Fathom

Already recording your calls — fathom.video. First sync opens a browser for OAuth via mcp-remote.

02Supabase (free)

Settings → API → grab the project URL + service_role key. God-mode key: env var only, never commit, never share (bug 6).

03Claude Code + Node 18+

Max plan. Node's built-in fetch + npx for mcp-remote@latest.

04Obsidian + your exact name

Vault path (iCloud-synced is fine — see bug 1). Your name exactly as in Fathom — the classifier keys off it.

Project layout

Five files, one folder

meeting-intelligence/
├── fathom-sync.mjs         # Fathom MCP → Supabase (meetings + transcripts). One-shot backfill, then daily.
├── export-to-obsidian.mjs  # Supabase → Obsidian markdown (notes + company/bucket/person hubs). iCloud-safe.
├── supabase/
│   └── bucketing.sql       # The auto-classification trigger (the brain). Run once in SQL editor.
├── CLAUDE.md               # Context: creds + bucketing reference + business context + "always query first"
└── .env                    # SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY  (gitignored)
Under the hood — what your Claude sets up

Six steps, each with a "done when"

The reference path. With the bundle, your Claude walks it for you (see Download & install ↓) — but every step is followable by hand too.

The reference walkthrough of what gets built, in order — your part is the three steps at the end. Download & install ↓

1

Spin up the schema

Two tables: meetings (id, title, recorded_at, recorded_by, invitees[], url, bucket, company, owner_present) and transcript_segments (meeting_id, speaker, timestamp_seconds, content, deep_link_url).

✓ Done when both tables exist in Supabase
2

The classifier trigger — the brain

A Postgres function + trigger sets bucket / company on every INSERT/UPDATE from recorder, invitees and title. Three sections, first-match-wins — order is everything (bugs 3 + 4). A second function computes company independently with the same pattern. Backfill all existing rows at the end by firing the trigger: UPDATE meetings SET recorded_by = recorded_by;

✓ Done when updating a row's invitees re-buckets it automatically
3

Backfill every meeting you've ever had

The sync script speaks JSON-RPC to Fathom via mcp-remote, paginates the meeting list, upserts metadata in batches of 100, then pulls transcripts one at a time (bug 2). You probably have 2–5 years of recordings doing nothing — this turns them into an asset overnight.

✓ Done when select count(*) returns your full history
4

Export to Obsidian — iCloud-safe

One note per meeting (frontmatter + speaker-grouped transcript) plus auto-built hubs: per company, per bucket, per person. Writes to /tmp first, then atomic folder-swap (bug 1).

✓ Done when clicking a person shows every conversation with them
5

Give your AI the context

A CLAUDE.md with creds, the bucketing reference, who's who — and the standing instruction "always query Supabase before answering questions about meetings or people."

✓ Done when Claude answers with real titles + dates
6

Automate + scoped team access (optional)

Cron both scripts daily. For team members: filtered view + read-only key behind RLS — content manager sees client calls, never board or finance. Revoke = rotate the key.

✓ Done when the team queries without seeing god-mode data
Critical bugs — these cost me the iterations

Six walls I hit, so you don't

BUG 01

iCloud eats your files

Writing the export directly into an iCloud-synced vault produces sync-conflict duplicates (_index 2.md everywhere).

✗ Wrong
await writeFile(
  join(VAULT, bucket, file), md);
// iCloud races the delete+write
✓ Right
// build all in /tmp, then swap
const TMP = join(tmpdir(), `exp-${Date.now()}`);
for (const f of folders) {
  await rm(join(VAULT,f), {recursive:true});
  await cp(join(TMP,f), join(VAULT,f),
    {recursive:true});
}
BUG 02

Rate limits kill the backfill

Fathom's MCP rate-limits hard on bulk transcript pulls — parallel requests = 429 storm and half your data missing.

✗ Wrong
await Promise.all(
  meetings.map(m => getTranscript(m.id)));
✓ Right
for (const m of meetings) {
  await getTranscript(m.id);
  await sleep(3000);  // + exp backoff
}                     // 4s 8s 16s 32s on 429
BUG 03

The guard clause silently nulls your team's meetings

If "you're not involved → skip" runs before "team member recorded it", every meeting you weren't personally in gets dropped to NULL and vanishes.

✗ Wrong order
1. external guard → NULL
2. team recorder → department
3. you're involved → client
✓ Right order
1. team recorder → department
2. external guard → NULL
3. you're involved → client
BUG 04

First-match-wins ordering inside the rules

Specific rules must precede generic ones, or meetings land in the wrong bucket.

✗ Wrong
when title ilike '%board%'
  then 'board'   -- catches squad leads!
✓ Right
when title ilike '%squad lead%'
  then 'leads'   -- FIRST
when title ilike '%board%'
  then 'board'   -- after
BUG 05

Re-runs duplicate transcripts

Re-syncing a meeting that already has segments doubles them silently.

✗ Wrong
await insert(segments);
// every re-run doubles the data
✓ Right
if (await hasTranscript(m.id)) continue;
await del(`?meeting_id=eq.${m.id}`);
await insert(segments);
// meetings: Prefer: merge-duplicates
BUG 06

Never ship the service_role key

It bypasses RLS — god-mode. .env only (gitignored), read from process.env. Team access = scoped anon key behind a filtered view: content manager sees client calls, never board, finance, or invitee emails.

GOTCHA

Transcript parsing needs two tiers — and people-hubs need filters

Fathom returns timestamped markdown with deep links [MM:SS](url) Speaker: text — parse that first, and keep a plain Speaker: text fallback for recordings without timecodes. In people-hub extraction: skip bare emails (florian@fino.de → skip) and skip yourself, or you pollute _people/ with junk nodes.

Verify it works

One question proves the whole stack

Open Claude Code and ask: "What are the top 3 themes in my client calls this month — and which meeting titles are you basing that on?"

If it cites real titles and dates → live. Second check: click any person in Obsidian's _people/ → every conversation you've ever had with them.

Make it yours

Customization knobs & cost

WhereWhat to change
bucketing.sql §aYour team members → their departments
bucketing.sql §cYour clients (name + email domain) + title keywords
fathom-sync.mjsYour exact Fathom display name
export-to-obsidian.mjsDEFAULT_VAULT → your vault path
.envSUPABASE_URL · SUPABASE_SERVICE_ROLE_KEY
LayerToolCost
RecordingFathom$19–39/mo
DatabaseSupabasefree–$25/mo
AIClaude Code (Max)$20/mo
Second brain · AutomationObsidian · cronfree

Total: ~$40–80/month — to turn every meeting into a queryable AI brain.

Confirm it worked

You're done when you can show this

Meetings synced · transcripts synced / skipped / errored
Buckets populated + a breakdown by bucket
Obsidian: notes + companies + buckets + people written
Cron jobs registered (crontab -l)
Link to _index.md in the vault
Action items

Your checklist

Create the Supabase project + run the schema
Write your bucketing rules (clients, team, title keywords) — 3 sections, first-match-wins
Run the backfill (smoke-test 10 meetings first)
Wire the Obsidian export + daily cron
Drop CLAUDE.md into the project → ask the verify question
Download & install

One download, three steps

1

Download the bundleThe production sync + export scripts, a bucketing template, and the setup brief.

2

Unzip & open in Claude CodeOpen the unzipped folder in Claude Code (or Cowork).

3

Say the magic sentence"Read SETUP-FOR-CLAUDE.md and install." — it asks for your Supabase keys, Fathom name, clients & team, then wires everything.

Download the bundle Free · 4 files · scripts + bucketing template + setup brief