How to Generate a SKILL.md From a YouTube Channel
The Prepublish channel skill generator reads the 12 most recent long-form uploads of a public channel, pulls the original-language captions from at least four of them, and writes a four-file Agent Skill bundle in about six minutes. The bundle is one SKILL.md brief plus three reference files of verbatim evidence: hooks, titles, and transcript excerpts.
TL;DR
Paste a channel handle into the generator. It lists the 60 newest uploads, keeps long-form videos, analyses at most 12, and requires 4 usable original-language transcripts. Gemini Flash writes a brief; a deterministic renderer emits SKILL.md plus references/hooks.md, references/titles.md, and references/transcript-excerpts.md. Every quote over 8 words is checked against the transcripts.
Try it on your own script
Paste your draft below. You get your hook, structure, and pacing scores, a script-level attention-risk map, and the single biggest issue quoted from your own lines. Free, no login.
Free · No login · See a sample audit first if you prefer.
Key Takeaways
- The generator analyses the 12 most recent long-form uploads and requires at least four usable original-language transcripts
- It writes a four-file Agent Skill bundle in about six minutes; measured runs on 18 and 19 September 2026 took 6 minutes 30 seconds, 5 minutes 35 seconds, and 6 minutes 5 seconds
- Gemini Flash writes a brief, and a deterministic renderer emits SKILL.md plus references/hooks.md, references/titles.md, and references/transcript-excerpts.md
- Quotes longer than 8 words are checked against the supplied transcripts; a quote that cannot be found is stripped and the removal is recorded in the provenance block
- The renderer caps SKILL.md at 480 lines, under the 500-line recommendation in the Agent Skills specification
Key Statistics
- •Measured runs on 18 and 19 September 2026: @maxinomics 6 minutes 30 seconds, @veritasium 5 minutes 35 seconds, @maxinomics rerun 6 minutes 5 seconds (marketing/content-drafts/EVIDENCE.md, section 6).
- •The pipeline analyses at most 12 long-form uploads and requires at least 4 usable transcripts (channel_skill_service.go, channelSkillMaxVideos and channelSkillMinTranscripts).
- •Quotes longer than 8 words are checked against the supplied transcripts; a quote that cannot be found is stripped and the removal is recorded in the provenance block (gemini_channel_skill.go, channelSkillQuoteVerifiedAboveWords).
- •The renderer caps SKILL.md at 480 lines, under the 500-line recommendation in the Agent Skills specification (channel_skill_render.go, maxSkillMDLines; agentskills.io/specification, retrieved 19 September 2026).
- •One stored bundle carried 11 videos and 11 transcripts, all auto-generated captions, and produced four files (stored @Maxinomics run, 18 September 2026, gemini-3.5-flash, prompt version 1).
In This Guide
- How to Generate a SKILL.md From a YouTube Channel
- What the generator reads and what it emits
- What is inside the generated SKILL.md
- A real SKILL.md from the Maxinomics run
- Identity and niche
- Structure and pacing template
- How to install the skill in Claude Code, Cursor, Codex CLI, Copilot, and Gemini CLI
- Which channels make good input
- How to edit the generated file before you use it
- What the generator cannot do
How to Generate a SKILL.md From a YouTube Channel
Paste a channel handle into the Prepublish channel skill generator. It analyses the 12 most recent long-form uploads, requires at least four usable original-language transcripts, and writes a four-file Agent Skill bundle in about six minutes. Measured runs on 18 and 19 September 2026 took 6 minutes 30 seconds, 5 minutes 35 seconds, and 6 minutes 5 seconds.
What the generator reads and what it emits
The generator accepts a bare @handle, a channel URL, or a link to any video on the channel. It resolves the channel with yt-dlp and reads public data only: the 60 newest entries in the videos tab, then titles, descriptions, tags, chapters, view counts, and durations for the long-form videos among them. There is no YouTube Data API call anywhere in the tool and no Google account is involved (ops/specs/channel-skill-generator.md, 18 September 2026).
Three numbers bound the read. Uploads under 180 seconds are discarded before the list is used, at most 12 videos are analysed, and the transcript stage stops once it has accumulated 60,000 characters (channel_skill_service.go, channelSkillLongformSeconds, channelSkillMaxVideos, channelSkillTranscriptsTotal). Each transcript is capped at 8,000 characters, of which the first 1,200 characters are kept as an opening and the next 6,000 as a body.
One Gemini Flash call writes the brief. A pure renderer then produces the files, with no model call and no wall clock, so the same stored result always renders the same bytes (channel_skill_render.go, RenderChannelSkillFiles).
| Run, 18 and 19 September 2026 | Wall clock | Videos read | Transcripts used | SKILL.md |
|---|---|---|---|---|
| @maxinomics | 6 min 30 s | 12 | 9 | 9,623 bytes |
| @veritasium | 5 min 35 s | 12 | 11 | 9,395 bytes |
| @maxinomics rerun | 6 min 05 s | 11 | 11 | 9.4 KB |
Source: marketing/content-drafts/EVIDENCE.md, section 6.
Metadata dominates that time rather than writing. Twelve detail pulls at roughly 13 seconds each account for about 2 minutes 36 seconds of the first run, and every transcript then costs a metadata probe plus a caption download (ops/specs/channel-skill-generator.md, 18 September 2026). A channel with fewer eligible uploads finishes sooner.
What is inside the generated SKILL.md
The renderer emits one brief file and up to three evidence files. SKILL.md is always present; a reference file appears only when it has evidence to carry:
// RenderChannelSkillFiles renders the downloadable bundle from the stored
// model output and the input snapshot. It is pure and deterministic: no model
// call, no wall clock, no map iteration, so the same entity always renders the
// same bytes. SKILL.md is always present; a reference file is emitted only when
// it has evidence to carry.
files := []ChannelSkillFile{{Path: "SKILL.md", Content: renderSkillMD(s)}}
// three conditional appends follow, in this order (conditions elided):
"references/hooks.md"
"references/titles.md"
"references/transcript-excerpts.md"
The SKILL.md body is fixed in order. These are the heading lines as renderSkillBody writes them, with each section's own render call elided:
func renderSkillBody(s *ChannelSkill, limits skillRenderLimits) []string {
var lines []string
if section := renderIdentity(s, limits); len(section) > 0 {
lines = append(lines, "## Identity and niche", "")
// ...section... elided
}
if section := renderAudience(s, limits); len(section) > 0 {
lines = append(lines, "## Audience", "")
}
if section := renderVoice(s, limits); len(section) > 0 {
lines = append(lines, "## Voice and diction rules", "")
}
if section := renderHooks(s, limits); len(section) > 0 {
lines = append(lines, "## Hook patterns", "")
}
if section := renderStructure(s, limits); len(section) > 0 {
lines = append(lines, "## Structure and pacing template", "")
}
if section := renderTitleConventions(s, limits); len(section) > 0 {
lines = append(lines, "## Title conventions", "")
}
if section := renderThumbnails(s, limits); len(section) > 0 {
lines = append(lines, "## Thumbnail conventions", "")
}
if section := renderRecurring(s, limits); len(section) > 0 {
lines = append(lines, "## Recurring segments and catchphrases", "")
}
if section := renderTopics(s, limits); len(section) > 0 {
lines = append(lines, "## Topics covered and gaps", "")
}
if section := renderCTAs(s, limits); len(section) > 0 {
lines = append(lines, "## CTA patterns", "")
}
if section := renderBannedMoves(s, limits); len(section) > 0 {
lines = append(lines, "## Banned moves", "")
}
if section := renderChecklist(s, limits); len(section) > 0 {
lines = append(lines, "## Draft checklist", "")
// (each section's content appends elided for length)
}
for len(lines) > 0 && lines[len(lines)-1] == "" {
lines = lines[:len(lines)-1]
}
return lines
}
renderProvenance then appends a closing ## Provenance block that is always present and never empty.
| SKILL.md part | Derived from | What the reader sees |
|---|---|---|
| YAML frontmatter | SkillFolderName, Result.Description, ChannelURL, VideosAnalyzed, GeneratedAt | name, description, and a metadata map with channel_url, videos_analyzed, generated_at, generator: prepublish |
| Identity and niche | identity.niche, .positioning, .promise, .credibility_markers | a niche paragraph, then bold-labelled "Where it sits" and "What a viewer gets" |
| Audience | audience.who, .knowledge_level, .what_they_want, .what_bores_them | who the channel writes for, plus two bullet lists |
| Voice and diction rules | voice.summary, .person, .formality, .sentence_rhythm, .rules[], .vocabulary[] | a rhythm description, then rules that can each carry a blockquoted transcript line |
| Hook patterns | hooks[]: pattern, seconds_to_payoff, video_title, opening_quote, why_it_works | real openings with the moment the promise lands |
| Structure and pacing template | structure.template[], .pacing_notes[] | one table row per beat: Beat, Typical start, Typical length, Purpose |
| Title conventions | titles.conventions, .formulas, .avoid | conventions, reusable formulas, and a "These titles never" list |
| Thumbnail conventions | thumbnails.conventions, .recurring_elements | what the thumbnails repeat |
| Recurring segments and catchphrases | recurring_segments[], catchphrases[] | named segments and repeated phrases with a frequency note |
| Topics covered and gaps | topics.covered, .adjacent_gaps | two lists: inside the supplied videos, and just outside them |
| CTA patterns | ctas[]: wording_example, placement, frequency_note | the wording, where it sits, and how often it appears |
| Banned moves | banned_moves[] plus voice.forbidden[] | moves the channel does not make, each with a reason |
| Draft checklist | draft_checklist[] | Markdown checkboxes |
| Provenance | video count, upload-date range, transcript count split manual and auto, fetch date, evidence_notes | what was read, when, and what the data could not show |
The three reference files carry the depth that does not fit in the brief:
| Reference file | Contents | Emitted when |
|---|---|---|
| references/hooks.md | one section per hook: the verbatim opening quote, then title, duration, views, and URL from the snapshot, then why it works and when the promise paid off | the result has at least one hook |
| references/titles.md | conventions, formulas, the avoid list, and a "Titles analysed" table of every video in the snapshot with title, published date, length, and views | there is any title evidence or any snapshot video |
| references/transcript-excerpts.md | five groups in fixed order: transcript openings, opening hooks, voice rule evidence, structure beat evidence, recurring segment evidence | at least one quote survives deduplication |
Two ceilings shape all of this. SKILL.md is capped at 480 lines (maxSkillMDLines), and the renderer walks a budget ladder of 8 items, 6 quotes, 240 characters per quote, and 900 characters per paragraph, then 5, 4, 180, and 600, then 3, 3, 140, and 400. The first set that fits wins, and the overflow evidence stays in the reference files. The skill name is capped at 48 characters, matches ^[a-z0-9-]{1,48}$, takes a -voice suffix, and falls back to youtube-channel-voice.
A real SKILL.md from the Maxinomics run
The bundle below is real output stored from a run against @Maxinomics on 18 September 2026: prompt version 1, model gemini-3.5-flash, 11 videos analysed, 11 transcripts used, all of them auto-generated captions. Nothing below is reconstructed.
---
name: "maxinomics-voice"
description: "A writing brief for Maxinomics, to be loaded when drafting scripts that analyze global business, economics, and industrial supply chains through real-world data."
metadata:
channel_url: "https://www.youtube.com/channel/UCUEmaeh13ai1ivT5wzz5Lhg"
videos_analyzed: 11
generated_at: "2026-09-18T17:07:05Z"
generator: prepublish
---
Identity and niche
The economic, industrial, and geopolitical forces driving global systems, business models, and supply chains.
Where it sits. An analytical, data-driven explainer channel that bypasses political rhetoric and corporate spin to focus on physical constraints, unit economics, and historical parallels.
What a viewer gets. A deep, logical understanding of how complex global systems actually work by tracing the money and physical resources underneath them.
Credibility markers
- Uses real-time industry data platforms, such as FreightWaves for freight intelligence.
- Cites academic research papers from institutions like MIT and Boston University.
- Breaks down complex corporate operations into precise unit economics, such as return per ton of payload.
- Draws direct historical parallels, comparing modern tech companies to 19th-century railroads or the 1920s rubber monopoly.
Structure and pacing template
| Beat | Typical start | Typical length | Purpose |
|---|---|---|---|
| The Scarcity Hook | 0:00 | 1:10 | Introduce a physical constraint or a specific object that represents the core economic puzzle of the video. |
| The Core Math or Unit Economics | 1:10 | 3:00 | Break down the exact numbers, costs, and revenues that drive the behavior of the key players. |
| The Historical Parallel | 6:40 | 3:20 | Show how this exact economic pattern has played out in the past, proving it is a recurring force of human nature. |
| The Physical Chokepoint | 10:00 | 5:00 | Identify the geographical or physical bottleneck that decides who wins and who loses in this market. |
Pacing notes
- Videos range from 13 to 25 minutes, allowing for deep, multi-chapter historical and economic investigations.
- Chapters are clearly defined, often transitioning from a modern corporate dilemma to a historical case study before returning to the present.
- The script maintains a steady, deliberate pace, using pauses and musical shifts to let complex mathematical or economic points sink in.
The closing provenance block of the same file reports `Videos analysed: 11 (2025-12-23 to 2026-08-07)` and `Transcripts used: 11 (0 manual, 11 auto-generated)`. It also records what the model could not establish. For this run the hooks carry no timings, and the note gives the reason:
> the exact seconds to payoff for the hooks could not be determined from the provided metadata as the transcripts do not contain explicit timestamps for the resolution of the opening promises.
Those values are zero in the file.
One detail about the evidence lines in the bundle: they reproduce the creator's own words, which means they carry the punctuation, filler, and mishearings of the caption track. Those passages sit in blockquotes and are quoted as they are.
How to install the skill in Claude Code, Cursor, Codex CLI, Copilot, and Gemini CLI
Unzip the download. The archive already contains a top-level folder named after the skill, and every client below expects exactly that shape.
| Client | Directory | Source |
|---|---|---|
| Claude Code | ~/.claude/skills/<skill-name>/SKILL.md for personal use, .claude/skills/<skill-name>/SKILL.md in a repository | Extend Claude with skills, retrieved 19 September 2026 |
| Cursor | .cursor/skills/ in a repository or ~/.cursor/skills/ for the machine | Cursor skills help, retrieved 19 September 2026 |
| Codex CLI | $HOME/.agents/skills/, or $REPO_ROOT/.agents/skills/ for a repository | Where Codex loads local skills, retrieved 19 September 2026 |
| GitHub Copilot, CLI and VS Code | .github/skills/, .claude/skills/, or .agents/skills/ in a repository; ~/.copilot/skills/ or ~/.agents/skills/ for personal | Adding agent skills for GitHub Copilot CLI, retrieved 19 September 2026; the VS Code page is dated 16 September 2026 |
| Gemini CLI | ~/.gemini/skills/ or ~/.agents/skills/ for user scope, .gemini/skills/ or .agents/skills/ for workspace scope | Gemini CLI skills, retrieved 19 September 2026 |
Cursor also loads .claude/skills/ and .codex/skills/ for compatibility, so one Claude Code install serves both. Copilot takes /skills reload to pick up a new folder without restarting, then /skills info <name> to confirm. Codex CLI needs a restart if a new skill does not appear.
Three constraints from the Agent Skills specification apply to any hand-editing afterwards. The name field must match the parent directory name, the description field is capped at 1024 characters, and the body is meant to stay under 500 lines with longer material in references/ (specification, retrieved 19 September 2026). The generator already works inside those limits, because it caps SKILL.md at 480 lines and puts the deep evidence in three reference files.
Which channels make good input
The 12-video budget cuts both ways. It is enough to describe a settled format and too little to describe a channel in transition.
| Input | What happens | Why |
|---|---|---|
| Twelve or more recent long-form uploads with captions | Full run | The brief is built from the maximum evidence set |
| Four to eleven eligible uploads | Run proceeds with fewer videos | Provenance records the real count, so the brief is thinner but honest |
| Fewer than four eligible long-form uploads | Fails as too_few_videos, and the run is charged | There is not enough material to describe a format |
| Uploads without captions, or with only machine translations | Those videos are skipped | The tool quotes the creator's own words and never generates a transcript |
| Fewer than four usable transcripts | Fails as too_few_transcripts, and the run is charged | Nothing can be quoted, so nothing can be written |
| A channel that pivoted format inside the last 12 uploads | The brief averages both eras | The window has no era filter |
Two practical rules follow. Pick a channel whose last dozen long-form uploads resemble each other, and check the provenance block before trusting the voice section, because the upload date range printed there is the window the model actually read.
A captions failure caused by YouTube blocking our own network is reported separately as captions_blocked and does not charge the daily run, because that failure is ours rather than the channel's (ops/specs/channel-skill-generator.md, 18 September 2026).
How to edit the generated file before you use it
Read the provenance block first, including the "What the data could not show" list. It is the model telling you where it guessed or gave up, and the fastest route to the parts that need a human.
The evidence sections are worth trusting without re-reading the channel, because a machine check backs them. Every *_quote field the model returns is compared against the supplied transcripts, and a quote longer than 8 words that cannot be found is removed, with the removal recorded in the provenance block (ai.ValidateChannelSkillQuotes, ai.StripChannelSkillUnverifiedQuotes). The writer gets up to three attempts, each retry naming the exact failures. Quotes of 8 words or fewer are not checked, so treat a short quotation as a paraphrase and a long one as grounded.
These sections deserve an edit:
- Identity, audience, and the draft checklist. These are interpretation rather than measurement. The model read metadata and transcript excerpts, and it did not meet the audience.
- Thumbnail conventions. They are inferred from titles, descriptions, tags, and chapters. The writer never sees the thumbnail image.
- Payoff timings.
seconds_to_payoffdepends on captions or chapters carrying timing. When it cannot be established, the value is zero and the reason appears in the provenance notes, as in the Maxinomics bundle above. - Title formulas. A formula carries an example only when that exact title appears in the analysed snapshot, so a missing example signals a pattern the model generalised.
Everything else can be saved and used. There is no build step and no schema to validate.
What the generator cannot do
It reads public captions and metadata, and nothing else. It does not watch the video. Delivery, editing rhythm, music, on-screen text, and the thumbnail image are invisible to it, which is why thumbnail guidance is inferred rather than observed.
It describes patterns rather than predicting results. The bundle carries no claim about retention, watch time, or platform treatment, and the model is instructed to report a gap rather than fill one. The provenance block says so directly: for the Maxinomics run it lists as absent "audience retention, click-through rates, and private analytics."
The transcripts are frequently auto-generated, so a verbatim quote can contain a caption track's error. The generator copies that text as it stands, which keeps the quote traceable and keeps a misheard word attributable to the source.
Finally, the analysis window is recent by design. Twelve uploads is a snapshot of how a channel publishes now, not a history of how it got there. If the channel has a second format that matters, the honest move is a second run once that format fills the window.
The channel scanner reads the same public surface if you want the raw numbers before committing to a skill run, and how to write a YouTube script covers the drafting side that the brief feeds.
Frequently asked questions
How long does it take to generate a SKILL.md from a YouTube channel?
Six minutes is the working figure. Three live runs measured on 18 and 19 September 2026 took 6 minutes 30 seconds for @maxinomics, 5 minutes 35 seconds for @veritasium, and 6 minutes 5 seconds for a @maxinomics rerun (marketing/content-drafts/EVIDENCE.md, section 6). Most of that time is metadata rather than writing: twelve detail pulls at roughly 13 seconds each account for about 2 minutes 36 seconds, and every transcript then costs a metadata probe and a caption download.
How many videos does the generator read, and how many transcripts does it need?
It lists the 60 newest uploads, discards anything under 180 seconds, and analyses at most 12 long-form videos (channel_skill_service.go, channelSkillVideoWindow and channelSkillMaxVideos). Each transcript is capped at 8,000 characters and collection stops at 60,000 characters across the run. At least 4 videos must yield a usable original-language transcript or the run fails without writing a file. A Shorts-heavy channel can lose most of its uploads to the 180-second filter before analysis begins.
What happens if the channel has no public captions?
The video is skipped. The generator never invents a transcript, and a video whose only tracks are machine translations is skipped as well, because quoting a translation back as the creator's voice would be a fabrication (channel_skill_service.go). If fewer than 4 usable transcripts remain, the run fails as too_few_transcripts. When the refusal comes from YouTube blocking our own network instead, the row records captions_blocked, and that failure does not charge the daily run.
Where do you put SKILL.md so an agent can use it?
Unzip the bundle and put the skill folder in the client's skills directory. Claude Code reads ~/.claude/skills/ and .claude/skills/; Cursor reads ~/.cursor/skills/ and .cursor/skills/; Codex CLI reads ~/.agents/skills/ and a repository's .agents/skills/; GitHub Copilot reads ~/.copilot/skills/ and .github/skills/; Gemini CLI reads ~/.gemini/skills/ and .gemini/skills/. The zip already contains a top-level folder named after the skill, which matters because the specification requires the name field to match the parent directory (agentskills.io/specification, retrieved 19 September 2026).
Can you edit the generated SKILL.md?
Yes. The file is plain Markdown with YAML frontmatter, so no build step is involved. Edit the interpretation sections first: identity, audience, and the draft checklist are the model's reading of the channel, while the quote fields were machine-checked against the transcripts. If you rename the folder, keep the name field in step, because the specification requires the name to match the parent directory. The generator writes nothing back, so an edited copy is yours alone.
Why does the brief describe two different formats?
Because the analysis window is the 12 most recent long-form uploads, with no era filter. A channel that changed format, length, or subject inside that window produces a brief that averages the old and the new. The provenance block dates the window, which is how you spot it: when the upload range covers a known pivot, read the voice and structure sections as two periods rather than one. Narrowing the input means waiting until the new format fills the window.
Does the generator need a YouTube account or an API key?
No. It reads public channel data with yt-dlp and makes no YouTube Data API call, so a visitor needs no Google account and the channel owner grants nothing (ops/specs/channel-skill-generator.md, 18 September 2026). The limit is one charged run per IP address per rolling 24 hours, with a seven-day cache per channel. A repeat request for the same channel inside seven days returns the stored bundle instead of spending the run.
Related Guides
Free tools to put this into practice
Hook Analyzer
Score your first 1-3 sentences
Title Analyzer
Writing rubric + 5 rewrites
Words to Minutes
Script length calculator
Word Counter
Count, reading time, duration
Want to see how this reads on real channels? Browse the channel breakdowns. Each one compares script patterns across a channel's own higher-viewed and lower-viewed uploads, quoted from the transcripts.
See where your next script leaks viewers
Paste your script, get your scores and the biggest leak for free. No login.