
Agency Docs Updater
- 51 installs
- 339 repo stars
- Updated August 4, 2026
- glebis/claude-skills
Run an end-to-end pipeline that finds a Fathom transcript, uploads the lab-meeting video to YouTube, and generates MDX docs for deployment.
About
An end-to-end pipeline that publishes Claude Code lab meetings by finding/creating a Fathom transcript, downloading video, uploading to YouTube, generating a fact-checked Russian summary, and creating MDX docs. A developer uses it to replace 5+ manual steps in publishing recorded meetings.
- Chains Fathom transcript, YouTube upload, summary, and MDX doc generation
- Single invocation runs the full sequence and only pauses on unrecoverable failure
Agency Docs Updater by the numbers
- 51 all-time installs (skills.sh)
- Ranked #1,075 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/glebis/claude-skills --skill agency-docs-updaterAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 51 |
|---|---|
| repo stars | ★ 339 |
| Last updated | August 4, 2026 |
| Repository | glebis/claude-skills ↗ |
What it does
Run an end-to-end pipeline that finds a Fathom transcript, uploads the lab-meeting video to YouTube, and generates MDX docs for deployment.
Files
Agency Docs Updater — End-to-End Pipeline
When this skill is invoked, execute ALL steps below automatically in sequence. Do not stop to ask for confirmation between steps — run the full pipeline. Only pause if a step fails and cannot be recovered.
Step 1: Find Fathom Transcript
DATE=$(date +%Y%m%d)Look for ~/Brains/brain/${DATE}-claude-code-lab-02.md. If it exists, read it and extract share_url and fathom_id from its YAML frontmatter.
If the file does NOT exist: 1. Run ~/.claude/skills/calendar-sync/sync.sh to sync today's calendar 2. Re-check for the file 3. If still missing, stop and report the issue
Store these variables for later steps:
FATHOM_FILE= full path to transcript (e.g.~/Brains/brain/20260207-claude-code-lab-02.md)SHARE_URL= theshare_urlfrom frontmatterMEETING_TITLE= thetitlefrom frontmatter (e.g. "Claude Code Lab 03 — Meeting 01: Знакомство и введение")DATE= YYYYMMDD stringVIDEO_NAME=${DATE}-claude-code-lab-02LAB_NUMBER= lab number from filename (e.g.03)MEETING_NUMBER= meeting number from title or determined in Step 5 (e.g.01)
Step 2: Download Video from Fathom
First check if ~/Brains/brain/${VIDEO_NAME}.mp4 already exists and is > 1MB. If so, skip this step.
Otherwise:
cd ~/Brains/brain && python3 ~/.claude/skills/fathom/scripts/download_video.py \
"${SHARE_URL}" --output-name "${VIDEO_NAME}"After download, verify the mp4 exists and is > 1MB:
ls -la ~/Brains/brain/${VIDEO_NAME}.mp4If download fails, stop and report. This is a long-running operation (may take several minutes for a 2h video).
Step 3: Upload to YouTube via videopublish
Prerequisites check (run before first invocation):
cd ~/ai_projects/youtube-uploader && node -e "require('playwright')" 2>/dev/null || (npm install playwright && npx playwright install chromium)cd ~/ai_projects/youtube-uploader && \
python3 process_video.py \
--video ~/Brains/brain/${VIDEO_NAME}.mp4 \
--fathom-transcript ${FATHOM_FILE} \
--title "${MEETING_TITLE}" \
--uploadKey notes:
- Always pass `--title` with the
titlefrom the Fathom transcript frontmatter. Without it, the LLM generates a generic/wrong title (e.g. "Клод Код Лаб" instead of the proper meeting name) - Do NOT use `source venv/bin/activate` — youtube-uploader has no venv, run python3 directly
--fathom-transcriptmakes it skip video transcription (uses Fathom transcript instead)--uploadtriggers YouTube + Yandex.Disk upload- Handles: metadata generation, thumbnail creation, YouTube upload, Yandex upload
- Thumbnail generation requires
playwrightnpm package and Chromium browser
Extract YouTube URL from stdout — look for the line:
✓ YouTube video: https://www.youtube.com/watch?v=VIDEO_IDIf not found in stdout, check the metadata JSON:
cat ~/ai_projects/youtube-uploader/processed/metadata/${VIDEO_NAME}.jsonStore YOUTUBE_URL for the next steps.
This step is long-running (10-30 minutes depending on upload speed). Run in background with run_in_background: true.
If the upload fails or stalls mid-way, resume from the upload step only (skips metadata/thumbnail regeneration):
python3 process_video.py --video ~/Brains/brain/${VIDEO_NAME}.mp4 \
--fathom-transcript ${FATHOM_FILE} --title "${MEETING_TITLE}" --upload --resume-from uploadParallelization: Start Step 4 (summary generation) while Step 3 upload runs in background. The summary does not depend on the YouTube URL.
Step 4: Generate Fact-Checked Russian Summary
Read the full Fathom transcript from ${FATHOM_FILE}.
Generate a comprehensive Russian-language summary of the meeting with these requirements:
- Structured with
##section headers - Bullet points for key concepts
- Code examples where relevant (keep code/paths in English)
- All technical terms in English (MCP, Skills, Claude Code, YOLO, vibe coding, etc.)
- Comprehensive enough to serve as meeting notes
- Exclude personal scheduling details (e.g. "X will be on vacation next week") — only include content relevant to the meeting topic itself
Then use the Task tool with claude-code-guide subagent to fact-check all Claude Code feature claims in the summary:
Launch claude-code-guide agent to fact-check this summary about Claude Code features.
Verify:
- Subagent types and their capabilities
- Tool names and parameters
- Feature availability and limitations
- Best practices mentioned
Correct any inaccuracies.After fact-checking, save the corrected summary to the scratchpad directory as summary.md.
Step 4b: Update YouTube Video Description
Do this after both Step 3 (upload) and Step 4 (summary) are complete.
The description generated by process_video.py's built-in LLM (Groq) is generic and low-quality for Russian content. Instead, generate the YouTube description yourself using the summary from Step 4.
Determine the meeting page URL: https://agency-lab.glebkalinin.com/docs/claude-code-internal-XX/meetings/NN (where XX = lab number, NN = meeting number).
Generate a YouTube description in this format:
${MEETING_TITLE}
[1-2 sentence overview of the meeting in Russian]
В этом видео:
- [bullet point 1 — key topic covered]
- [bullet point 2]
- ...
- [bullet point 8-10 max]
Материалы и конспект занятия:
https://agency-lab.glebkalinin.com/docs/claude-code-internal-XX/meetings/NN
Сообщество AGENCY — практики AI-агентов:
https://agency-lab.glebkalinin.com
#ClaudeCode #AI #Anthropic #Claude #AIагенты #программированиеThen update the video on YouTube using the API via auth.py (which manages token.pickle with youtube.force-ssl scope):
cd ~/ai_projects/youtube-uploader && PYTHONPATH=. python3 -c "
from auth import get_authenticated_service
youtube = get_authenticated_service()
resp = youtube.videos().list(part='snippet', id='VIDEO_ID').execute()
snippet = resp['items'][0]['snippet']
snippet['title'] = MEETING_TITLE
snippet['description'] = DESCRIPTION
snippet['tags'] = ['Claude Code', 'Claude', 'Anthropic', 'AI', 'AI агенты', 'программирование', 'Claude Code Lab', 'MCP']
youtube.videos().update(part='snippet', body={'id': 'VIDEO_ID', 'snippet': snippet}).execute()
"Key notes:
auth.pyusesyoutube.force-sslscope which covers both uploads and metadata updatestoken.picklepersists across sessions — no browser auth needed after initial setup- If token expires,
auth.pyauto-refreshes it - Extract
VIDEO_IDfromYOUTUBE_URL - Generate the bullet points from the summary content, not from the transcript directly
Add video to playlist — after updating metadata, add the video to the lab's playlist:
cd ~/ai_projects/youtube-uploader && PYTHONPATH=. python3 -c "
from auth import get_authenticated_service
youtube = get_authenticated_service()
# Find playlist matching 'Claude Code Lab XX'
resp = youtube.playlists().list(part='snippet', mine=True, maxResults=50).execute()
playlist_id = None
for p in resp['items']:
if p['snippet']['title'] == 'Claude Code Lab LAB_NUMBER':
playlist_id = p['id']
break
if playlist_id:
youtube.playlistItems().insert(part='snippet', body={
'snippet': {
'playlistId': playlist_id,
'resourceId': {'kind': 'youtube#video', 'videoId': 'VIDEO_ID'}
}
}).execute()
print(f'Added to playlist: {playlist_id}')
else:
print('Playlist not found — create it manually on YouTube first')
"Known playlist IDs (for reference):
- Claude Code Lab 03:
PLZNP0SKU2Sqic4njcSQemmyrVLHZ4C_iT - Claude Code Lab 02:
PLZNP0SKU2SqizoM9_7jMjgae2cvjGN9bQ - Claude Code Lab:
PLZNP0SKU2Sqga_EjxAW_OxnqaUk1ZGfXU
Replace LAB_NUMBER with the two-digit lab number (e.g. 03). The playlist name must match exactly (e.g. "Claude Code Lab 03").
Step 5: Run update_meeting_doc.py
python3 ~/.claude/skills/agency-docs-updater/scripts/update_meeting_doc.py \
${FATHOM_FILE} \
"${YOUTUBE_URL}" \
${SCRATCHPAD}/summary.mdThe script auto-detects:
- Lab number from filename (
claude-code-lab-XX->XX) - Target docs dir:
~/Sites/agency-docs/content/docs/claude-code-internal-XX/ - Next meeting number from existing files in
meetings/ - Presentation files from
~/ai_projects/claude-code-lab/presentations/lab-XX/ - Summary language (auto-translates to Russian if needed)
IMPORTANT: Meeting number detection — The script picks the next available number, but placeholder MDX files may already exist for future meetings with dates pre-filled. Before using the script's auto-detected number: 1. List existing MDX files in meetings/ 2. Check if any placeholder file already has today's date in its content (e.g. grep -l "14 февраля" meetings/*.mdx) 3. If a placeholder exists for today's date, use --update flag or -n NN to target that file instead of creating a new one
Output: MDX file at ~/Sites/agency-docs/content/docs/claude-code-internal-XX/meetings/NN.mdx
After the script runs, post-process the generated MDX:
1. Strip appended presentation content: The script appends Marp presentation markdown from presentations/lab-XX/ which contains HTML comments (<!-- _class: lead -->) that break MDX compilation. Remove everything after the summary section (after the last --- separator following the summary). The MDX should only contain: frontmatter, video section, and summary.
2. Copy lesson HTML to public: If ~/ai_projects/claude-code-lab/lesson-generator/${DATE}.html exists, copy it to ~/Sites/agency-docs/public/${DATE}-claude-code-lab-XX.html (where XX is the lab number). Then add a link in the MDX video section:
**Материалы:** [Презентация занятия](/${DATE}-claude-code-lab-XX.html)3. Replace frontmatter placeholders:
[Название встречи]-> actual meeting title derived from transcript content[Краткое описание встречи]-> brief description[Дата встречи]-> formatted date from the transcript
4. Verify build locally before committing:
cd ~/Sites/agency-docs && npm run build 2>&1 | tail -5If build fails, fix the MDX (common issues: HTML comments, unescaped < or { characters) and retry.
Step 6: Commit and Push
cd ~/Sites/agency-docs && git add . && git commit -m "Add meeting NN" && git pushReplace NN with the actual meeting number from Step 5 output.
This triggers Vercel deployment automatically.
Step 7: Verify Vercel Deployment
Wait ~90 seconds after push, then check deployment status:
gh api repos/glebis/agency-docs/commits/COMMIT_HASH/status --jq '{state, total_count}'
gh api repos/glebis/agency-docs/commits/COMMIT_HASH/statuses --jq '.[0] | {state, description}'- If
state: success— deployment is live. - If
state: failure— check the build error locally withcd ~/Sites/agency-docs && npm run build 2>&1 | tail -20, fix, and re-push. - If
state: pending— wait another 60 seconds and re-check.
Pipeline Summary
After completion, report: 1. Fathom transcript path 2. Downloaded video path 3. YouTube URL 4. Generated MDX path 5. Git commit hash 6. Vercel deployment status (success/failure)
Error Recovery
- Step 1 fail (no transcript): Run calendar-sync, retry once. If still missing, stop.
- Step 2 fail (download): Check if share_url is valid. Report ffmpeg errors.
- Step 3 fail (upload): Check YouTube OAuth tokens, Playwright installation. Report specific error. Do NOT try
source venv/bin/activate. - Step 4 fail (summary): Proceed with English summary if Russian generation fails.
- Step 5 fail (MDX): Check that fathom_url exists in frontmatter. Check docs_dir exists.
- Step 6 fail (git): Report conflict details. Do not force-push.
Reference: CLI Interfaces
download_video.py
python3 download_video.py <share_url> --output-name <name_without_ext>Downloads to current directory as <name>.mp4.
process_video.py
python3 process_video.py --video <path> --fathom-transcript <path> --uploadFlags: --upload (YouTube+Yandex), --yandex-only, --skip-thumbnail, --language <code>, --title <override>.
update_meeting_doc.py
python3 update_meeting_doc.py <fathom_file> <youtube_url> <summary_file> [-n NN] [-l ru|en|auto] [--update]Learnings
2026-02-07
Context: First full pipeline run for meeting 08
What Worked:
--resume-from uploadavoids re-generating metadata/thumbnails on upload retry- Parallelizing summary (Step 4) with YouTube upload (Step 3) saves 10+ minutes
gh api repos/OWNER/REPO/commits/HASH/statusreliably checks Vercel deploy status- Local
npm run buildcatches MDX errors before pushing
What Failed:
- YouTube upload speed degraded from 5.4 MB/s to 0.15 MB/s mid-upload (3 attempts needed)
update_meeting_doc.pyappended lab-01 Marp presentation with<!-- -->comments — broke MDX build- Pushed without local build check — caused Vercel deploy failure, required fix commit
Known Issues:
presentations/lab-XX/may contain presentations from wrong meetings — always strip appended content- YouTube API upload speed is highly variable and not controllable from client side
- MDX does not support HTML comments (
<!-- -->), unescaped<, or bare{characters
2026-02-14
Context: Pipeline run for meeting 10 (Agent SDK workshop)
What Worked:
- Parallelizing summary with YouTube upload continues to save significant time
- Date-matching existing placeholder MDX files correctly identifies target meeting number
- Local
npm run buildcaught issues before push
What Failed: 1. venv activation — source venv/bin/activate fails because youtube-uploader has no venv. Fixed: run python3 directly 2. Playwright missing — ERR_MODULE_NOT_FOUND: Cannot find package 'playwright' during thumbnail generation. Fixed: added prerequisite check in Step 3 3. Wrong meeting number — update_meeting_doc.py auto-detected meeting 13 (next available), but meeting 10 was a placeholder for today's date. Fixed: added date-matching guidance in Step 5 4. Personal scheduling details in summary — "X will be on vacation" included in published summary. Fixed: added exclusion rule in Step 4 5. Appended Marp content — still happens despite being documented. Reinforced in Step 5 post-processing
Key Fix: Always check existing MDX files by date content before trusting auto-detected meeting number. Use -n NN flag to override.
2026-03-04
Context: Pipeline run for Lab 03, Meeting 01
What Worked:
- Full pipeline completed successfully (transcript, download, upload, summary, MDX, deploy)
- Fathom recorded as "Impromptu Zoom Meeting" — found by date, renamed correctly
What Failed: 1. Wrong YouTube title — Without --title flag, LLM generated "Клод Код Лаб" instead of proper meeting name. Fixed: added --title "${MEETING_TITLE}" to Step 3 using frontmatter title 2. YouTube OAuth scope too narrow — youtube.upload scope can't update video metadata (title/description) after upload. Needed youtube.force-ssl scope for videos().update() call 3. Appended Marp content — Still happens (3rd time). Truncation via Edit tool only replaced first match, leaving 1100+ lines of Marp. Fixed: rewrote entire file with Write tool
Key Fix: Always pass --title from Fathom frontmatter title field to process_video.py. The LLM metadata generator produces poor/generic titles for Russian-language content.
#!/usr/bin/env python3
"""
Update agency-docs meeting documentation.
Creates/updates meeting MDX files with Fathom links, YouTube embeds, fact-checked summaries, and presentations.
"""
import os
import sys
import re
import json
import argparse
from pathlib import Path
from typing import Dict, Optional
def parse_fathom_frontmatter(fathom_file: str) -> Dict:
"""Extract Fathom meeting URL and metadata from frontmatter."""
with open(fathom_file, 'r', encoding='utf-8') as f:
content = f.read()
# Parse frontmatter
parts = content.split('---')
if len(parts) < 3:
raise ValueError("Invalid Fathom transcript format - missing frontmatter")
frontmatter = parts[1].strip()
metadata = {}
for line in frontmatter.split('\n'):
if ':' in line:
key, value = line.split(':', 1)
metadata[key.strip()] = value.strip().strip('"\'[]')
return metadata
def extract_lab_number(fathom_file: str) -> str:
"""Extract lab number from Fathom transcript filename."""
# Pattern: YYYYMMDD-claude-code-lab-XX.md
filename = os.path.basename(fathom_file)
match = re.search(r'claude-code-lab-(\d+)', filename)
if not match:
raise ValueError(f"Could not extract lab number from filename: {filename}")
return match.group(1).zfill(2)
def find_presentation_file(lab_number: str) -> Optional[str]:
"""Find presentation markdown for lab number."""
presentations_dir = Path.home() / 'ai_projects' / 'claude-code-lab' / 'presentations' / f'lab-{lab_number}'
if not presentations_dir.exists():
print(f"⚠️ Presentations directory not found: {presentations_dir}")
return None
# Find latest .md file (not .html)
md_files = sorted(presentations_dir.glob('*.md'), key=lambda p: p.stat().st_mtime, reverse=True)
# Filter out homework-prompt.md
md_files = [f for f in md_files if 'homework-prompt' not in f.name.lower()]
if md_files:
return str(md_files[0])
print(f"⚠️ No presentation markdown found in {presentations_dir}")
return None
def determine_meeting_number(docs_dir: str) -> str:
"""Determine next meeting number from existing files."""
meetings_dir = Path(docs_dir) / 'meetings'
if not meetings_dir.exists():
return "01"
# Find all XX.mdx files
existing = [f.stem for f in meetings_dir.glob('*.mdx') if f.stem.isdigit()]
if not existing:
return "01"
# Return max + 1
max_num = max(int(n) for n in existing)
return str(max_num + 1).zfill(2)
def create_meeting_doc(
meeting_number: str,
fathom_url: str,
youtube_url: str,
summary: str,
presentation_content: Optional[str],
docs_dir: str
) -> str:
"""Create meeting MDX document."""
# Extract YouTube video ID
youtube_id = youtube_url.split('/')[-1].split('?v=')[-1].split('&')[0]
# Build content
content = f"""---
title: "Встреча {meeting_number}: [Название встречи]"
description: [Краткое описание встречи]
---
**Дата:** [Дата встречи] | **Длительность:** ~2 часа
## Видео
**Fathom:** [Запись на Fathom]({fathom_url})
**YouTube:** [Смотреть на YouTube]({youtube_url})
<iframe width="560" height="315" src="https://www.youtube.com/embed/{youtube_id}" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
---
## Краткое содержание
{summary}
---
"""
# Append presentation if available
if presentation_content:
# Remove frontmatter from presentation
presentation_lines = presentation_content.split('\n')
if presentation_lines[0].strip() == '---':
# Find end of frontmatter
end_idx = presentation_lines[1:].index('---') + 2 if '---' in presentation_lines[1:] else 0
presentation_content = '\n'.join(presentation_lines[end_idx:]).strip()
content += f"\n{presentation_content}\n"
# Write file
output_file = Path(docs_dir) / 'meetings' / f'{meeting_number}.mdx'
output_file.parent.mkdir(parents=True, exist_ok=True)
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
return str(output_file)
def detect_language(text: str) -> str:
"""Detect if text is primarily Russian or English."""
# Count Cyrillic characters
cyrillic_count = sum(1 for char in text if '\u0400' <= char <= '\u04FF')
total_alpha = sum(1 for char in text if char.isalpha())
if total_alpha == 0:
return 'en'
cyrillic_ratio = cyrillic_count / total_alpha
return 'ru' if cyrillic_ratio > 0.3 else 'en'
def translate_summary_to_russian(summary: str) -> str:
"""Translate English summary to Russian using Task agent."""
import subprocess
import tempfile
print("⚙️ Translating summary to Russian...")
# Create temp file with translation prompt
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False, encoding='utf-8') as f:
f.write(summary)
temp_input = f.name
try:
# Use claude to translate
result = subprocess.run([
'claude', '-p',
f'''Translate this meeting summary to Russian. Keep all technical terms in English (MCP, Skills, Claude Code, YOLO, vibe coding, etc.). Preserve all markdown formatting, code examples, paths, and table structures.
Input file: {temp_input}
Output the translated text directly.''',
'--output-format', 'text'
], capture_output=True, text=True, encoding='utf-8')
if result.returncode == 0:
return result.stdout.strip()
else:
print(f"⚠️ Translation failed: {result.stderr}")
return summary
finally:
os.unlink(temp_input)
def main():
parser = argparse.ArgumentParser(
description='Update agency-docs meeting documentation',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''
Examples:
# Auto-detect meeting number and language
python3 update_meeting_doc.py transcript.md https://youtube.com/watch?v=abc summary.md
# Specify meeting number
python3 update_meeting_doc.py transcript.md https://youtube.com/watch?v=abc summary.md -n 07
# Force Russian translation
python3 update_meeting_doc.py transcript.md https://youtube.com/watch?v=abc summary.md -l ru
# Update existing meeting with new summary
python3 update_meeting_doc.py transcript.md https://youtube.com/watch?v=abc summary.md -n 07 --update
'''
)
parser.add_argument('fathom_transcript', help='Path to Fathom transcript markdown file')
parser.add_argument('youtube_url', help='YouTube video URL')
parser.add_argument('summary_file', help='Path to summary markdown file')
parser.add_argument('docs_dir', nargs='?', help='Target docs directory (optional, auto-detected)')
parser.add_argument('-n', '--meeting-number', help='Specific meeting number (e.g., 07)')
parser.add_argument('-l', '--language', choices=['en', 'ru', 'auto'], default='auto',
help='Summary language (auto-detect, en, or ru)')
parser.add_argument('--update', action='store_true',
help='Update existing meeting file instead of creating new')
args = parser.parse_args()
# Parse Fathom frontmatter
print(f"Parsing Fathom transcript: {args.fathom_transcript}")
metadata = parse_fathom_frontmatter(args.fathom_transcript)
fathom_url = metadata.get('meeting_url', metadata.get('url', metadata.get('fathom_url', '')))
if not fathom_url:
print("⚠️ Could not find Fathom URL in frontmatter (looking for 'meeting_url', 'url', or 'fathom_url')")
sys.exit(1)
# Extract lab number
lab_number = extract_lab_number(args.fathom_transcript)
print(f"✓ Detected lab number: {lab_number}")
# Determine docs directory
docs_dir = args.docs_dir
if not docs_dir:
docs_dir = str(Path.home() / 'Sites' / 'agency-docs' / 'content' / 'docs' / f'claude-code-internal-{lab_number}')
print(f"✓ Target docs directory: {docs_dir}")
# Determine meeting number
if args.meeting_number:
meeting_number = args.meeting_number.zfill(2)
print(f"✓ Using specified meeting number: {meeting_number}")
# Check if file exists
meeting_file = Path(docs_dir) / 'meetings' / f'{meeting_number}.mdx'
if meeting_file.exists() and not args.update:
print(f"⚠️ Meeting file already exists: {meeting_file}")
print(" Use --update flag to update existing file, or omit -n to create new meeting")
sys.exit(1)
else:
meeting_number = determine_meeting_number(docs_dir)
print(f"✓ Auto-detected meeting number: {meeting_number}")
# Find presentation
presentation_file = find_presentation_file(lab_number)
presentation_content = None
if presentation_file:
print(f"✓ Found presentation: {presentation_file}")
with open(presentation_file, 'r', encoding='utf-8') as f:
presentation_content = f.read()
else:
print("ℹ️ No presentation found, continuing without")
# Read summary
with open(args.summary_file, 'r', encoding='utf-8') as f:
summary = f.read()
# Handle language detection and translation
detected_lang = detect_language(summary)
target_lang = args.language if args.language != 'auto' else 'ru' # Default to Russian
print(f"✓ Detected summary language: {detected_lang}")
print(f"✓ Target language: {target_lang}")
if detected_lang != target_lang and target_lang == 'ru':
summary = translate_summary_to_russian(summary)
# Create meeting doc
output_file = create_meeting_doc(
meeting_number,
fathom_url,
args.youtube_url,
summary,
presentation_content,
docs_dir
)
action = "Updated" if args.update else "Created"
print(f"\n✓ {action} meeting documentation: {output_file}")
print(f"\nNext steps:")
print(f" 1. Edit title and description in frontmatter")
print(f" 2. cd {Path(docs_dir).parent.parent.parent}")
print(f" 3. git add . && git commit -m '{action} meeting {meeting_number} documentation'")
print(f" 4. git push")
print(f" 5. Check Vercel deploy logs")
if __name__ == '__main__':
main()