ingest-youtube
Skill50 starsChanged 7 months agoMITView on GitHub
Use when the user says /ingest-youtube <url-or-channel> [--days N], pastes a YouTube URL (youtube.com or youtu.be) wanting a transcript or summary in the vault, asks to ingest, capture, sync, transcribe, or pull a YouTube video, channel, talk, podcast, or keynote into the vault, or wants a video's captions or content available to the knowledge graph. Not for downloading video files, live streams, or non-YouTube sources (Vimeo, Twitch).
- Installs packages
1 other project uses a version of this.
Adopted by
Most recently taken up by
- allanbian1017/skillstheir own version, first seen Jul 3, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- allanbian1017/skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository39 other files it gives its agents.
- docs/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- setup-brainSkill
- backfill-journal-body-contextSkill
- cierre-de-llamadaSkill
- coachingSkill
- coachSkill
- daily-journalSkill
- deconstructSkill
- diagnoseSkill
- doubt-driven-developmentSkill
- evolveSkill
- for-my-teamSkill
- graphifySkill
- health-contextSkill
- health-doctorSkill
- health-setupSkill
- ingest-githubSkill
- ingest-healthSkill
- insightsSkill
- instinct-exportSkill
- instinct-importSkill
- interview-meSkill
- longitudinalSkill
- meeting-todosSkill
- nano-bananaSkill
- note-todosSkill
- optimize-brainSkill
- patternsSkill
- repurpose-talkSkill
- resolver-querySkill
- riseSkill
- second-brain-mappingSkill
- secret-warnSkill
- security-snapshotSkill
- setup-vault-typesSkill
- skillify-meta-loopSkill
- sunday-reviewSkill
- vault-systemSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 22
Do NOT use for:
- Very specific: line 31
Verify yt-dlp is installed.
- Distinctive: line 47
No em dashes (use commas, colons, periods, parentheses)
- Very specific: line 50
No paraphrasing or summarization at ingest time.
- Very specific: line 100
If the video has no available subtitles and Whisper is not installed locally, write a stub file with subtitle_source: none and a note in …
- Very specific: line 104
If yt-dlp --list-subs returns no manual or auto subtitles AND whisper-cpp is installed locally, fall back to:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
ingest-youtube — YouTube-to-vault connector
{SKILL_DIR}= this skill's own folder (locally: the directory this SKILL.md lives in; a served brain substitutes the real absolute path before you read this). If a path does not resolve, name the missing file and stop — never guess another location.
Ingests YouTube transcripts into the vault as markdown the graphify pipeline can read and the rest of the AI Brain Starter substrate (decision log, session-close cascade, hooks) can act on.
Same connector pattern as ingest-github: adding a new source means a new normalizer, not a new architecture.
When to use
- User says
/ingest-youtube <url>for a single video - User says
/ingest-youtube <channel-handle> [--days N]for a channel's recent uploads - User asks to capture, sync, ingest, transcribe, or pull a talk/podcast/keynote into the vault
- User pastes a YouTube URL and asks for a transcript or summary
- User mentions wanting a video's content available to the knowledge graph
Do NOT use for:
- Downloading the actual video file (use
yt-dlpdirectly with-f best) - Live streams (transcripts are not stable)
- Non-YouTube sources (Vimeo, Twitch, Twitter Spaces get their own connectors)
- One-off transcript reads where the user does not want a vault file (run
yt-dlp --write-auto-subdirectly and pipe to stdout)
How it works
- Parse the input: single URL → single-video mode. Channel handle (e.g.
@channelname) → channel mode (last N days, default 14). - Verify
yt-dlpis installed. If not, attemptbrew install yt-dlp(macOS) orpip3 install --user yt-dlpand surface the install path. Abort if neither works. - For each video, call
yt-dlp --list-subs <url>to enumerate available subtitles. - Subtitle priority: manual subs > auto-generated > Whisper fallback. Manual subs preserve creator-provided punctuation and speaker labels; auto-gen is uppercase + no punctuation; Whisper is the floor.
Download the highest-priority subtitle as VTT via
yt-dlp --write-sub --sub-lang <lang> --skip-download. Default language preference:en,es(so non-English content is captured in its original language without forcing English).Gotcha:
en,espicks whichever of those two is available, including YouTube's auto-translated captions. For a video whose original language is neither English nor Spanish,enin the auto-caption list is a translation, not the source audio, and will outrank the real original-language transcript under the default preference. Always runyt-dlp --list-subs <url>first: if an<xx>-origcode exists (e.g.es-orig), that's the untranslated auto-caption in the actual source language — pass--lang <xx>-orig,<xx>explicitly to prefer it over the default.- Strip VTT timing markers and merge into clean prose paragraphs. Preserve speaker labels if the source had them.
- Pull video metadata (title, channel, upload date, duration, video_id, URL) via
yt-dlp --print-json --skip-download. - Slugify the channel name and video title. Write to
External Inputs/YouTube/<channel-slug>/<YYYY-MM-DD>-<video-slug>.md. Scan transcript for trigger keywords (decision, framework, model, principle, "the lesson is", playbook, anti-pattern, case study). For each match, create a writing-seed stub at
⚙️ Meta/Captures/<YYYY-MM-DD>-youtube-<channel-slug>-<video-id>.mdso the seed lands in the captures aggregator.Gotcha: keyword matching is a plain substring check, not word-boundary-aware, so it also fires inside unrelated words in other languages — e.g. Spanish "decisiones" contains "decision", "modelo" contains "model". Non-English ingests routinely produce false-positive seed stubs; treat any stub from a non-English transcript as unverified until a human confirms it, and delete it if it's noise.
- Print summary: file path, transcript word count, language, seeds detected.
Voice rules
- No em dashes (use commas, colons, periods, parentheses)
- Spanish-language transcripts stay in Spanish; English stays in English; bilingual transcripts preserve language code-switches
- Speaker labels quoted verbatim from the source subtitle file
- No paraphrasing or summarization at ingest time. Summaries happen downstream via
/note-todosor/repurpose-talk.
Invocation
The skill is a thin orchestrator. The actual ingestion runs in Python at {SKILL_DIR}/ingest.py.
When invoked:
- Parse arguments: URL (single-video) or channel handle (channel mode),
--days N(channel mode only, default 14),--lang <code>(override defaulten,es). - Single-video mode: hand the URL to
ingest.py. The script handlesyt-dlpcalls, VTT cleanup, vault write, and seed stub creation. - Channel mode: enumerate the last N days of uploads via
yt-dlp --flat-playlist --print-json --dateafter <date> https://www.youtube.com/<channel>. Pass each video URL toingest.pyin sequence. - Surface the summary to the user. If seed stubs were created, list the file paths.
Output contract
The vault file at External Inputs/YouTube/<channel-slug>/<YYYY-MM-DD>-<video-slug>.md has frontmatter:
---
type: external-input
source: youtube
video_id: <11-char ID>
url: https://www.youtube.com/watch?v=<id>
channel: <channel-name>
channel_url: https://www.youtube.com/<handle>
title: <video title>
upload_date: <YYYY-MM-DD>
duration_seconds: <int>
language: <ISO code>
subtitle_source: manual | auto | whisper
word_count: <int>
ingested_at: <ISO 8601 timestamp>
---Body is the cleaned transcript as paragraph prose. If the source had speaker labels, format as **<speaker>:** <text> per turn.
Capture seed stubs at ⚙️ Meta/Captures/<date>-youtube-<channel-slug>-<video-id>.md carry frontmatter that matches the existing capture schema so the captures aggregator picks them up cleanly.
Idempotency
Re-ingesting the same video URL overwrites the same vault file (the path is deterministic from channel-slug + upload-date + video-slug). The seed stub filenames hash the video_id, so the same source video produces the same stub filename across re-runs. Re-runs refresh, never duplicate.
Acceptance test
A successful run produces:
- One new (or refreshed) file at
External Inputs/YouTube/<channel>/<date>-<title>.mdwith valid frontmatter and clean prose body - Zero or more new capture stubs at
⚙️ Meta/Captures/<date>-youtube-<channel>-<video-id>.md - A stdout summary:
Wrote N words to <path>. Language: <code>. Subtitle source: <source>. Seeds at: <paths>.
If the video has no available subtitles and Whisper is not installed locally, write a stub file with subtitle_source: none and a note in the body explaining the gap, so re-runs are still idempotent and the absence is recorded.
Whisper fallback
If yt-dlp --list-subs returns no manual or auto subtitles AND whisper-cpp is installed locally, fall back to:
yt-dlp -x --audio-format mp3 -o <tmp>/<video-id>.mp3 <url>to download audiowhisper-cli <tmp>/<video-id>.mp3 --model ggml-large-v3.bin --output-vttto transcribe- Continue with the VTT cleanup pipeline
Whisper fallback is OFF by default for cost reasons. Enable per-call with --whisper. Local Whisper has zero per-minute cost but takes ~real-time on CPU.
Cross-references
- For turning the transcript into LinkedIn/Substack content →
repurpose-talkafter ingest - For pulling action items out of the transcript →
note-todosafter ingest - For knowledge-graph extraction across many transcripts →
graphifyonExternal Inputs/YouTube/directly
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

