source-to-skill · git:20261004.33810fc · 2026-10-04 · sha256 f6b37e46484f56f4

source-to-skill git:20261004.33810fcA

Immutable. This exact content never changes and is served at /api/v1/blob/f6b37e46484f56f4.

---
name: source-to-skill
description: Turn a YouTube video, playlist or channel, podcast or audio/video file (local Whisper), academic paper (PDF / arXiv URL), book (EPUB, or PDF book via --type book), web article, or GitHub repository - or several of them at once - into an installable agent skill, and refresh such skills later. Use when the user runs /source-to-skill, or asks to convert a video, talk, lecture, podcast, episode, recording, playlist, course, channel, paper, PDF, book, EPUB, article, blogpost, or GitHub repo into a skill / structured reference, to merge sources into one topic skill, or to update a skill made from a playlist or channel.
---

# source-to-skill

Turn a knowledge source into a structured agent skill the user can load on
demand. Supported sources: YouTube video, playlist and channel URLs,
podcasts and audio/video (Apple Podcasts, direct media URLs, local files,
any yt-dlp site via `--type audio`), arXiv URLs, local PDF papers, books
(EPUB files, or PDF books via `--type book`), web article URLs, and GitHub
repository URLs.

Usage:

- `/source-to-skill <url-or-file> [skill-slug]` — one source, one skill.
- `/source-to-skill <source> <source> ... [skill-slug]` — several sources,
  one topic skill (see "Several sources" below).
- `/source-to-skill update <skill-dir>` — refresh a skill (see "Refresh").

## Step 1 — Extract

Run from this skill's directory (the folder containing this SKILL.md —
`scripts/` and `tools/` live next to it):

    python3 scripts/extract.py "<source>"

- `.epub` files are detected as books automatically. A `.pdf` defaults to
  the paper parser — when the PDF is a book, add the override:
  `python3 scripts/extract.py "<source>" --type book`. If it is unclear
  whether a PDF is a paper or a book, ask the user before extracting.
- `youtube.com/playlist?list=...` URLs are detected as playlists. A
  `watch?v=...&list=...` URL stays a single video — add `--type playlist`
  to extract the whole playlist instead; if it is unclear which the user
  wants, ask before extracting.
- In a playlist, videos without captions are skipped with a stderr warning
  and listed in `metadata.json` under `skipped` — report skipped videos to
  the user; extraction fails only when no video has usable captions.
- Channel URLs (`youtube.com/@handle`, `/channel/...`) extract as a
  playlist of the latest 20 uploads (`metadata.json` has
  `"kind": "channel"`); pass `--limit N` for more or fewer. `--limit` also
  caps a long playlist.
- Videos without captions are transcribed locally with Whisper when a
  backend is installed (`--transcribe` forces it even with captions).
  Apple Podcasts links, direct `.mp3`/`.m4a`/... URLs, and local audio or
  video files are detected as `audio` and always transcribed; any other
  page with a video or audio track (Vimeo, SoundCloud, TED, ...) needs
  `--type audio`. Transcription takes a few minutes per hour of audio —
  say so before starting. A different model can be set with the
  `SOURCE_TO_SKILL_WHISPER_MODEL` environment variable.
- Bare `github.com/<owner>/<repo>` URLs are detected as repos (deeper
  paths are not); any other `http(s)` URL is treated as a web article.
- On dependency errors, run `python3 scripts/extract.py --check` and show the
  user the install hints. Do not install anything without asking.
- On any other ERROR, report it verbatim and stop.
- On success the command prints JSON with `work_dir`, `title`, `est_tokens`,
  and `segments`. All extracted content is in `<work_dir>/full_text.txt` and
  `<work_dir>/metadata.json`; `<work_dir>/source.json` records what was
  extracted so the skill can be refreshed later.

## Step 2 — Confirm cost

Tell the user the title, source type, and `est_tokens`, and ask to proceed.
Generation reads the full text once; skills built from it cost a fraction of
that per future question.

## Step 3 — Analyze structure

