Build an AI advisor SKILL from any YouTube channel — transcripts, BM25 + semantic RAG, verbatim quotes with timestamps.
SaferSkills independently audited youtube-advisor (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
The user does exactly two things:
You (the AI agent) do everything in between. Never expose --since, --max, --out, bash, or any CLI flag to the user. Never paste a shell command for the user to run. Compose every command silently, run it via Bash, and report results in plain language.
@handle, or playlist URL appears in the message.Extract from the user's message:
@handle, playlist URL, or a named creator.yt-dlp ytsearch5:"<name>" (or yt-dlp --get-id ytsearch3:"<name> channel"), then ASK the user "I found @navalr — Naval Ravikant's channel — use that one?" before continuing. Don't guess.--since 2025-MM-DD (today minus 1 year).--title-exclude "shorts|#shorts" (already default — no extra flag).--title-include "Founder Stories"./tmp/ids.txt, pass --ids /tmp/ids.txt.--intent "...").--answer-language only if the user explicitly says.If the message is ambiguous, ask AT MOST 3 short questions in plain language. NEVER list flag names. NEVER show CLI syntax.
Print a one-line summary:
"I'll fetch ~187 videos from @ycombinator (2022 → today), output to ~/.claude/skills/yc-advisor. Roughly 20 minutes. Go?"Only ask about Whisper time if the estimated duration is > 15 minutes for the Whisper fallback.
youtube-advisor bootstrap \
--channel @ycombinator \
--since 2022-01-01 \
--out ~/.claude/skills/yc-advisor \
--from-natural-language --intent "YC startup advice with focus on hiring" \
--answer-language auto \
--quote-style auto \
--yesRun it via the Bash tool. The user does NOT see this command.
Reuse the scriba progress-streaming pattern:
/loop, ScheduleWakeup, or any periodic wake-up — they cost prompt-cache misses ($).#### Live status from a side terminal
While bootstrap is running, you can peek at progress without tailing the verbose stdout:
bash <repo>/scripts/status.sh <advisor-dir>
# or
youtube-advisor status <advisor-dir>Both read <advisor>/.progress.json and print a one-line snapshot, e.g. 🎬 ingesting · 4/187 · 02:14 · ETA 18:45.
Use this when the user asks "how far along is it?" — read the progress JSON, don't tail bash output. The JSON updates atomically on every stage change and per-video ingest.
Whenever bootstrap ran without ANTHROPIC_API_KEY (the default Claude Code case) — or when you passed --no-llm — the CLI writes a stub SKILL.md plus a hand-off file at <advisor>/.pending-llm-draft.json. Do not echo the postrun guide yet. Instead:
<advisor>/.pending-llm-draft.json (it contains the schema, ~8 transcript excerpts, the corpus metadata, the user intent, and the output paths).SKILL.md directly from those samples — anti-patterns must be specific to THIS channel's actual failure modes (not generic clichés), and example_queries must be real questions this corpus can answer well.SKILL.md and AGENTS.md at the paths listed in output_paths. Use the same Jinja templates the stub came from (templates/advisor.SKILL.md.tmpl, advisor.AGENTS.md.tmpl) — only the description/purpose/anti_patterns/example_queries change.evals/benchmark.json (10–20 channel-grounded Q/A items with expected_quote_video_ids and must_terms) so the user can later run a quality check.Only then echo the postrun guide.
When bootstrap exits, it prints the "what's next" guide. Echo it to the user AS-IS (verbatim from the CLI output). Do NOT add commentary about what flags you used. The user should see only the guide and a brief "Done!" framing.
When the user says "обнови yc-advisor", "refresh the advisor", "check for new videos", "что нового на канале":
youtube-advisor update --advisor ~/.claude/skills/yc-advisor --yesSame UX: never show the user the command. Echo the postrun summary. If the user provides a hint ("обнови, но только за эту неделю"), translate it to --since <date>.
Each example shows: user message → flags YOU compose → what the user sees.
User: https://www.youtube.com/@ycombinator. I want a YC advisor focused on startup hiring and fundraising.
You parse:
@ycombinator"YC startup advice with focus on hiring and fundraising"You run:
youtube-advisor bootstrap \
--channel @ycombinator \
--out ~/.claude/skills/yc-advisor \
--from-natural-language \
--intent "YC startup advice with focus on hiring and fundraising" \
--answer-language auto \
--yesUser sees: confirmation summary → progress updates → postrun guide. NEVER sees the flags.
User: pick interviews longer than 1 hour from 2024 onwards on @lexfridman
You parse:
@lexfridman2024-01-01You run:
youtube-advisor bootstrap --channel @lexfridman --since 2024-01-01 \
--out ~/.claude/skills/lex-advisor \
--from-natural-language --intent "Long-form Lex Fridman interviews" --yesTell the user: "Note: I'll pull videos from 2024 onwards. The shorts filter is on by default. Length-based filtering isn't a v1 feature, so very short interviews will also be included — let me know if you'd like to drop them manually later."
User: Use these specific videos: https://youtu.be/abc, https://youtu.be/def, https://youtu.be/ghi
You:
abc, def, ghi.echo -e "abc\ndef\nghi" > /tmp/youtube-advisor-ids.txt (via Bash).youtube-advisor bootstrap --channel "<infer from one of the videos via yt-dlp>" \
--ids /tmp/youtube-advisor-ids.txt \
--max 3 \
--out ~/.claude/skills/<slug>-advisor \
--from-natural-language --intent "<ask user>" --yesAsk the user briefly: "These three videos come from <channel>. Use that as the channel handle? And: what should this advisor be good at? (One sentence.)"
User: Build me an advisor on Naval
You:
yt-dlp --flat-playlist -J "ytsearch3:Naval Ravikant channel" | jq -r '.entries[] | .channel' to find candidates.@navalr — Naval Ravikant's channel. Use that one?"y, run bootstrap with --channel @navalr.User: обнови yc-advisor — также проверь нет ли новых видео за эту неделю
You parse:
~/.claude/skills/yc-advisorYou run:
youtube-advisor update --advisor ~/.claude/skills/yc-advisor --since 2026-05-29 --yesTell user the result via the postrun summary.
If youtube-advisor is not installed (which youtube-advisor fails), do the install yourself — the user shouldn't have to leave chat. Clone into ~/.claude/skills/youtube-advisor (or ~/tools/youtube-advisor outside Claude Code), then run bash scripts/install.sh via the Bash tool. If ffmpeg is missing, install.sh will surface that — run brew install ffmpeg (macOS) or the platform equivalent and retry. Only ping the user if a step needs a sudo password or a non-trivial decision.
ANTHROPIC_API_KEY is not required when this skill is invoked from inside Claude Code — the agent in chat (you) drafts SKILL.md directly via the .pending-llm-draft.json hand-off (see Step 4). If the env var IS set, the CLI auto-uses the Anthropic SDK to pre-draft SKILL.md and the eval benchmark — that is purely an optimization, never a prerequisite. Pass --no-llm to force the hand-off path explicitly.
If you see HTTP 429 / "Sign in to confirm you're not a bot" / _extract_player_response failed errors, YT's anti-bot is rate-limiting this IP. yt-dlp invocations already pass --remote-components ejs:github (the EJS JS-challenge solver) and --extractor-args youtube:formats=missing_pot (PO-token tolerance) by default — but the EJS solver needs `deno` on PATH at runtime. If which deno fails, install via brew install deno (macOS) or curl -fsSL https://deno.land/install.sh | sh (Linux) and retry. If you're still blocked after that, two more fixes:
Option 1 — Use your logged-in browser cookies (recommended): Pass --cookies-from-browser chrome (or firefox, safari, brave, edge). yt-dlp reads cookies straight from the browser profile — no copy-paste. With cookies set, the captions pool stays at concurrency 8.
Option 2 — Wait it out: The defaults already slow requests (1–5s random sleep) and retry on 429 with exponential backoff. Without cookies the captions pool also drops to concurrency 2 + a 0.5–2s jitter per call. A retry after a few minutes usually clears.
You can also set YOUTUBE_ADVISOR_COOKIES_BROWSER=chrome once in your shell rc, or drop a Netscape cookies.txt at ~/.config/youtube-advisor/cookies.txt, to default that browser/file for all advisors.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.