Extract Action Items
Extract action items from a Fireflies transcript using parallel subagents. Catches items automated summaries miss.
Two modes:
All attendees (default):
No target specified — extract action items for every participant
Single person:
Target specified — extract action items for that person only
Phase 1: Determine Mode
Parse the user's invocation:
If a target person is specified →
single-person mode
Otherwise →
all-attendees mode
Extract the search criteria (date, keyword, or transcript ID) from the invocation.
Phase 2: Fetch & Preprocess (Subagent)
The transcript API returns a JSON array (or an MCP wrapper containing one). Extract to plain text before chunking.
You should inspect the user's local hooks config and avoid running commands that are blocked by the hooks.
MCP based extraction
mkdir
-p
.claude/scratchpad
node
-e
"
const fs = require('fs');
let data = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));
// Handle MCP wrapper: if top-level array has a .text field containing the real transcript, parse that
if (data.length === 1 && typeof data[0]?.text === 'string') {
// Extract speaker lines from the text content
const lines = data[0].text.split('
\n
').filter(l => l.match(/^[A-Za-z].?:/));
fs.writeFileSync('.claude/scratchpad/transcript.txt', lines.join('
\n
'));
const speakers = [...new Set(lines.map(l => l.split(':')[0].trim()))].sort();
console.log('Speakers:', JSON.stringify(speakers));
console.log('Total lines:', lines.length);
} else {
// Standard array of {speaker_name, text} objects
const lines = data.map(e => (e.speaker_name || 'Unknown') + ': ' + (e.text || ''));
fs.writeFileSync('.claude/scratchpad/transcript.txt', lines.join('
\n
'));
const speakers = [...new Set(data.map(e => e.speaker_name).filter(Boolean))].sort();
console.log('Speakers:', JSON.stringify(speakers));
console.log('Total lines:', lines.length);
}
"
[
TRANSCRIPT_JSON_FILE
]
If the transcript JSON was saved to a tool-results file by the MCP client, pass that file path as the argument.
API based extraction
CRITICAL: The orchestrator MUST NOT call any Fireflies MCP tools directly. ALL Fireflies interaction happens inside this subagent.
Launch a single
general-purpose
subagent with this prompt:
Search Fireflies for a transcript matching: [SEARCH_CRITERIA]
1. Call mcp__fireflies__fireflies_get_transcripts to find the transcript (by date, keyword, or ID).
2. Call mcp__fireflies__fireflies_get_summary and mcp__fireflies__fireflies_get_transcript in parallel for the matched transcript.
3. The transcript API returns a JSON array. Extract to plain text:
- With jq: jq -r '.[].text' < raw_transcript.json > .claude/scratchpad/transcript.txt
- Fallback: python3 -c "import json,sys; print('\n'.join(e['text'] for e in json.load(sys.stdin)))" < raw_transcript.json > .claude/scratchpad/transcript.txt
4. Count lines: wc -l < .claude/scratchpad/transcript.txt
5. Extract the distinct speaker list from the transcript JSON:
python3 -c "import json,sys; data=json.load(sys.stdin); print('\n'.join(sorted(set(e.get('speaker_name','') for e in data if e.get('speaker_name')))))" < raw_transcript.json
Return EXACTLY this (no other text):
- meeting_title:
[Name] Action Items — [Meeting Title] ** Date: ** [Date] ** Fireflies Link: ** https://app.fireflies.ai/view/[TRANSCRIPT_ID]
[Category Name]
[ ] ** Item title ** - Context and details -
"Exact quote"
Quick Reference — Time-Sensitive 1. [Item with deadline or scheduled time] All-attendees mode — Write to .claude/scratchpad/action-items-YYYY-MM-DD.md :
Action Items — [Meeting Title] ** Date: ** [Date] ** Fireflies Link: ** https://app.fireflies.ai/view/[TRANSCRIPT_ID]
[Person Name]
[Category Name]
[ ] ** Item title ** - Context and details -
"Exact quote"
Quick Reference — Time-Sensitive 1. [Person] — [Item with deadline or scheduled time] Phase 5: Review & DM to Slack Use AskUserQuestion : "DM action items to each person on Slack?" — options: "Send DMs", "Skip — just keep the file" If approved, ensure .claude/slack-users.local.json exists in the project root: If missing , run node [SKILL_DIR]/scripts/fetch-slack-users.mjs (requires SLACK_BOT_TOKEN with users:read scope), present the output to the user for review, then save to .claude/slack-users.local.json (gitignored by /.claude//*.local.json ) If present , proceed directly Run the bundled script with the output file path: node [ SKILL_DIR ] /scripts/slack-post.mjs [ OUTPUT_FILE_PATH ] The script sends Block Kit–formatted DMs to each person via conversations.open + chat.postMessage . Requires env var SLACK_BOT_TOKEN (with chat:write and im:write scopes). Behavior by mode: All-attendees: Each person matched in slack-users.local.json receives a DM with only their action items. Unresolvable names are skipped with a warning. Single-person: One DM to the target person. Name resolution supports exact match and fuzzy first-name match (e.g., "Jelvin" resolves to "Jelvin Base"). After the script runs, report any skipped names to the user. After posting (or skipping), delete all artifacts created during the run: transcript.txt , the action items markdown file, and any other temp files written to .claude/scratchpad/ during this workflow. Example Invocations /extract-my-action-items — all attendees, most recent meeting /extract-my-action-items standup — all attendees, search for "standup" /extract-my-action-items for Basti from yesterday — single person /extract-my-action-items 01KFY1RSEVVQW7MB1TKG4N2D20 — all attendees, specific transcript