summarize-meetings · git:20260706.7e33712 · 2026-07-06 · sha256 395221da8e39ea1c

summarize-meetings git:20260706.7e33712A

Immutable. This exact content never changes and is served at /api/v1/blob/395221da8e39ea1c.

---
name: summarize-meetings
description: Batch-processes a backlog of Granola meeting transcripts into structured Obsidian notes — summaries, People stubs, Concept notes, and wiki-links. Use when you have a pile of Granola meeting transcripts to summarize, process, or turn into Obsidian knowledge graph entries; or when asked to "summarize meetings", "process meetings", "meeting notes cleanup", or "extract insights from meetings".
---

# Summarize Meetings

Process meeting transcripts from `Meetings/transcripts/` — extract people, action items, project ideas, blog ideas, knowledge graph connections, concepts, and general ideas. Populate the vault knowledge graph and generate rich summary files.

## Setup

Before running this skill, determine the absolute path to the Obsidian vault. Check the project's `CLAUDE.md` or user configuration, or ask the user: "What is the absolute path to your Obsidian vault?" There is no silent default.

All agent prompts in this skill use `{{VAULT_PATH}}` as a placeholder. Replace it with the actual vault path before dispatching any agent.

## Campaign Workflow

Processing works in **monthly batches**, most-recent month first. Each month follows this cycle:

1. Scan month (ls -lS)
2. Triage: check small/suspicious files
3. Identify skips vs substantive
4. Dispatch wave of agents (10-15)
5. Wait for returns
6. Dispatch remaining agents
7. All agents returned
8. Compile monthly report table
9. Post social media update
10. Next month or stop

### Step 1: Scan the Month

```bash
ls -lS "Meetings/transcripts/" | grep "YYYY-MM"
```

List all transcripts for the target month, sorted by size. This gives you:
- Total count of transcripts
- File sizes (critical for triage and agent instructions)
- Filenames for slug generation

### Step 2: Check for Existing Summaries

```bash
ls "Meetings/" | grep "YYYY-MM.*summary"
```

Skip any transcript that already has a corresponding summary file.

### Step 3: Triage

Before dispatching agents, manually check files that are suspicious:

| Signal | Action |
|--------|--------|
| **< 2K** | Read the file — likely empty stub or sparse notes |
| **2K-6K** | Skim the file — may be scheduling fragment, garbled recording, or logistics-only |
| **Filename says "untitled"** | Almost always empty — read to confirm |
| **Known non-meeting patterns** | Medical appointments, kid brainstorming, screen-sharing setup, recording process discussions |

**Skip criteria (with log entry):**
- Empty stubs (template only, no content)
- < 20 words of real content after frontmatter
- Garbled/corrupted recordings
- Scheduling fragments (just logistics, no substance)
- Medical/personal appointments
- Kid content (school brainstorming, etc.)
- Recording process discussions (just setting up Granola)
- Screen-sharing setup conversations

**Sparse but substantive notes** (like handwritten bullet points from a real meeting) should still be processed — even 1.2K of real fundraising notes is worth a summary.

### Step 4: Dispatch Parallel Agents

Spawn one Task agent per transcript using `subagent_type: general-purpose` with `mode: bypassPermissions` and `run_in_background: true`.

**Wave sizing:** Dispatch 10-15 agents per wave. Wait for returns, then dispatch remaining agents. This prevents overwhelming the system while maintaining parallelism.

**Large file instructions:** For files > 50K, include "read in chunks using offset/limit" in the agent prompt. For files > 100K, explicitly say "this is a large file — read in chunks of 500-1000 lines using offset/limit parameters."

