Youtube advisor
Build or update a Claude Code advisor skill from any YouTube channel. Use when the user pastes a YouTube channel URL or handle, names a creator, or says "make an advisor on …", "build a skill from …", "обнови … advisor", "refresh that advisor". Triggers on bare URLs like https://youtube.com/@channel, @handles, or creator-name mentions.From its SKILL.md
npx -y skills add provencal-potatoskin571/youtube-advisorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 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
11.9 KB, ~3.1k tokens by cl100k_base, as published. Nobody here has run it
youtube-advisor — build a Claude Code advisor from any YouTube channel
Two-action user contract
The user does exactly two things:
- Drops a channel URL/handle and a one-sentence intent in chat.
- Uses the resulting
/<channel-slug>-advisorskill to ask questions about that channel.
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.
When this skill triggers
- A YouTube channel URL,
@handle, or playlist URL appears in the message. - Creator name appears in a "build me an advisor on …" / "make a skill from …" / "make a YC advisor" framing.
- The user says "обнови yc-advisor", "refresh that advisor", "check for new videos".
Workflow
Step 1 — parse intent silently
Extract from the user's message:
- Channel(s) — URL,
@handle, playlist URL, or a named creator.- If a creator is named without a URL, search via
yt-dlp ytsearch5:"<name>"(oryt-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.
- If a creator is named without a URL, search via
- Selection hints:
- "last year" →
--since 2025-MM-DD(today minus 1 year). - "long videos only" →
--title-exclude "shorts|#shorts"(already default — no extra flag). - "the Founder Stories series" →
--title-include "Founder Stories". - Pasted video URLs → write IDs to
/tmp/ids.txt, pass--ids /tmp/ids.txt.
- "last year" →
- Intent sentence — for the LLM SKILL.md drafter (
--intent "..."). - Language preference — match the chat language by default; pass
--answer-languageonly 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.
Step 2 — confirm in plain language
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.
Step 3 — execute via Bash (HIDDEN from the user)
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 \
--yes
Run it via the Bash tool. The user does NOT see this command.
Step 4 — stream progress sparsely
Reuse the scriba progress-streaming pattern:
- Emit a short status message on each stage transition (resolving channel, ingesting, indexing, embedding, drafting SKILL.md, running evals).
- Emit on ~25% audio-processed boundaries for Whisper transcription (NOT every 10%, NOT on a timer).
- NEVER use
/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.
Step 4 — polish the draft (YOU are the LLM)
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:
- Read
<advisor>/.pending-llm-draft.json(it contains the schema, ~8 transcript excerpts, the corpus metadata, the user intent, and the output paths). - Draft a polished
SKILL.mddirectly 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. - Re-render
SKILL.mdandAGENTS.mdat the paths listed inoutput_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. - (Optional) Draft
evals/benchmark.json(10–20 channel-grounded Q/A items withexpected_quote_video_idsandmust_terms) so the user can later run a quality check. - Delete
.pending-llm-draft.json— that marker file's presence means "AI hasn't polished yet". Removing it signals the advisor is ready.
Only then echo the postrun guide.
Step 5 — show 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.
Update flow
When the user says "обнови yc-advisor", "refresh the advisor", "check for new videos", "что нового на канале":
youtube-advisor update --advisor ~/.claude/skills/yc-advisor --yes
Same UX: never show the user the command. Echo the postrun summary. If the user provides a hint ("обнови, но только за эту неделю"), translate it to --since <date>.
Worked examples (for YOU the agent — never shown to the user)
Each example shows: user message → flags YOU compose → what the user sees.
Example 1 — bare URL + intent
User: https://www.youtube.com/@ycombinator. I want a YC advisor focused on startup hiring and fundraising.
You parse:
- channel =
@ycombinator - intent =
"YC startup advice with focus on hiring and fundraising" - language = match chat language (RU/EN auto)
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 \
--yes
User sees: confirmation summary → progress updates → postrun guide. NEVER sees the flags.
Example 2 — date hint, long videos only
User: pick interviews longer than 1 hour from 2024 onwards on @lexfridman
You parse:
- channel =
@lexfridman - since =
2024-01-01 - title_exclude default already drops shorts; "longer than 1 hour" is a length filter not yet in v1 — skip it and accept all matching videos.
You run:
youtube-advisor bootstrap --channel @lexfridman --since 2024-01-01 \
--out ~/.claude/skills/lex-advisor \
--from-natural-language --intent "Long-form Lex Fridman interviews" --yes
Tell 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."
Example 3 — explicit video IDs
User: Use these specific videos: https://youtu.be/abc, https://youtu.be/def, https://youtu.be/ghi
You:
- Extract IDs:
abc,def,ghi. echo -e "abc\ndef\nghi" > /tmp/youtube-advisor-ids.txt(via Bash).- Run:
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>" --yes
Ask 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.)"
Example 4 — named creator, no URL
User: Build me an advisor on Naval
You:
- Run
yt-dlp --flat-playlist -J "ytsearch3:Naval Ravikant channel" | jq -r '.entries[] | .channel'to find candidates. - Ask: "I found
@navalr— Naval Ravikant's channel. Use that one?" - On
y, run bootstrap with--channel @navalr.
Example 5 — update with hint
User: обнови yc-advisor — также проверь нет ли новых видео за эту неделю
You parse:
- advisor =
~/.claude/skills/yc-advisor - since override = 7 days ago.
You run:
youtube-advisor update --advisor ~/.claude/skills/yc-advisor --since 2026-05-29 --yes
Tell user the result via the postrun summary.
Rules
- Never show flags to the user. Always build the command silently. Run it via Bash. Echo the result.
- Never paste a
bashcommand for the user to run. You run everything; you echo only natural-language summaries and the post-run guide. - Match the user's language in conversation (RU / EN / etc.) — but the CLI itself is English-only.
- If Whisper time is estimated > 15 min, ask before continuing ("Some videos lack captions and would need ~3h of local transcription. Skip them, or wait?").
- Don't poll status on a timer. Reuse the scriba pattern: emit on stage change + 25% audio progress.
- End with the bootstrap_guide output unmodified. No additional commentary.
- Never use
/looporScheduleWakeupfor progress monitoring — they cost prompt-cache misses. - Don't fabricate channel handles. If the user names a creator without a URL, always disambiguate via search first.
Installation prerequisites
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.
When YouTube blocks the fetch
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.
What ships with it: 72 files
1938.5 KB alongside SKILL.md, 49 of them executable
docs/
- logo.png1201.4 KB
references/
- .gitkeep0 B
scripts/
- install.shruns2.2 KB
- status.shruns977 B
- youtube_advisor_v2.5.zip465.4 KB
src/
- youtube_advisor/bootstrap.pyruns18.8 KB
- youtube_advisor/build_embeddings.pyruns5.1 KB
- youtube_advisor/build_index.pyruns1.7 KB
- youtube_advisor/cli.pyruns5.7 KB
- youtube_advisor/_cookies.pyruns4.0 KB
- youtube_advisor/eval_runner.pyruns2.8 KB
- youtube_advisor/fetch_channel.pyruns5.6 KB
- youtube_advisor/filters.pyruns2.6 KB
- youtube_advisor/gen_benchmark.pyruns4.8 KB
- youtube_advisor/gen_skill_md.pyruns4.8 KB
- youtube_advisor/ingest/captions_api.pyruns3.4 KB
- youtube_advisor/ingest/captions_ytdlp.pyruns2.5 KB
- youtube_advisor/ingest/__init__.pyruns0 B
- youtube_advisor/ingest/normalize.pyruns1.6 KB
- youtube_advisor/ingest/orchestrator.pyruns6.0 KB
- youtube_advisor/ingest/whisper.pyruns2.9 KB
- youtube_advisor/__init__.pyruns104 B
- youtube_advisor/_llm.pyruns1.3 KB
- youtube_advisor/_md.pyruns2.5 KB
- youtube_advisor/_naming.pyruns231 B
- youtube_advisor/_paths.pyruns176 B
- youtube_advisor/postrun_guide.pyruns3.9 KB
- youtube_advisor/_progress.pyruns3.0 KB
- youtube_advisor/search.pyruns5.7 KB
- youtube_advisor/templates/advisor.AGENTS.md.tmpl1.5 KB
- AGENTS.md2.2 KB
- CHANGELOG.md3.0 KB
- CONTRIBUTING.md3.0 KB
- .editorconfig261 B
- .gitattributes308 B
- .gitignore142 B
- LICENSE1.0 KB
- pyproject.toml2.2 KB
- README.md11.5 KB
- SECURITY.md1.3 KB
32 more files not listed here. See all 72 in the repository.
Gives 0 of the 12 instructions most social media skills give in ~3.1k tokens
Counted across 489 of the 492 authors here whose files we hold, read 2026-08-07
- Adapt formats and tone to each platformin 26 of 489, across 14 files
- Build content around three to five pillarsin 25 of 489, across 13 files
- Read product marketing context before asking questionsin 23 of 489, across 13 files
- Respond to all comments on your postsin 21 of 489, across 9 files
- Use the output flag to specify an output directoryin 14 of 489, across 4 files
- Generate output logo images with white backgroundin 13 of 489, across 4 files
- Fix failing generation scripts directlyin 13 of 489, across 4 files
- Ask user about HTML preview after logo generationin 12 of 489, across 3 files
- Run the download script with a URLin 12 of 489, across 3 files
- Implement exponential backoff for 429 responsesin 12 of 489, across 3 files
- Write the hook firstin 12 of 489, across 7 files
- Include a single clear call to actionin 12 of 489, across 9 files
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.