Follow your youtubers
Track a list of YouTube channels and produce a daily digest brief. Use when the user wants a refresh of their followed channels — phrases like "follow my youtubers", "pull today's videos", "refresh the channel digest", "track the finance YouTubers". Reads handles from channels.txt, discovers new uploads for free, fetches transcripts through a fallback chain (transcriptapi if configured → free YouTube captions → OpenAI Whisper if configured), saves raw transcripts under transcripts/<handle>/, then writes a synthesis brief to daily/<YYYY-MM-DD>.md using the template selected in channels.txt (finance by default). Works with zero API keys.From its SKILL.md
npx -y skills add johnsonice/follow-your-youtubersAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.4 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
follow-your-youtubers
Daily-digest skill for a fixed list of YouTube channels. Two outputs per run: raw transcripts (one file per video, grouped by channel) and a daily brief (one file per day). Channel discovery is always free. Transcripts go through an ordered fallback chain, so the skill works with zero API keys and gets more capable with each key you add.
Path convention
All paths are relative to this skill's own directory (the folder
containing this SKILL.md). Resolve every path against that directory — do not
assume any other working directory. .venv/bin/python refers to the
skill-local virtualenv (see references/setup.md for first-run install).
Inputs and outputs
-
channels.txt— sibling of this SKILL.md. One channel per line.#comments and blank lines ignored. Re-read on every run.Row format. Whitespace-separated tokens. First token is
@handle; anykey=valuetoken is a tag; anything else (e.g. a URL) is informational and ignored. A barekey=valueline with no@handleis a global directive. Recognized:Kind Key Values Effect directive templatefinance(default) |generalSelects templates/<value>.mdfor the daily brief.tag langISO code, e.g. zhCaption-language preference and Whisper language hint for that channel. tag backendlocalSkip the transcriptapi stage for this channel (saves credits where it's known to fail, e.g. captions disabled). Unknown keys: warn one line, never fatal. Empty channel list: stop and tell the user to add channels (see channels.example.txt).
-
transcripts/<handle>/<YYYY-MM-DD>_<videoId>.md— raw transcripts. The filesystem is the dedup ledger: if a file matching this videoId already exists for the handle, the video is processed; skip it. -
daily/<YYYY-MM-DD>.md— the brief written at the end of each run.
If any directory or channels.txt is missing, create it (channels.txt by copying channels.example.txt) and tell the user before continuing.
Transcript backend chain
Per new video, try stages in order; first success wins. Log each fallthrough
inline (@handle:<videoId>: stage failed — <reason>).
- transcriptapi — only if configured AND the channel is not tagged
backend=local. Configured means: thetranscriptapiskill is installed in your environment (preferred — use it per its own docs), orTRANSCRIPTAPI_API_KEYis set (call the HTTP API per transcriptapi.com docs). Costs 1 credit per transcript. - Local captions — free, no account:
.venv/bin/python scripts/fetch.py transcript --video-url <videoId> --no-whisper --format json(append--language <code>when the channel has alangtag). - Whisper — only if
OPENAI_API_KEYresolves; ~$0.006/min:.venv/bin/python scripts/fetch.py transcript --video-url <videoId> --format json(same--languagerule). The script runs captions first internally, so stage 3 also covers stage 2 — invoke stage 3 directly instead of stage 2 when a Whisper key exists.
fetch.py prints one JSON object on stdout. Success shape matches
transcriptapi's /transcript response plus source: "captions" | "whisper".
Errors: {"error": kind, "detail": msg} with exit codes 0 success · 1
transient (retry once) · 2 unavailable (skip) · 3 caller error (fix config).
Workflow
- Load channels. Parse channels.txt per the format above. Apply global
directives; default
template=finance. - Per-channel cutoff. For each handle, look in
transcripts/<handle>/: maxYYYY-MM-DDfilename prefix if files exist, else today − 7 days. - Discover new uploads (always free). Preferred: transcriptapi's
channel/latest(0 credits) when configured. Otherwise:.venv/bin/python scripts/fetch.py latest --channel @HANDLE→{"channel": "@h", "results": [{"video_id", "title", "published", "url"}]}. A single-channel failure must not abort the run — log inline, continue. - Filter to new uploads. Keep videos where BOTH:
publishedis after the channel's cutoff, AND notranscripts/<handle>/*_<videoId>.mdexists. - Fetch and save transcripts. Run each surviving video through the
backend chain. On success write
transcripts/<handle>/<published-date>_<videoId>.mdusing the transcript template below (create the folder if needed). On chain exhaustion: log, skip, never write a partial file. Retry a stage once only on exit 1. - Write the daily brief. After all fetches, write
daily/<today>.mdfollowing the selectedtemplates/<name>.md, covering ONLY transcripts captured this run. 800–1500 words of substance. Non-English content: the brief stays in English, but quote key numbers and claims in the original language with an English gloss. Ifdaily/<today>.mdexists from an earlier run today, append a## Additional pull — HH:MMsection instead of overwriting. Zero new transcripts → no daily file; print the tally and stop. - Tally as the last line of your reply:
N channels checked, M new transcripts saved (A via transcriptapi, B via captions, C via whisper), K credits spent— always show every line item, even when zero.
Transcript file template
---
title: "Video Title Goes Here"
channel: "@ChannelHandle"
published: 2026-07-01
url: https://youtube.com/watch?v=abc123XYZ00
videoId: abc123XYZ00
captured: 2026-07-08
language: en # en | zh | zh-CN | ...
transcript_source: captions # transcriptapi | captions | whisper
---
<raw transcript text — keep paragraph breaks, do not summarize, do not strip
filler. This is the source of truth for re-summarization later.>
transcript_source values: transcriptapi (stage 1), captions (stage 2 or
fetch.py's captions path), whisper (fetch.py's Whisper path — copy the
source field from its output).
Cost discipline
- Discovery is free at every stage. Local captions are free. transcriptapi
costs 1 credit/video. Whisper costs
$0.006/min ($0.15 per 25-min video). - Cutoff + filesystem dedup are the only guards against runaway spend. Never fetch a transcript unless both step-4 conditions hold.
- Watch the tally's
via whisperfigure run-to-run — a sudden jump means a channel's captions went dark. - Backfills beyond the last 7 days: estimate first
(
videos × 1 creditand/orcaptionless videos × ~$0.15) and confirm with the user before fetching.
Failure handling
- Single-channel discovery failure → log inline, continue with the rest.
- Single-video failure → fall through the chain; if exhausted, log and skip.
- transcriptapi 402 (out of credits) → disable stage 1 for the rest of the run; the chain continues at stage 2. Surface in the tally.
- fetch.py exit 3 (
missing_openai_key,openai_auth) → disable stage 3 for the run; surface in the tally so the user knows to fix the key. - fetch.py exit 1 (
openai_unavailable,audio_*) → per-video transient; retry once, then skip that video and keep going. - Bogus
@handle→ expected; report and move on.
What ships with it: 24 files
56.5 KB alongside SKILL.md, 11 of them executable
.claude-plugin/
- marketplace.json579 B
- plugin.json437 B
daily/
- .gitkeep0 B
references/
- setup.md3.9 KB
scripts/
- captions.pyruns3.0 KB
- core.pyruns6.1 KB
- fetch.pyruns6.2 KB
- rss.pyruns4.2 KB
- whisper_stt.pyruns11.4 KB
templates/
- finance.md1.6 KB
- general.md1.4 KB
tests/
- conftest.pyruns210 B
- test_captions.pyruns1.6 KB
- test_cli.pyruns3.5 KB
- test_core.pyruns2.0 KB
- test_rss.pyruns2.2 KB
- test_whisper_stt.pyruns1.7 KB
transcripts/
- .gitkeep0 B
- channels.example.txt1.7 KB
- channels.txt1.1 KB
- .gitignore126 B
- LICENSE1.0 KB
- README.md2.2 KB
- requirements.txt306 B