**Agent prompt template** (replace `{{VAULT_PATH}}` with the actual vault path before dispatching — see [Setup](#setup)):

```
You are a meeting summarizer for an Obsidian vault at `{{VAULT_PATH}}`.

Read the transcript at `[PATH]` ([SIZE] — [read in chunks if large]).

Then:
1. Extract: People, Action Items, Project Ideas, Blog Ideas, Knowledge Graph, Concepts, Ideas
2. Write summary to `Meetings/YYYY-MM-DD-slugified-name-summary.md`
3. Create/update People notes in `People/Firstname Lastname.md` (Title Case) — check if they exist first
4. Create Concept notes in `Concepts/` for genuinely reusable insights

Use the full summary template with YAML frontmatter (title, date, tags, type, source, status, related).
Write a strong 2-4 paragraph narrative meeting summary.
Use `[[wiki-links]]` throughout.
Never fabricate info not in the transcript.
Don't create People stubs for first-name-only references.
```

### Step 5: Compile Monthly Report

After all agents return, present a summary table:

```
| Meeting | Date | People | Actions | Concepts | Status |
|---------|------|--------|---------|----------|--------|
| harper-john | Jan 31 | 1 | 5 | 3 | Done |
| untitled | Jan 15 | - | - | - | Skipped (empty) |
```

Include: total processed, total skipped (with reasons), and notable highlights (interesting concepts, key people).

### Step 6: Social Media Update

Post a completion update via `mcp__socialmedia__create_post` with:
- Month completed
- Count of summaries processed
- Notable highlights (key meetings, interesting concepts)
- Tags: `["meeting-summaries", "month-year", "vault-curation"]`

---

## Transcript Format: Granola

See [references/transcript-format.md](references/transcript-format.md) for the full Granola transcript structure, key fields, and common quirks.

---

## Determining "Substantive"

A note is **not substantive** if:
- Body content (after frontmatter) is only template skeleton with no filled-in content
- Body has fewer than 20 words of actual content (excluding headings, `---`, empty bullets)
- All discussion/notes sections are blank
- Content is garbled/corrupted (random characters, no coherent sentences)
- Content is purely logistics (scheduling, screen sharing setup)

Skip these with a log entry. Don't waste a summary on nothing.

---

## Extraction Categories

For each substantive meeting note, extract:

### 1. People
- Full names mentioned in content or attendees
- Role/company/context if discernible
- Relationship to the vault owner if clear

### 2. Action Items
- Explicit tasks (`- [ ]`, "need to", "should", "will", "action:")
- Owner if identifiable
- Due dates if mentioned
- Preserve existing Obsidian Tasks syntax items

### 3. Project Ideas
- Products, tools, apps, or ventures discussed
- Both existing projects and new ideas
- Brief description of what was discussed about each

### 4. Blog Ideas
- Topics worth writing about publicly
- Interesting takes or contrarian views expressed
- Experiences worth sharing

### 5. Knowledge Graph Ideas
- Connections between entities (people <-> projects, concepts <-> people)
- Relationships worth capturing as wiki-links
- Patterns across meetings (if processing a batch)

### 6. Concepts
- Mental models, frameworks, or reusable ideas
- Strategic insights or principles discussed
- Technical concepts worth an atomic note
- **Must be genuinely reusable** — not just a topic that was discussed
- **Check vault first** — enrich existing concept notes rather than creating duplicates

### 7. Ideas
- General ideas that don't fit the above categories
- Shower thoughts, brainstorms, what-ifs
- Anything interesting that was floated

---

## Vault Graph Updates

### People Notes

For each person extracted:

1. **Check** if `People/Firstname Lastname.md` exists (search case-insensitively, check aliases)
2. **If exists:** Add meeting reference to `related` frontmatter. Append new context to Notes section. Update `last-contact` if this meeting is more recent.
3. **If not exists and full name is known:** Create stub using Person template (below)
4. **If only first name:** Do NOT create a stub. Document them in the summary's people table with whatever context is available.

**Name resolution:**
- Transcript may misspell names — cross-reference with `attendees` frontmatter and existing vault notes
- Nicknames in transcript (e.g., "Dens" for Dennis Crowley, "JB" for John Borthwick) — match to existing People notes and add as aliases
- When uncertain if a first-name reference matches an existing person, note the ambiguity rather than guessing

**People note stub template:** See [references/templates.md](references/templates.md#people-note-stub).

**File naming:** `People/Firstname Lastname.md` — Title Case, NEVER kebab-case for people.

### Concept Notes

For concepts worth capturing in `Concepts/`:

**Before creating a new concept note:**
1. Search `Concepts/` for existing notes on the same topic
2. Check aliases and related terms
3. If a related concept exists, **enrich it** with new evidence/connections rather than creating a duplicate
4. Only create a new note if the insight is genuinely distinct and reusable

See [references/templates.md](references/templates.md#concept-note) for the Concept note template.

### Project Stubs

For projects mentioned that don't exist in `Projects/`: See [references/templates.md](references/templates.md#project-stub) for the Project stub template.

---

## Summary File Format

Write to: `Meetings/YYYY-MM-DD-slugified-meeting-title-summary.md`

See [references/templates.md](references/templates.md#summary-file) for the full YAML frontmatter and markdown body template, including slug generation guidance.

---

## What NOT To Do

- Never delete or modify the original transcript
- Never strip existing links or tags from the original
- Never create duplicate People notes — check existing vault first, use aliases
- Never create duplicate Concept notes — enrich existing ones instead
- Never modify Dataview or Tasks query blocks in any note
- Never fabricate information not present in the meeting notes — extract only what's there
- Don't create People stubs for ambiguous first-name-only references unless context makes identity clear
- Don't create concept notes for trivial or obvious things — only genuinely reusable insights
- Don't create concept notes that overlap significantly with existing ones — add to the existing note instead
- Don't process medical appointments, kid content, or recording setup conversations
- Don't rely solely on Granola's `summary_text` — always read the actual transcript