| name | fill-participants |
| description | Resolve and fill Participants frontmatter + link unlinked names in body. Args: <path>, all. |
| license | MIT |
| compatibility | Requires qmd (CLI or MCP) and gws CLI when resolving names from Google Docs (read-only). See [google-workspace-cli](../_shared/google-workspace-cli.md). |
Fill Participants
Usage
/fill-participants all — Scan all meetings, find those missing Participants, resolve and fill them.
/fill-participants <path> — Fill participants for a specific meeting note (relative to workspace root, e.g. Meetings/Engineering/Some Meeting.md).
Frontmatter Conventions
See people-resolver for wikilink format and name matching rules.
Participants live in YAML frontmatter as either:
Participants: "[[@Jane Doe]]"
Participants:
- "[[@Jane Doe]]"
- "[[@Alex Kim]]"
Participants: "[[+Engineering]]"
Workflow
Step 1: Identify targets
Mode A (all):
Run /note-status pending --step=participants to discover notes missing Participants:, present them, and let the user select which to process.
Mode B (specific file):
- Read the specified file.
- Check if Participants already exists in frontmatter. If so, inform user and stop (or ask if they want to override).
Step 2: Gather participant info for each target
For each meeting missing Participants, determine attendees using the resolution priority defined in people-resolver. In summary:
- External transcript sources — Use the source linked in
Notes: frontmatter:
- Google Docs: Extract document ID from
Notes:, fetch content with gws (gws docs documents get or gws drive files export to plain text — see google-workspace-cli); Gemini summaries name participants explicitly.
- Otter.ai: Use otter-fetch when an Otter URL is in
Notes: (user pastes JSON; run parse_otter.js or parse inline).
- File name —
X x Y patterns.
- File content — Existing
[[@Name]] references.
- Folder conventions — e.g.
Meetings/Engineering/Scrum/ → [[+Engineering]].
- Similar meetings — Recurring meeting with same name, different date.
- Tracker.md — Jira ticket assignees for disambiguation.
Step 3: Match names to People files
Build a name dictionary per people-resolver. Match names from the transcript source (Google Docs, Otter when enabled, etc.) against the dictionary. Flag any unmatched names for user confirmation.
Step 4: Present findings and ask for confirmation
Present results grouped into:
- Confident matches — Table of meeting → proposed Participants. Apply without asking.
- Needs confirmation — Ambiguous matches, unknown people, or meetings with only Otter.ai links (no Google Doc). Ask the user.
- New people — Names not in People files. See people-resolver § "Creating New People".
Also flag if any existing @Person.md files are missing key properties (FullName, Team) that were discovered from Google Docs.
Step 5: Link unlinked names in note body
Scan the entire file content (body + AI transcript callouts) for mentions of people that are not already wrapped in [[@Name]] wikilinks. This catches plain-text references from Gemini transcripts and manual notes.
5a: Build a name dictionary
Use the name dictionary and matching rules from people-resolver.
5b: Scan for unlinked mentions
Search the note body for each name variant, following the word boundary and skip rules in people-resolver.
5c: Present matches for confirmation
⚠️ MANDATORY: Always prompt the user before replacing. Never auto-replace — false positives are common with first names and nicknames.
Display a numbered table of proposed replacements:
| # | Replace? | Found text | → Link | Context (surrounding text) |
|---|----------|------------|--------|---------------------------|
| 1 | ✅ | Jane Doe | [[@Jane Doe]] | "...assigned Jane Doe a bug ticket..." |
| 2 | ✅ | @Jane | [[@Jane Doe]] | "...recent changes made by @Jane..." |
| 3 | ⬜ | Alex Kim | [[@Alex Kim]] | "...Alex Kim confirmed they have been..." |
| 4 | ⬜ | Alex | — (skip, it's the user) | "...Alex Rivera and Alex agreed..." |
- Default
✅ for full-name matches (high confidence).
- Default
⬜ for first-name-only or nickname matches (need confirmation).
- Always skip linking the vault owner's name (see
USER.md Identity) — these don't need wikilinks.
- Show a short context snippet so the user can judge correctness.
- Let the user toggle by saying numbers (e.g. "1,2" or "all" or "none").
5d: Apply confirmed replacements
Use StrReplace for each confirmed match. When a name appears multiple times, ask the user if they want to replace all occurrences or specific ones.
Step 6: Apply frontmatter changes
For each file, add Participants: to the YAML frontmatter just before the closing ---. Use StrReplace targeting a unique anchor (last line before ---).
Step 7: Handle intentionally blank meetings
For meetings where participants genuinely can't be determined:
- Use team links where the meeting clearly belongs to a team (e.g.
[[+QA]], [[+Eng]]).
- Use
— (em-dash) as the universal "intentionally left blank" marker for true unknowns.
- Never leave the field absent — every meeting should end up with a Participants value.
Step 8: Offer to commit
See /commit. Skip when called as part of a sequence (e.g. /meeting wrap).
Important Notes
- Always read a file before editing it — frontmatter may have been modified by Obsidian sync.
- The
modified: timestamp in frontmatter changes frequently; use other properties as unique anchors for StrReplace.
- Batch edits where possible to minimize round-trips, but never edit a file without reading it first.
- Interview notes use the co-interviewer (not the candidate) as Participants. If it was a solo interview, use
[[@Me]].
- This workspace may not be a git repo. If
git status fails, skip the commit step entirely without error.