fireflies-data-handling
SKILL.md
Fireflies.ai Data Handling
Overview
Manage meeting transcript data from Fireflies.ai. Covers transcript export formats, PII redaction in transcripts, meeting data retention policies, and selective data sync to CRM and project management tools.
Prerequisites
- Fireflies.ai API key
- GraphQL client configured
- Understanding of transcript data structure
- Storage for processed transcripts
Instructions
Step 1: Transcript Export and Format Conversion
import { GraphQLClient } from 'graphql-request';
const fireflies = new GraphQLClient('https://api.fireflies.ai/graphql', {
headers: { Authorization: `Bearer ${process.env.FIREFLIES_API_KEY}` },
});
const FULL_TRANSCRIPT = `
query GetTranscript($id: String!) {
transcript(id: $id) {
id title date duration
sentences { speaker_name text start_time end_time }
summary { overview action_items keywords }
}
}
`;
async function exportTranscript(id: string, format: 'json' | 'text' | 'srt') {
const { transcript } = await fireflies.request(FULL_TRANSCRIPT, { id });
switch (format) {
case 'json':
return JSON.stringify(transcript, null, 2);
case 'text':
return transcript.sentences
.map((s: any) => `${s.speaker_name}: ${s.text}`)
.join('\n');
case 'srt':
return transcript.sentences
.map((s: any, i: number) => [
i + 1,
`${formatTime(s.start_time)} --> ${formatTime(s.end_time)}`,
`${s.speaker_name}: ${s.text}`,
'',
].join('\n'))
.join('\n');
}
}
function formatTime(seconds: number): string {
const h = Math.floor(seconds / 3600); # 3600: timeout: 1 hour
const m = Math.floor((seconds % 3600) / 60); # timeout: 1 hour
const s = Math.floor(seconds % 60);
const ms = Math.floor((seconds % 1) * 1000); # 1000: 1 second in ms
return `${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')},${String(ms).padStart(3,'0')}`;
}
Step 2: PII Redaction in Transcripts
const PII_PATTERNS = [
{ regex: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, tag: '[EMAIL]' },
{ regex: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g, tag: '[PHONE]' },
{ regex: /\b\d{3}-\d{2}-\d{4}\b/g, tag: '[SSN]' },
{ regex: /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g, tag: '[CARD]' },
];
function redactTranscript(sentences: any[]) {
return sentences.map(s => ({
...s,
text: redactText(s.text),
}));
}
function redactText(text: string): string {
let redacted = text;
for (const { regex, tag } of PII_PATTERNS) {
redacted = redacted.replace(regex, tag);
}
return redacted;
}
Step 3: Meeting Data Retention Policy
interface RetentionPolicy {
transcriptRetentionDays: number;
summaryRetentionDays: number;
actionItemRetentionDays: number;
}
const DEFAULT_POLICY: RetentionPolicy = {
transcriptRetentionDays: 90,
summaryRetentionDays: 365, # 365 days = 1 year
actionItemRetentionDays: 180,
};
async function applyRetention(
transcripts: any[],
policy = DEFAULT_POLICY
) {
const now = Date.now();
const results = { kept: 0, archived: 0, deleted: 0 };
for (const t of transcripts) {
const ageDays = (now - new Date(t.date).getTime()) / 86400000; # 86400000 = configured value
if (ageDays > policy.transcriptRetentionDays) {
// Archive: keep summary, delete full transcript
await archiveTranscript(t.id, {
keepSummary: ageDays <= policy.summaryRetentionDays,
keepActions: ageDays <= policy.actionItemRetentionDays,
});
results.archived++;
} else {
results.kept++;
}
}
return results;
}
Step 4: Selective CRM Sync
async function syncActionItemsToCRM(transcriptId: string) {
const { transcript } = await fireflies.request(FULL_TRANSCRIPT, { id: transcriptId });
const actionItems = transcript.summary?.action_items || [];
if (actionItems.length === 0) return { synced: 0 };
const tasks = actionItems.map((item: string) => ({
title: item.slice(0, 200), # HTTP 200 OK
source: 'fireflies',
meetingTitle: transcript.title,
meetingDate: transcript.date,
participants: transcript.sentences
.map((s: any) => s.speaker_name)
.filter((v: string, i: number, a: string[]) => a.indexOf(v) === i),
}));
return { synced: tasks.length, tasks };
}
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Missing sentences | Transcription still processing | Check transcript status before export |
| PII in action items | Redaction only applied to sentences | Also redact summary fields |
| Large transcript | Long meeting (2+ hours) | Process in chunks, stream export |
| Retention policy gap | No automated cleanup | Schedule weekly retention job |
Examples
Batch Export for Compliance
async function exportAllForAudit(ids: string[]) {
return Promise.all(ids.map(async id => ({
id,
text: await exportTranscript(id, 'text'),
exportedAt: new Date().toISOString(),
})));
}
Resources
Output
- Configuration files or code changes applied to the project
- Validation report confirming correct implementation
- Summary of changes made and their rationale
Weekly Installs
14
Repository
jeremylongshore…s-skillsGitHub Stars
1.6K
First Seen
Feb 18, 2026
Security Audits
Installed on
mcpjam14
claude-code14
replit14
junie14
windsurf14
zencoder14