From youtube-analyzer
Analyze YouTube videos with content-type detection, multi-agent transcript chunking, optional GitHub repo exploration, and structured markdown output. Use when the user asks to "analyze a YouTube video", "summarize this video", "extract insights from a tutorial", or pastes a YouTube URL with intent to analyze.
How this skill is triggered — by the user, by Claude, or both
Slash command
/youtube-analyzer:youtube-analyzerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Purpose:** Comprehensive YouTube video analysis with content-type detection, specialized format workflows (tutorial/finance/general/etc.), multi-agent orchestration for long videos, and optional GitHub repo cross-referencing for tutorial content.
Purpose: Comprehensive YouTube video analysis with content-type detection, specialized format workflows (tutorial/finance/general/etc.), multi-agent orchestration for long videos, and optional GitHub repo cross-referencing for tutorial content.
Architecture: This file is the orchestration spine — 4 phases with blocking gates. Mechanical detail is progressively disclosed via references/*.md (loaded by phase) and content-analysis rules live in workflows/*.md (passed into sub-agents).
| File | Read when |
|---|---|
references/source-selection.md | Starting Phase 1 |
references/scaling-and-repo-explore.md | Starting Phase 3 |
references/output-paths.md | Phase 4 Step 4.5, only if mode == "document" |
references/output-templates.md | Phase 4 Step 4.3, passed into synthesis agent |
content-types.md | Phase 2 Q1, when detection confidence < 60% |
workflows/<format>-workflow.md | Phase 4 Step 4.1, passed into chunk agents |
package-database-schema.md | Phase 4 Step 4.4, tutorials only |
Parse the user's invocation BEFORE Phase 1. Flags pre-set Phase 2 outputs and suppress the matching prompt.
Syntax accepted (any of these forms):
--chat <url> — deliver inline, no file written--chat: <url> / --chat=<url>--document <url> (explicit; default behavior)| Flag | Effect | Pre-sets |
|---|---|---|
--chat | Skip Q5; deliver analysis inline (no file written) | mode = "chat" |
--document | Skip Q5; save to resolved output directory (default) | mode = "document" |
Parsing rules:
: or =value) before extracting the URLmode and SKIP Q5--foo) → warn user inline, proceed without itWhen a flag was detected, surface it: "Flag detected: --chat → mode preset to chat (Q5 skipped)."
Verify these are installed before Phase 1. If missing, surface a single install message and stop:
yt-dlp — pip install yt-dlp or brew install yt-dlpyoutube_transcript_api — pip install youtube-transcript-apibun — curl -fsSL https://bun.sh/install | bashcommand -v yt-dlp && command -v youtube_transcript_api && command -v bun
BEFORE Phase 1, capture the working directory the user invoked the skill from. Store as invocationCwd. Used by Step 4.7 (post-save copy prompt).
pwd
Persist that value through all phases. Sub-agents may run elsewhere — only the orchestrator's initial cwd counts.
This skill runs from any agent context (the primary thread, or a delegated agent like general-purpose) provided the calling agent has: Agent/Task, AskUserQuestion, Write/Edit, Bash, Read, Grep. Agents lacking any of these (e.g. Explore) should defer — auto-detect via tool availability, not by name.
The terms "the orchestrator" and "the calling agent" both refer to whatever agent is executing this skill.
The orchestrator NEVER does analysis work directly. All content extraction, processing, and writing is delegated to specialized sub-agents via the Task tool. The orchestrator coordinates, routes, and writes files (in mode == "document") once results return.
EVERY phase has a BLOCKING GATE. Do not proceed until the gate checklist is satisfied.
PRE-CONDITIONS: External tools verified
MANDATORY OUTPUTS:
- transcriptPath: string # Path to loaded clean transcript file
- transcriptSource: string # "yt-dlp" | "youtube_transcript_api"
- videoMetadata: object # { title, channel, duration?, upload_date?, video_id?, topic? }
- wordCount: number # Estimated word count
- transcriptQuality: string # "HIGH" | "MEDIUM" | "NONE" | "UNAVAILABLE"
Mechanics: Read references/source-selection.md. It covers URL extraction, the 4-tier transcript fallback chain, and VTT cleanup.
Auto-detect: If the user already provided a YouTube URL, skip the URL prompt and go directly to metadata extraction.
Gate 1 checklist (verify ALL):
transcriptPath exists and is readabletranscriptSource is setvideoMetadata.title and videoMetadata.channel are non-emptywordCount > 0transcriptQuality is set"Phase 1 complete. {wordCount} words loaded from {transcriptSource}. Proceeding to config..."
PRE-CONDITIONS:
- transcriptPath exists and is readable
- videoMetadata is populated (title + channel at minimum)
MANDATORY OUTPUTS:
- category: string # business, finance, technology, etc.
- format: string # tutorial | course | finance | interview | lecture | general
- outputSelection: string[] # Selected output types
- depth: string # "quick" | "standard" | "deep"
- focusArea: string # Format-specific focus (or "none")
- repoUrl: string | null # GitHub repo URL (tutorials only)
- confidence: number # Detection confidence percentage
- mode: string # "document" | "chat" — see Q5 (or pre-set by flag)
Detection: Run the content-type detector with metadata extracted in Phase 1:
bun run ${CLAUDE_PLUGIN_ROOT}/scripts/detect-content-type.ts --url "URL"
# OR pipe metadata JSON
echo '{"title":"...","description":"...","tags":[...]}' | bun run ${CLAUDE_PLUGIN_ROOT}/scripts/detect-content-type.ts --json
If confidence < 60%, present alternatives. See content-types.md for full keyword lists and scoring.
{
"questions": [{
"question": "I detected this as {category}/{format} ({X}% confidence). Is that correct?",
"header": "Content type",
"options": [
{"label": "Yes, proceed", "description": "Use {category}/{format} as detected"},
{"label": "Change category", "description": "Keep {format} format, pick a different category"},
{"label": "Change format", "description": "Keep {category} category, pick a different format"},
{"label": "Change both", "description": "Select both category and format manually"}
],
"multiSelect": false
}]
}
The available options depend on format:
tutorial / course: Detailed Summary · Production Checklist · Tool/Package Inventory · Key Quotes finance: Strategy Breakdown · Action Items · Risk Analysis · Key Quotes general / interview / lecture: Detailed Summary · Deep Analysis · Key Insights · Key Quotes
Default if user says "all" or doesn't specify: Detailed Summary + Key Quotes.
A) Quick (~500w) · B) Standard (~1500w, recommended) · C) Deep dive (~3000w+)
repoUrl)SKIP this question entirely if mode was pre-set by an invocation flag. Otherwise:
{
"questions": [{
"question": "How should the analysis be delivered?",
"header": "Delivery",
"options": [
{"label": "Save to disk", "description": "Default — write a permanent markdown file at the resolved output directory. Best when you want to reference this later."},
{"label": "Discuss in chat", "description": "Run the full analysis but return the rendered markdown inline so we can talk through it. No file is created."}
],
"multiSelect": false
}]
}
Map: Save to disk → mode = "document"; Discuss in chat → mode = "chat". Default: mode = "document".
category is a valid category from content-types.mdformat is one of: tutorial, course, finance, interview, lecture, generaloutputSelection has ≥1 itemdepth is setfocusArea is set (can be "none")repoUrl is a string or nullmode is "document" or "chat""Phase 2 complete. {category}/{format} at {confidence}% confidence. Depth: {depth}. Outputs: {outputSelection}. Mode: {mode}. Proceeding to scaling..."
PRE-CONDITIONS:
- category, format, outputSelection, depth all set
- transcriptPath exists
MANDATORY OUTPUTS:
- partitionStrategy: string # "single" | "multi"
- agentCount: number # 1 for single, 2+ for multi
- chunkPaths: string[] # Chunk file paths
- repoExploreResults: object | null # Mermaid diagrams from repo exploration
Mechanics: Read references/scaling-and-repo-explore.md. It covers token estimation, the scaling decision table (≤30K / 30–100K / >100K), partition execution, and the 3-explorer parallel repo exploration (StructureExplorer, DependencyExplorer, PatternExplorer — all subagent_type: Explore).
Trigger for repo exploration: repoUrl is non-null AND format is tutorial or course. Run in parallel with transcript partitioning.
partitionStrategy is setagentCount ≥ 1chunkPaths has ≥1 path; each path exists and is readablerepoExploreResults is set (object or null)repoUrl was provided, either repoExploreResults has content OR a skip reason is documented"Phase 3 complete. {agentCount} agent(s) ready. {repoExploreResults ? 'Repo exploration complete with Mermaid diagrams.' : ''} Dispatching {format} workflow..."
PRE-CONDITIONS:
- All Gate 3 outputs satisfied
- category, format, outputSelection, depth, focusArea, mode all set
MANDATORY OUTPUTS:
- workflowLoaded: string # Workflow file that was loaded
- outputPath: string | null # Canonical output path (null when mode == "chat")
- renderedMarkdown: string | null # Rendered markdown (populated when mode == "chat")
- copyPath: string | null # Optional cwd copy path from Step 4.7 (null if declined or chat mode)
Final-phase reporting (branch on mode):
If
mode == "document"ANDcopyPathis set: "Analysis complete. Saved to {outputPath}. Copy also at {copyPath}." Ifmode == "document"ANDcopyPathis null: "Analysis complete. Saved to {outputPath}." Ifmode == "chat": "Analysis complete — rendered below for discussion. No file written." Then printrenderedMarkdowninline so it enters the conversation context.
Dispatch table:
| Format | Workflow File | Agent Description | Agent Type | Model |
|---|---|---|---|---|
| tutorial | workflows/tutorial-workflow.md | TutorialAgent | general-purpose | sonnet |
| course | workflows/tutorial-workflow.md | TutorialAgent | general-purpose | sonnet |
| finance | workflows/finance-workflow.md | FinanceAgent | general-purpose | sonnet |
| interview | workflows/general-workflow.md | GeneralAgent | general-purpose | sonnet |
| lecture | workflows/general-workflow.md | GeneralAgent | general-purpose | sonnet |
| general | workflows/general-workflow.md | GeneralAgent | general-purpose | sonnet |
Why general-purpose on sonnet: Workflow agents follow precise file instructions to extract structured data and produce markdown. general-purpose executes workflow instructions directly without loading specialized agent personalities.
Pre-dispatch verification:
subagent_type: "general-purpose" and model: "sonnet" set explicitlyPer chunk, launch a Task agent with subagent_type: "general-purpose", model: "sonnet". Each agent receives:
{ category, format, outputSelection, depth, focusArea }{ title, channel, duration, upload_date, video_id }workflows/*.md)Parallel: if agentCount > 1, launch ALL chunk agents in parallel (single message, multiple Task calls).
Launch ONE synthesis agent (general-purpose, sonnet) with a fresh context. Pass it references/output-templates.md (YAML frontmatter, Production Checklist section, Ground Truth Architecture section, Package Version table) so it can apply the templates without polluting the orchestrator context.
Synthesis agent receives:
mode)repoExploreResults if non-null (Mermaid diagrams)mode == "document"; pass null for chatreferences/output-templates.mdSynthesis agent does:
format + outputSelectionmode == "document" → write file to output path. Return { outputPath, renderedMarkdown: null, wordCount, packagesFound[] }mode == "chat" → skip file write. Return { outputPath: null, renderedMarkdown: <full markdown including frontmatter>, wordCount, packagesFound[] }. Orchestrator prints renderedMarkdown inline.For each package found:
bun run ${CLAUDE_PLUGIN_ROOT}/scripts/package-db.ts add \
--name "{packageName}" --display-name "{displayName}" \
--version-mentioned "{version}" --category "{packageCategory}" \
--source "{videoUrl}"
The package database lives at ~/.config/youtube-analyzer/package-db.json (created on first use).
Version lookup (post-analysis, batches of 5; skip packages checked within 7 days):
WebFetch on https://registry.npmjs.org/{pkg}/latestWebFetch on https://pypi.org/pypi/{pkg}/jsonWebSearchUpdate the package database with --latest-version. Status thresholds and the Package Version table format live in references/output-templates.md. Schema details: package-database-schema.md.
Skip this step entirely when mode == "chat" — set outputPath = null and continue to cleanup.
For mode == "document": read references/output-paths.md. The skill resolves the output directory from ${CLAUDE_PROJECT_DIR}/.claude/youtube-analyzer.local.md if present, otherwise prompts the user once via AskUserQuestion and persists the answer there for next time.
rm -rf "{scratchpad}/repo-explore/"
Skip when mode == "chat" — no file exists to copy. Set copyPath = null.
After the canonical file is written and cleanup is done, ask the user whether to also drop a copy in the cwd captured at skill invocation. Use AskUserQuestion:
{
"questions": [{
"question": "Also save a copy to the project you ran this from? Cwd: {invocationCwd}",
"header": "Copy to repo",
"options": [
{"label": "No, just the configured output dir", "description": "File stays at {outputPath} only. No copy created."},
{"label": "Yes, copy to cwd root", "description": "Drop a copy at {invocationCwd}/{filename}"},
{"label": "Yes, custom subpath", "description": "I'll specify a subdirectory under {invocationCwd}"}
],
"multiSelect": false
}]
}
Branch on response:
copyPath = null. Done.targetDir = invocationCwd. Proceed to copy.{invocationCwd} (e.g., docs/research, leave blank for cwd root):". Resolve targetDir = invocationCwd + (subpath || ""). Proceed to copy.Copy execution:
mkdir -p "{targetDir}"
cp "{outputPath}" "{targetDir}/{filename}"
Set copyPath = "{targetDir}/{filename}".
Safety guards:
invocationCwd is unset (rare — only if cwd capture failed), skip the prompt and set copyPath = null.invocationCwd equals the configured output directory, skip the prompt — copying onto itself is a no-op.-2, -3, etc. to the filename rather than overwriting.Input: "Analyze this video: https://youtube.com/watch?v=xyz123"
youtube_transcript_api transcript → 12K words.{configured-output-dir}/2026-04-27-dividend-portfolio-strategy.md. Step 4.7 then asks whether to copy a duplicate into invocationCwd.For --chat invocation, Phase 4 returns renderedMarkdown inline, skips Steps 4.5 and 4.7, and never writes a file.
Scripts (in ${CLAUDE_PLUGIN_ROOT}/scripts/): clean-transcript.ts, detect-content-type.ts, partition-transcript.ts, package-db.ts · External: yt-dlp, youtube_transcript_api, bun
Agent types:
general-purpose + sonnet, given full workflow file contentExplore (Structure / Dependency / Pattern)general-purpose + sonnet, given merged results + references/output-templates.mdWorkflow files: workflows/{tutorial,finance,general,repo-exploration}-workflow.md
Sequence: verify external tools → Phase 1 (Gate 1) → Phase 2 (Gate 2) → Phase 3 (Gate 3) → Phase 4 (Gate 4) → report. No phase may be skipped.
Guides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.
Dispatches multiple subagents concurrently for independent tasks without shared state. Use when facing 2+ unrelated failures or subsystems that can be investigated in parallel.
npx claudepluginhub aojdevstudio/agentic-utilities --plugin youtube-analyzer