| name | yt-dlp |
| description | Probe, transcript, and download video/audio with yt-dlp CLI on supported hosts. Use when you need metadata, captions, or local media. Transcript-first (probe, transcript, download). NOT for static HTML (Fetch MCP), research, or ffmpeg transforms. |
| argument-hint | <probe|transcript|download|playlist|cookies|doctor|help> [url or path] |
| user-invocable | true |
| license | MIT |
| metadata | {"author":"wyattowalsh","version":"1.0.0"} |
| allowed-tools | Bash Read Glob Write |
yt-dlp
CLI skill for yt-dlp: read-only URL probes, caption/transcript extraction, and optional media download. Follow the transcript-first protocol before any download.
Scope: Supported video/audio hosts via yt-dlp, user-owned cookie files, playlist metadata, and local output under an explicit directory. NOT for: static page fetch (use Fetch MCP or curl), broad multi-source research (research), ffmpeg transform recipes (ffmpeg), or bypassing platform Terms of Service.
Canonical Vocabulary
| Term | Meaning | NOT |
|---|
| probe | Read-only metadata via --dump-json; no media write | download |
| transcript | Captions/subtitles to text files; prefer over full download | audio rip by default |
| download | Persist media bytes after probe + user approval | silent bulk grab |
| playlist | Multi-entry URL; enumerate before selective download | blind full-playlist download |
| cookies | User-owned Netscape cookie file passed with --cookies | committed or skill-bundled secrets |
| doctor | Preflight JSON report for binary, version, ffmpeg | live URL smoke |
| format id | yt-dlp format_id from probe (e.g. 251, 137+140) | guessed extension |
| manual sub | Creator-uploaded captions | auto-generated only |
| auto sub | Platform-generated captions | guaranteed accuracy |
Dispatch
$ARGUMENTS | Mode | Action |
|---|
probe <url> / metadata <url> / info <url> | Probe | Run bundled probe_url.py; summarize title, id, duration, subs |
transcript <url> / subs <url> / captions <url> | Transcript | Probe first; extract best available subtitles without video download |
download <url> / fetch <url> / save <url> | Download | Probe first; confirm rights + format; download to explicit output dir |
playlist <url> | Playlist | Probe with playlist allowed; list entries; selective download only with approval |
cookies <path> / cookies check <path> | Cookies | Validate user-owned cookie file path; never copy into repo |
doctor / preflight | Doctor | Run scripts/doctor.py --format json |
| Natural language: "what is this video", "get subtitles", "download this" | Auto | Map to probe → transcript → download per protocol below |
| (empty) | Help | Show modes, protocol, ethics pointer, and examples |
Auto-Detection Heuristic
- URL + words like subtitle, caption, transcript, CC → Transcript (still probe first).
- URL + download, save, mp4, audio, rip → Download (still probe + approval first).
- URL + playlist, channel list, all videos → Playlist.
- Bare URL or "what is this link" → Probe.
- Path ending in
cookies.txt or mention of login/auth → Cookies guidance, then re-probe with --cookies.
- Ambiguous → ask: metadata only, transcript, or download?
Transcript-First Protocol
Run these stages in order. Do not skip probe. Do not download until transcript needs are ruled out or the user explicitly wants media files.
Stage 1 — Doctor (once per session or after errors)
uv run python scripts/doctor.py --format json
Stop on ok: false or any check with status: fail (missing yt-dlp binary).
Stage 2 — Probe (mandatory before transcript or download)
uv run python scripts/probe_url.py --url 'https://…' --format json
With user-owned cookies:
uv run python scripts/probe_url.py --url 'https://…' --cookies "$HOME/.config/yt-dlp/cookies.txt" --format json
Playlist URL (enumerate entries; pass --allow-playlist on probe):
uv run python scripts/probe_url.py --url 'https://www.youtube.com/playlist?list=PL…' --allow-playlist --format json
From probe JSON, report: id, title, duration, uploader, availability, subtitles / automatic_captions languages, and recommended format_id candidates. Load references/formats-and-quality.md when choosing formats.
Stage 3 — Transcript (preferred over download)
When subtitles exist, extract text without downloading video:
yt-dlp --skip-download --write-subs --write-auto-subs --sub-langs 'en.*,en' \
--convert-subs srt --sub-format srt \
-o '%(title).200B.%(ext)s' \
--paths home:"$HOME/Downloads/yt-dlp/transcripts" \
'URL'
Prefer manual subs over auto when both exist. Summarize path to .srt / .vtt and offer to strip timing lines for plain text. If no subs: say so and ask before download-for-transcription (higher cost, rights-sensitive).
Stage 4 — Download (explicit approval required)
Before running:
- Confirm the user has rights to save the content (personal/archive/fair-use context per references/ethics-and-tos.md).
- Confirm output directory (default:
$HOME/Downloads/yt-dlp/media/).
- Confirm format from probe (
-f FORMAT or sensible default: bv*+ba/b).
mkdir -p "$HOME/Downloads/yt-dlp/media"
yt-dlp -f 'bv*+ba/b' \
--paths home:"$HOME/Downloads/yt-dlp/media" \
-o '%(playlist_index)s-%(title).200B.%(ext)s' \
'URL'
Report output path, format id, file size, and whether ffmpeg merge ran.
Mode Details
Probe mode
- Use bundled
probe_url.py (wraps yt-dlp --dump-json --no-download).
- Read-only: no writes under cwd or repo.
- For age-gated or login-only content, stop and route to Cookies — do not guess credentials.
Transcript
- Never default to downloading video/audio for text needs.
- Use
--skip-download always.
- If multiple languages, pick user-requested lang or
en with fallback list from probe.
Download
- Single URL default:
--no-playlist unless user asked for playlist.
- No bulk channel/archival without explicit scope confirmation.
- Do not embed cookies in commands in chat logs; reference
$COOKIES env or user path only.
Playlist
- Probe with playlist enabled:
uv run python scripts/probe_url.py --url 'PLAYLIST_URL' --allow-playlist --format json
- Present numbered entries (index, title, duration).
- Download selected indices only (
--playlist-items 1,3,5) after approval — never blind full playlist.
Cookies
- User-owned cookie file only — path under user home or explicit user-provided path.
- Never commit cookie files, never store in repo, never bundle in skill package.
- Export guidance (browser extension → Netscape
cookies.txt) lives in references/ethics-and-tos.md.
- Validate readability:
test -r "$HOME/.config/yt-dlp/cookies.txt" && echo readable
Pass --cookies PATH only on probe/download when user supplied the path.
Doctor
uv run python scripts/doctor.py --format json
Parses JSON ok, summary, and per-check status. Stop workflow on fail. Treat warn (e.g. missing ffmpeg) as advisory.
Help
Show dispatch table, transcript-first protocol, default paths, and ethics reference link.
Gallery (Empty Arguments)
Present common invocations when $ARGUMENTS is empty:
| # | Task | Example |
|---|
| 1 | Preflight | /yt-dlp doctor |
| 2 | Probe metadata | /yt-dlp probe https://www.youtube.com/watch?v=… |
| 3 | Get subtitles | /yt-dlp transcript https://www.youtube.com/watch?v=… |
| 4 | Download (after approval) | /yt-dlp download https://www.youtube.com/watch?v=… |
| 5 | Playlist enumerate | /yt-dlp playlist https://www.youtube.com/playlist?list=… |
| 6 | User-owned cookies | /yt-dlp cookies ~/.config/yt-dlp/cookies.txt |
Pick a number, a mode from the dispatch table, or paste a URL and say whether you need metadata, subtitles, or a download.
Critical Rules
- Probe before transcript or download — always use
probe_url.py or equivalent --dump-json --no-download.
- Transcript before download — prefer
--skip-download subtitle extraction when captions exist.
- Explicit approval for downloads — confirm rights, scope, output dir, and format.
- User-owned cookies only — never commit, copy into repo, or invent cookie paths.
- No ToS bypass coaching — see references/ethics-and-tos.md; refuse DRM circumvention or paywall evasion requests.
- Not Fetch MCP — static HTML, docs pages, and non-yt-dlp hosts → Fetch MCP or
curl, not this skill.
- Not ffmpeg skill — remux, transcode, clip, waveform →
/ffmpeg after download if needed.
- Least privilege output — write only under user-approved directories, never into the agents repo tree.
- Report provenance — title, URL, extractor, format id, and output paths in the final summary.
Troubleshooting
See references/troubleshooting.md for extractor errors, geo blocks, signature failures, and ffmpeg merge issues.
References
Scripts
| Script | Purpose |
|---|
scripts/doctor.py | JSON preflight: yt-dlp, version, ffmpeg |
scripts/probe_url.py | Read-only --dump-json wrapper |
scripts/check.py | Validate skill manifest and evals |
Examples
uv run python scripts/doctor.py --format json
uv run python scripts/probe_url.py --url 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' --format json
yt-dlp --skip-download --write-subs --write-auto-subs --sub-langs en -o '%(id)s' \
--paths home:"$HOME/Downloads/yt-dlp/transcripts" 'URL'
yt-dlp -f 'bv*+ba/b' --paths home:"$HOME/Downloads/yt-dlp/media" -o '%(title).200B.%(ext)s' 'URL'