Use when the user wants to learn something, asks for a video, or says "teach me X", "I want to learn X", "how does X work", "explain X", "is there a video about X", "recommend a course/tutorial on X". Builds a progressive YouTube course through wide, creative search, reading the transcript and the comments before recommending anything.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add LuisMIguelFurlanettoSousa/youtube-course-builder --skill youtube-course-builder --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Youtube Course Builder?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/luismiguelfurlanettosousa-youtube-course-builder)More formats (shields.io, HTML) on the badges page.
---
name: youtube-course-builder
description: Use when the user wants to learn something, asks for a video, or says "teach me X", "I want to learn X", "how does X work", "explain X", "is there a video about X", "recommend a course/tutorial on X". Builds a progressive YouTube course through wide, creative search, reading the transcript and the comments before recommending anything.
argument-hint: [topic the user wants to learn]
---
# YouTube Course Builder (progressive curation)
## Core principle
When the user wants to learn something, deliver **a short explanation + a progressive YouTube
learning path** — from "get the idea" to "you can now say you know this". A recommendation is
**never** made from a title and a thumbnail: every video in the path is picked only after
**reading its transcript and its comments** and judging whether it actually teaches well.
**Golden rule of search:** the words the user typed are the starting point, **never** the whole
search. The search has to be creative and wide — many angles, synonyms, the canonical name of the
subject, the problem behind the question. Searching only the literal string is failure mode #1.
## When to use / when not to
- **Use:** "teach me / I want to learn / how does X work / explain X / got a video on X /
recommend a course on X", or any request for video-based learning.
- **This skill delivers the explanation AND the path** — for learning requests it takes over
instead of a text-only answer.
- **Don't use / turn off:** if the user says "no video", "just explain it", "text only" → give
only the explanation. Also skip it for narrow theory questions where a video adds nothing.
## Flow (7 phases — follow in order)
Create one todo per phase. **All 7 phases are mandatory** — the delivery is not finished until the
path exists as a YouTube playlist (phase 7). Do not ask whether to build it; building it is the
default.
### 1. Understand the learning target
Extract the **real goal**, not the literal sentence:
- Which concept/skill is actually behind the request? What is its **canonical name**
(e.g. "that Google language" → "Go/Golang")?
- What is the user's likely **starting level** on this topic?
- What does **"knowing this"** mean here — memorizing syntax? building a project? grasping theory?
- Which **prerequisites** the user may need first.
**Classify the BREADTH of the topic** (this drives the size and shape of the path — see phase 5):
| Breadth | Example | Ideal path |
|---|---|---|
| **Narrow / one-off question** | "how does `Long` work in Java", "what is debounce" | 1–2 surgical videos (or 1 video + a timestamp). **Do not inflate.** |
| **Focused** | "async/await in JS", "closures", "Docker Compose" | 2–4 progressive videos |
| **Broad / whole domain** | "computer networks", "security", "machine learning", "compilers", "operating systems" | **Full course anchored to the field's canonical textbook** — dense search, one module per chapter, 12–25 videos (see "Broad topic" below) |
If the topic is broad, do **not** dump 15 random videos and do **not** settle for a handful of
overview videos. A broad topic is almost always a topic that **already has a settled curriculum** —
ignoring that produces a path that looks complete and isn't.
#### Broad topic → anchor it to a canonical textbook
Before searching for a single video, identify **the reference work of the field** and use its
**table of contents as a coverage checklist**. The book defines what "knowing the subject" means;
YouTube only fills it in.
**Never recommend a book from memory.** The same rigor demanded for video applies to books: no
citing a memorized classic without verifying. Books age — and the list "everybody knows" usually
points at an edition from ten years ago.
**How to find the candidates:** WebSearch for "best book to learn X", "X reference book",
**university course syllabi and bibliographies**, recent discussions (r/\<field\>, Hacker News,
Stack Exchange) — looking for what is adopted **today**, not what used to be.
**Evaluate each candidate before recommending** (2–4 finalists):
| Criterion | What to check |
|---|---|
| **Current edition** | Which is the latest edition, and **from what year**? Is there a translation, and is it behind the original? |
| **What aged out** | What changed in the domain after that edition that the book does **not** cover? That becomes a declared gap, not a surprise. |
| **Approach** | Order of presentation and intended reader (e.g. bottom-up vs top-down) — it changes who gets along with it. |
| **Real adoption** | Is it still assigned/cited, or has it been replaced? |
| **Reader verdict** | Reviews and discussions: where it is strong, where it drags, what readers say is missing. |
**Community discussion is mandatory here** — it is where the honest criticism lives ("great as a
reference, awful to read cover to cover", "skip chapters X and Y", "the new edition only changed
the exercises"), which storefront reviews and publisher pages never give.
> ⚠️ **Reddit is often unreachable from agent environments** (*verified 2026-07-25*): `WebFetch`
> refuses `reddit.com` and `old.reddit.com`, `curl` on the JSON API returns **403**, and web search
> does not surface threads even with `site:reddit.com`. A substitute that **works** and carries
> discussion of comparable quality — the Hacker News search API (Algolia), no key required:
>
> ```bash
> curl -s "https://hn.algolia.com/api/v1/search?query=<book>&tags=comment&hitsPerPage=8" \
> | jq -r '.hits[]? | (.comment_text // "" | gsub("<[^>]*>";"") | .[0:400])'
> ```
>
> Other open routes: Goodreads, Stack Exchange, course syllabi. **Never invent a "community
> verdict"** that was not actually read — say the source was unreachable and name what was used
> instead.
Then recommend **one** as the primary (naming edition, year, and why this one over the other), and
mention the runner-up in one line for readers who prefer the other approach.
#### Covering the current state of the art (mandatory for broad topics)
A canonical curriculum teaches fundamentals, but **not** what appeared after it. Studying only the
classic produces someone who understands the technology of 2010 and not the one running today.
- Explicitly research **what is current in the domain** (WebSearch: "what changed in X in recent
years", "X 2025/2026", recent RFCs/specs, release notes) and list those topics.
- Guarantee **at least one "current state" module** in the path, with recent videos covering what
the book does not reach.
- While evaluating each video (phase 4), flag whatever the transcript reveals as **dated** — and
say so on delivery: "this part is fundamentals and still holds; that part was replaced by Y".
What this changes in the delivery:
1. **Recommend the book explicitly**, saying which edition/approach and why — the video path is
the fast lane, the book is the depth no video delivers.
2. **Derive the path's modules from the table of contents**, not from whatever YouTube happened
to return.
3. **Deliver a coverage table** of path × chapters, honestly marking what the path covers well,
what it half-covers, and what **only the book covers**. Never let the user believe they watched
the equivalent of the book when they did not.
### 2. Creative search (query fan-out) — NOT literal
Generate **8+ search variations** across different angles before evaluating anything. Combine terms
from the table below:
| Angle | Expansion examples |
|---|---|
| Canonical / real name | nickname → official technical name; acronym → spelled out |
| Level | "for beginners", "from scratch", "basics", "advanced", "in depth", "deep dive" |
| Format | "tutorial", "explained", "full course", "crash course", "masterclass", "guide" |
| Reference channels | the established channels of the niche (e.g. Fireship, freeCodeCamp, 3Blue1Brown) **plus the top channels in the user's own language** |
| Problem behind it | what the user is trying to *solve*, not the label they used |
| Prerequisite / adjacent | the concept that comes before; the sibling topic |
| Common misconceptions | "mistakes", "don't do this", "what nobody tells you" |
| Practice | "hands on", "real project", "in practice", "real world example" |
Run the searches through **two channels in parallel**:
- **WebSearch** with those queries (and `site:youtube.com`).
- **`yt-dlp "ytsearchN:<query>"`** — native YouTube search (see `reference-yt-dlp.md`).
Collect a **wide candidate pool (~15–30 videos)**, filtering nothing yet.
#### Dense search (mandatory for broad topics)
For a broad topic, 8 generic queries are **not enough** — they only return the overview layer
("how X works"), and the technical core of the subject never shows up. Do this instead:
- **One query per chapter/module** of the anchor book's table of contents, using the chapter's
technical vocabulary (not the user's): "CRC error detection data link layer", "TCP congestion
control slow start" — not "how the internet works".
- **20+ queries** total; a pool of **60–150 candidates**.
- Also search for a **backbone**: a complete university course/playlist that follows the book
("full networks course lectures", "Kurose lectures", "lecture 1 course X"). A good backbone plus
surgical videos on its weak spots usually beats a patchwork.
- At the end, **check the table of contents item by item**: a chapter with no candidate is a
**hole**, and a hole must be searched again with different terms before being declared uncovered.
### 3. Metadata triage
Pull metadata for the pool with `yt-dlp --dump-json --skip-download` (views, likes, publish date,
channel, duration, chapters, description). Cut down to a **shortlist of ~6–10**, balancing:
- **Authority** (channel, views/likes, like/view ratio),
- **Recency** (fast-moving topic → penalize old videos; timeless theory → date matters less),
- **Relevance** to the real goal,
- **Level coverage** (make sure the shortlist has beginner, intermediate and advanced candidates).
### 4. Deep evaluation (the non-negotiable criterion)
For **every video on the shortlist**, read the **transcript** (auto-captions) + the **top comments**
(see `reference-yt-dlp.md`). Run this **in parallel subagents, in the foreground** (one video per
agent) to keep it fast — never in the background.
Evaluate per video:
- **Actual teaching quality** (does the transcript explain well, with rhythm and logical order, or
does it ramble / is it clickbait?),
- **Accuracy and currency** of the content,
- **True level** — does the transcript confirm it really is "beginner"/"intermediate"/"advanced"?
- **Prerequisites** the video assumes,
- **Comment verdict** — do they confirm ("best explanation", "saved my semester") or contradict
("understood nothing", "outdated", "bad audio", "missing X")?
Discard without mercy whatever does not survive the reading, even if the title was perfect.
### 5. Sequence the progressive path
- **Derive the number of videos from the breadth classified in phase 1** — it is NOT fixed at 3:
- *Narrow:* 1–2 videos (or 1 video + a timestamp). A single excellent video is a valid answer —
do not force steps.
- *Focused:* 2–4 progressive videos.
- *Broad:* **a modular course mirroring the anchor book's table of contents** — 12–25 videos
grouped into modules named after the chapter's subject (e.g. "Module 3 — Data link layer"), in
the book's pedagogical order. Each module opens by stating what it solves. A module with no
worthy video → say "only the book serves here" instead of plugging the hole with a bad video.
- Every video must **earn its place** (YAGNI: two videos teaching the same thing become one).
- **Order into steps** with progress labels (skip steps the topic does not need), for example:
1. **🟢 Start here — get the idea** (overview, "what it's for")
2. **🟡 Now you understand it** (mechanics, the core concepts)
3. **🔵 Now you can say you know it** (real usage, depth)
4. **⚫ (optional) Go deeper / practice** (project, edge cases, advanced)
- Adapt the labels to the topic; not every subject needs all four steps.
### 6. Deliver
- **A short explanation** of the topic — direct, **in the user's language**.
- **The path**, in the format below.
- **For broad topics:** the **recommended anchor book** (edition/approach + why that one) and the
**coverage table** of path × chapters (🟢 covers / 🟡 partial / 🔴 book only). Be blunt about the
real fraction covered — a video path rarely passes ~70% of a textbook, and promising more than
that is the worst mistake available in this skill.
### 7. Export to a YouTube playlist (MANDATORY — always close the round with this)
**Every course ends as a playlist.** A path that lives only in the chat transcript is lost the
moment the conversation scrolls away; the playlist is what the user actually studies from. So do
not offer it, do not ask permission for it — build it as the last step of every run.
Create a **private playlist** in the user's account named after the topic, with the videos **in the
path's order**. Method: **Playwright MCP** — it reuses the already-logged-in Chrome session, so no
OAuth and no API key. Steps verified 2026-07-25.
**First — two checks that prevent losing the whole round:**
1. **Widen the window:** `browser_resize` to **1680×1000**. In a narrow viewport YouTube collapses
the "Save" button inside "More actions": the selector still matches, but the click fails with
`element is not visible`, and on a re-render the button disappears from the DOM.
2. **Check the login** (profile sessions expire):
```js
() => !document.querySelector('ytd-masthead a[href*="ServiceLogin"]') // true = logged in
```
⚠️ **Do not use `#avatar-btn`** — it gives a false negative (the element does not exist in the
current layout). If logged out, **stop and ask the user to log in** in the window the MCP
opened: Google credentials/2FA are theirs, there is no way around it.
> ⚠️ **`aria-label` values follow the language of the user's Google account, not the OS.** The
> selectors below are given in English; for another account language, substitute the localized
> string (Portuguese shown as an example). When in doubt, **do not guess the string** — take a
> `browser_snapshot` of the panel and click by `ref`, which is locale-independent and always works.
**Flow:**
| Step | How |
|---|---|
| Open video 1 | `browser_navigate` |
| Open the panel | click `ytd-watch-metadata button[aria-label="Save to playlist"]` (pt-BR: `"Salvar na playlist"`) |
| Create the playlist | click `yt-sheet-view-model button[aria-label="Create new playlist"]` (pt-BR: `"Criar nova playlist"`) — last item in the list |
| Title | `browser_type` into `textarea[placeholder="Choose a title"]` (pt-BR: `"Escolha um título"`) |
| Confirm | **native click** (`browser_click`) on the `Create` button **inside the `dialog`** |
| Videos 2..N | open each → "Save to playlist" → click `yt-sheet-view-model button[aria-label^="<playlist title>"]` |
- **Visibility already defaults to "Private"** — verify it in the dialog, don't touch it.
- **Programmatic clicks do not work *to create*, but do work *to add*** (verified 2026-07-27):
- **Creating:** `element.click()` via `browser_evaluate` opens the sheet and fills the title, but
the "Create" button never fires its handler — the playlist **is silently never created**. Only
`browser_click` (real mouse events) creates it.
- **Adding videos 2..N:** `element.click()` **does** work. That halves the calls per video — one
`browser_navigate` plus one `browser_evaluate` that opens the panel and ticks the playlist:
```js
async () => {
const sleep = ms => new Promise(r => setTimeout(r, ms));
const SEL = 'ytd-watch-metadata button[aria-label="Salvar na playlist"]'; // localized
for (let t = 0; t < 20 && !document.querySelector(SEL); t++) await sleep(500);
const save = document.querySelector(SEL);
if (!save) return 'FAILED: no save button';
save.click(); await sleep(2000);
const btn = Array.from(document.querySelectorAll('yt-sheet-view-model button[aria-label]'))
.find(b => (b.getAttribute('aria-label') || '').startsWith('<playlist title>'));
if (!btn) return 'FAILED: playlist not listed';
btn.click(); await sleep(1500);
return 'OK ' + location.search;
}
```
The retry loop matters: the button only exists after the player hydrates. On a 22-video course
this took ~4 minutes instead of ~10.
- **`browser_navigate` + `browser_evaluate` can be batched in a single message** — the harness
runs them in order, so several videos fit in one round trip. Batches of 3–4 held up fine.
- **There are two "Create" buttons in the DOM** — disambiguate with a `browser_snapshot` of the
`dialog` and click by `ref`.
- **Insertion order is the final order** of the playlist.
- **Getting the `playlistId`:** `fetch('/feed/playlists')` and match the title in the HTML.
- **Always verify at the source:** open `/playlist?list=<id>` and list `ytd-playlist-video-renderer`
(position + `videoId`) plus the header (confirms `Private` and the count). **Never validate by
`aria-label`** — it keeps saying "Not selected" long after the video was added.
- Include the `playlist_url` in the delivery.
**The playlist is only "done" when verified at the source.** Adding N videos means N page loads —
budget for it on long courses (20+ videos) instead of declaring victory after the first few.
**The only acceptable reasons to finish without a playlist**, and both must be stated plainly in
the delivery rather than silently skipped:
1. **The user is logged out.** Stop, show them the window the MCP opened, and ask them to log in —
Google credentials and 2FA are theirs. Resume as soon as they confirm.
2. **No browser is available at all** (headless/cron run, MCP absent). Say so explicitly, and hand
over the ordered list of video IDs so the user can build it themselves.
Never drop phase 7 quietly, and never turn it into a question when the browser is working.
## Path output format
```markdown
## 🎓 Mini-course: <Subject>
_<1–2 sentences framing the topic and what the path delivers.>_
### 🟢 Start here — get the idea
**[Video title](URL)** · Channel · ⏱ 12 min · 🇬🇧
- **Why this one:** <the teaching edge, what the transcript/comments confirmed>
- **After it you can:** <what the user is now able to do/understand>
- **Watch / skip:** <the chapter that matters, the stretch worth skipping>
### 🟡 Now you understand it
**[Title](URL)** · Channel · ⏱ 40 min · 🇬🇧
- ...
### 🔵 Now you can say you know it
**[Title](URL)** · Channel · ⏱ 1h10 · 🇬🇧
- ...
```
Always mark the language of each video. Prefer videos in the user's own language; reach for another
language only when it is **clearly superior**, and say so.
## Common mistakes (avoid)
| Mistake | Fix |
|---|---|
| Searching only the user's literal words | Fan out 8+ queries across different angles (phase 2) |
| Recommending by title/views without reading | Transcript + comments are mandatory (phase 4) |
| Locking on 3 videos | The count comes from the topic's breadth (phase 1); 1 up to many |
| Treating a broad topic as a short overview path | Anchor to the canonical book, dense per-chapter search, modular course (phase 1) |
| Recommending a book from memory / a memorized list of classics | Research candidates and **evaluate** them (edition, year, what aged out, adoption, reviews) exactly as you do with video (phase 1) |
| A 100% classic path, teaching technology no longer in use | Mandatory "current state" module + flag what is dated in each video (phases 1, 4 and 6) |
| Delivering 6–8 overview videos and letting it look like full coverage | Honest coverage table + recommended book (phase 6) |
| Searching only the user's vocabulary on a broad topic | One query per chapter, using the chapter's technical vocabulary (phase 2) |
| Inflating a narrow topic ("`Long` in Java") with steps | 1 surgical video + the explanation may be enough; don't pad it |
| A path with no clear progression | Labeled steps, from "the idea" to "you know it" |
| Redundant videos in the path | One concept, one video; cut the overlap |
| Running agents in the background | Phase 4 subagents always run in the foreground |
| Delivering the path and stopping there | The playlist is mandatory (phase 7) — a course that lives only in the chat is lost when it scrolls away |
| Asking "want me to create the playlist?" | Don't ask, build it. Only stop to ask if the user is **logged out** |
| Declaring the playlist done without checking | Open `/playlist?list=<id>` and count `ytd-playlist-video-renderer` — never trust `aria-label` |
## Reference
Exact `yt-dlp` commands (search, metadata, transcript, comments) live in **`reference-yt-dlp.md`** —
read it when executing phases 2–4.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!