Read `metadata.json`. For large sources (over ~40k est_tokens) do NOT read
`full_text.txt` in one go — read it segment by segment using the `offset`
values (character offsets, not bytes; each segment's text runs to the next
segment's offset). Above ~100k est_tokens, if your host can run subagents,
hand each one a range of segments to distill and assemble the results
yourself.

## Step 4 — Choose install target

Ask the user where to install (default first):

1. `~/.claude/skills/<slug>/` (Claude Code, user-level)
2. `~/.agents/skills/<slug>/` (cross-agent)
3. `~/.copilot/skills/<slug>/` (GitHub Copilot CLI)
4. `./.claude/skills/<slug>/` (this project only, Claude Code)
5. `./.agents/skills/<slug>/` (this project only, cross-agent)
6. `./.github/skills/<slug>/` (this project only, GitHub Copilot)

`<slug>` is the second argument if given, else slugified from the title.

## Step 5 — Generate

Always write in English, regardless of source language. Extract structure —
frameworks, decision rules, anti-patterns, concrete numbers — never padded
summaries. Front-load the most important content in SKILL.md and keep it
under ~4k tokens; support files carry the detail.
A support file must carry content SKILL.md does not; for a small source
(under ~3k est_tokens) skip files that would only repeat it. Short quotes
(two sentences at most) are fine in any skill; never long passages.

When `metadata.json` says `"captions": "auto"`, the transcript is machine
captions: fix names that are unambiguously misheard (a model, a person,
a product the context makes certain) and leave anything uncertain
generic — never guess a fact.

For `source_type: youtube`:

- `SKILL.md` — frontmatter (name = slug; description = what the video
  teaches and when to load this skill), core ideas, then a segment index
  table: segment title, one-line takeaway, link `segments/NN-<slug>.md`.
- `segments/NN-<slug>.md` — one per segment, first line is the deep link
  `<origin>&t=<start_s>s` (use `?t=` if the origin URL has no query string),
  then the distilled content of that segment. Merge segments under ~60
  seconds into their neighbour. Inline `[t=Ns]` markers in the text mark
  moments inside a segment — use them to link a specific claim or quote
  to its own second, not just the segment start. Segment boundaries can
  split a sentence; attach the fragment to the segment it belongs to.
- `cheatsheet.md` — actionable steps, decision rules, and named techniques
  from the whole video.

For `source_type: audio` (a podcast episode, talk, or recording): the same
files as a video. Each segment file opens with
`deep_link_template` with `{s}` replaced by `start_s` when that field is
not null, otherwise with the `[hh:mm:ss]` timestamp and the `origin`.
SKILL.md names the show or speaker (`channel`) and, for conversations,
attributes claims to who made them when the transcript makes it clear.

For `source_type: playlist` (a course; `"kind": "channel"` is a channel —
describe what the channel teaches rather than a course order):

- `SKILL.md` — frontmatter as above, course overview (what the course
  teaches and in what order), then a lesson index table: lesson, one-line
  takeaway, link `lessons/NN-<slug>.md`.
- `lessons/NN-<slug>.md` — one per video, numbered in playlist order; the
  first line is the video URL (the segment's `url` field), then the
  distilled content of that lesson, linking key moments as
  `<url>&t=<N>s` from the transcript's inline `[t=Ns]` markers.
- If the playlist is not one coherent course (unrelated videos, a part 2
  without its part 1), say so in the overview instead of inventing an
  order.
- `cheatsheet.md` — actionable steps, decision rules, and named techniques
  across the whole course.

For `source_type: paper`:

- `SKILL.md` — frontmatter as above, TL;DR (3 sentences max), key claims
  each with its supporting evidence and section reference, file index.
- `methods.md` — how the work was done; enough detail to assess validity.
- `findings.md` — results with concrete numbers and conditions.
- `limitations.md` — stated limitations plus caveats evident from methods.
- `glossary.md` — terms alphabetically, each with a one-line definition.
- `citations.md` — how to cite this paper (title, authors, year, DOI when
  present in metadata.json) and the reference list from `references`.

For `source_type: book`:

- `SKILL.md` — frontmatter as above, the book's core mental models and
  frameworks front-loaded, then a chapter index table: chapter, one-line
  takeaway, link `chapters/NN-<slug>.md`.
- `chapters/NN-<slug>.md` — one per chapter (numbered in reading order),
  loaded on demand: the chapter's frameworks, arguments, and concrete
  examples — not a retelling.
  Segments marked `"front_matter": true` (contents, contributors,
  dedications) get no chapter file; mention a license
  page in one line.
- `glossary.md` — key terms alphabetically, each with a one-line definition
  and the chapter it comes from.
- `cheatsheet.md` — decision rules, named techniques, and anti-patterns
  from the whole book.

For `source_type: article`:

- `SKILL.md` — frontmatter as above, a byline (author and date when
  known — check the text if `metadata.json` has none), the article's
  thesis, then its key claims each with the points supporting it, and a
  link to the original article (the `origin` URL).
- `highlights.md` — the passages worth keeping, as short quotes.

For `source_type: repo`:

- `SKILL.md` — frontmatter as above, what the project does, how to install
  it, the core usage patterns, then a doc index table linking `guides/*.md`.
- `guides/<area>.md` — one per doc area (group segments by topic, not one
  file per source doc): setup, configuration, APIs, workflows — distilled,
  not a file dump.
- `cheatsheet.md` — commands and code snippets from across the docs.

Every single-source skill: copy `<work_dir>/source.json` into the skill
directory unchanged, so it can be refreshed later.

## Step 6 — Verify

Do not trust that generation "looked done":

1. Every file promised by the SKILL.md index exists and is non-empty.
2. Run: `python3 tools/validate_skill.py <install-dir>/<slug>` — must print
   `OK: skill is valid`. Fix any FAIL lines and re-run.
3. For video skills, spot-check one deep link timestamp against
   metadata.json; for playlist skills, spot-check one lesson's video URL.

Then tell the user the skill name, where it was installed, and one example
question to try against it.

## Several sources → one topic skill

When the user passes more than one source (or asks to merge sources on one
topic):

1. Extract each into its own work dir:
   `python3 scripts/extract.py "<source>" --work-dir <tmp>/source_skill_topic/NN`
   (NN = 01, 02, ... in the order given). Report failures per source and
   continue with the rest only if the user agrees.
2. Confirm cost once, with the sum of `est_tokens` and one line per source.
3. Generate (slug = given, else from the shared topic):
   - `SKILL.md` — frontmatter as above; the synthesized core ideas, each
     tagged with the sources that support it (`[S1]`, `[S2]`); then a
     sources table: id, title, type, one-line takeaway, link
     `sources/NN-<slug>.md`.
   - `sources/NN-<slug>.md` — one per source, the first line its origin:
     that source type's content condensed into one file, with the files
     its template would create as `##` sections (deep links and
     timestamps included).
   - `disagreements.md` — where sources contradict each other, use
     different definitions, or give different numbers: each point states
     both positions with their source ids. Never average them into one
     claim. If they agree throughout, say so in one line.
   - `cheatsheet.md` — actionable steps across all sources, each tagged
     with its source ids.
   - Copy each work dir's `source.json` to `sources/NN-<slug>.source.json`
     (topic skills have no top-level `source.json`; refresh one source by
     re-extracting it and comparing against its own manifest).
4. Verify as in Step 6.

## Refresh an existing skill

For `/source-to-skill update <skill-dir>` (most useful for playlists and
channels that keep growing):

1. Read `<skill-dir>/source.json`. Missing → the skill predates refresh
   support; tell the user and stop.
2. Re-extract the same source with the same options into a fresh dir:
   `python3 scripts/extract.py "<source>" [--type T] [--limit N] [--transcribe] --work-dir <tmp>/source_skill_update`
   using the manifest's `source` and `options`.
3. Run `python3 tools/diff_source.py <skill-dir> <tmp>/source_skill_update`.
   No `added` entries → tell the user the skill is up to date and stop.
4. Show the added (and removed) items with the new `est_tokens`, ask to
   proceed, then generate only the added lessons/segments (number new
   files by their `position`), add them to the SKILL.md index, extend the
   cheatsheet, and leave existing files untouched. Never delete files for
   removed items — list them for the user instead.
5. Replace `<skill-dir>/source.json` with the new one and verify as in
   Step 6.