AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Media Distill

skill-codexis-claude-media-skills-media-distill · by codexis

Fetches a YouTube video transcript and creates a zettelkasten note. Use when the user shares a YouTube link and asks to save / summarize / take a note (also works with short commands `w/s/b/a <url>`). Triggers on phrases like 'save this', 'make a note', 'bookmark', 'save for later', 'just export', 'summary'.

No reviews yet
0 installs
33 views
0.0% view→install

Install

$ agentstack add skill-codexis-claude-media-skills-media-distill

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-codexis-claude-media-skills-media-distill)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Media Distill? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

YouTube → Zettelkasten

Turns a YouTube video into an atomic Zettelkasten note and stores it under Video/.

When to use

  • User sends a YouTube URL and asks for a summary / note / recap.
  • User says "save this", "make a note", "bookmark this", "save for later", "just export" about a video.
  • You need to distill knowledge from a lecture, podcast, or tutorial.

Determining status from the user's command

Status is derived from the meaning of the message or from a short command prefix before the link.

| Command | Synonyms / intent | status | |----------------------|-------------------------------------------------|--------------| | w , s | "save", "make a note", "watched" | watched | | b | "bookmark", "save for later", "watch later" | bookmarked | | a | "archive", "just export", "source", "mentioned" | archived |

If no command prefix is given — infer from the phrasing. Default: watched.

Configuration

Edit these settings directly in this file before using the skill.

| Setting | Default | Description | |--------------------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | VAULT_ROOT | . | Path to your Obsidian vault root (where Video/, Book/, Person/, Author/ folders live). Can be absolute or relative to the repo root. Example: ~/notes or /home/user/vault. | | NOTE_LANG | transcript | Language for note content. transcript = match the video's transcript language. Or set a fixed locale: en, ru, de, etc. | | TRANSCRIPT_LANGS | ru,en | Comma-separated preferred transcript languages passed to --lang. Order = priority. | | PYTHON | python3 | Python executable to use. Change to .venv/bin/python3 if using a local venv. |

Current values:

VAULT_ROOT = .
NOTE_LANG = transcript
TRANSCRIPT_LANGS = ru,en
PYTHON = python3

To reconfigure — edit the three lines inside the code block above. No other files need to change.

Dependencies

pip install -r .claude/skills/media-distill/scripts/requirements.txt

Handling multiple URLs

If the user's message contains several YouTube URLs — process each one sequentially, creating a separate note per URL using the process below. Report intermediate progress to the user.

Playlists, shorts, live

  • Shorts (/shorts/) — treated as regular videos.
  • Playlists (?list=...) — not supported. Ask the user for a specific video URL from the playlist.
  • Live recording — treated as a regular video if subtitles are available. For an active live stream the transcript is usually unavailable.

Process (step by step)

1. Fetch transcript and metadata

 .claude/skills/media-distill/scripts/youtube_export.py  --lang 

The script prints JSON to stdout:

{
  "video_id": "abc123",
  "url": "https://www.youtube.com/watch?v=abc123",
  "transcript": "full text...",
  "lang": "ru",
  "title": "Video title",
  "channel": "Channel name",
  "upload_date": "2024-03-15",
  "duration_sec": 1080,
  "channel_url": "https://www.youtube.com/channel/UC...",
  "channel_name": "Channel name",
  "channel_handle": "@handle",
  "channel_description": "Channel description...",
  "safe_title": "Video title",
  "safe_channel_name": "Channel name"
}

On error — a message in stderr, exit code 1.

The transcript is not saved to the vault as a separate file — it is only used to generate the note, then discarded.

Channel metadata is cached in scripts/.cache/cache.sqlite (30-day TTL) — repeated videos from the same channel reuse cached data. The cache file is gitignored.

2. Check for filename collisions

Before creating Video/.md, check whether the file exists.

If the file exists — ask the user via AskUserQuestion:

  • Skip — note already exists, do nothing.
  • Overwrite — recreate the note (manual edits will be lost).
  • Add video_id suffix — create Video/ ().md.

Same rule applies to Book/.md. For Person/ and Author/ a collision simply means "file exists" and should not be overwritten (see §3 and §4).

3. Check and create the Person note

Use safe_channel_name from the JSON as both the filename and the wikilink target.

Check whether Person/.md exists:

  • If it exists — continue, use [[]] as the author reference. The Person note is not overwritten (even if channel_description has changed).
  • If missing — create it from .claude/skills/media-distill/templates/person.md, substituting fields from the JSON.

Placeholders in person.md:

| Placeholder | Source (JSON) | |---------------------------|---------------------------------------------------| | {{channel_handle}} | channel_handle (channel handle, @name format) | | {{channel_url}} | channel_url | | {{channel_description}} | channel_description |

4. Create the Video note

Pick the template by status:

| status | Template | |--------------|-------------------------------------------------------------------------------------------------------------------------------| | watched | .claude/skills/media-distill/templates/video.md (full distillation) | | bookmarked | .claude/skills/media-distill/templates/video.md (full distillation — produce it now, even if the user hasn't watched yet) | | archived | .claude/skills/media-distill/templates/video-archived.md (minimal stub — export book/author notes, skip video distillation) |

Placeholders (both video.md variants):

| Placeholder | Source | |-------------------------|-------------------------------------------------------------------------------| | {{url}} | url from JSON | | {{safe_channel_name}} | safe_channel_name from JSON (sanitized — must match the Person/ filename) | | {{upload_date}} | upload_date from JSON (video publish date, YYYY-MM-DD) | | {{save_date}} | today's date in YYYY-MM-DD | | {{status}} | watched / bookmarked / archived (from user command) | | {{duration_sec}} | duration_sec from JSON | | {{lang}} | lang from JSON (transcript language) | | {{title}} | title from JSON (original title used as the note heading) |

Filename: Video/.md (field safe_title from the JSON).

Requirements for full-distillation notes (watched / bookmarked):

  • Note language = determined by NOTE_LANG (see Configuration). If transcript — use the video's transcript language (lang field). If a fixed locale is set — write the entire note in that language regardless of the transcript.
  • Each idea is atomic: one section = one thought.
  • No retelling — only distillation of meaning.
  • Tags as #word, wikilinks as [[concept]].
  • Forward-wikilinks on books/authors ([[Book Title]], [[Author Name]]) in the body are the trigger for step 5. Write them in the source language as they sound in the video — do not try to guess the canonical English title. Alias resolution happens in step 5.

Requirements for archived notes:

  • 1–2 sentences of context — why this note exists as a source (what is referenced, what it links to).
  • No "Key ideas", "Practice", "Related" sections — the note is a stub for backlinks.
  • Primary purpose: capture book/author references so step 5 runs and Book/Author notes are saved.
  • If the video mentions books: populate the "Books mentioned" section — one line per book in the format [[Title]] — [[Author Name]]. Write the title and author as they appear in the video (source language); step 5 resolves them to canonical filenames. If no books — omit the section entirely.

5. Post-process — book/author references

Trigger: any forward [[...]] wikilink in the Video note body (context sentence for archived, body / Related section for watched / bookmarked) that points to a book or a book's author. Always run this step when such wikilinks exist — book notes are saved unconditionally.

Action: for each such wikilink pass through book-flow.md, passing the tentative name (exactly as written in the wikilink) as the input. Several books in one video → one pass per book.

Wikilink rewrite. After book-flow.md finishes and the canonical Book/Author filenames are known, rewrite each matching wikilink in the Video note to Obsidian pipe syntax [[canonical|tentative]] — e.g. [[La Cinquième Discipline]][[The Fifth Discipline|La Cinquième Discipline]]. Reason: Obsidian does not auto-resolve [[alias]] through the aliases: frontmatter field inside wikilinks; the pipe form is required for the link to navigate to the canonical file while keeping the source-language display. If tentative == canonical, leave the wikilink as is.

Common errors

| Error | Cause | Resolution | |-------------------------------|----------------------------------------|---------------------------------------------------| | 403 Forbidden | YouTube is blocking the IP | Run locally, not in CI/cloud | | TranscriptsDisabled | Author disabled captions | Transcript unavailable | | NoTranscriptFound | No captions for the requested language | Add --lang en | | Empty transcript | Private video or no captions | Check video availability | | Sign in to confirm your age | Age-restricted | Inform the user — the script does not bypass auth |

Skill files

media-distill/
├── SKILL.md              ← this file (video flow, triggers, common errors)
├── book-flow.md          ← book recommendations flow (templates, list/null fields)
├── templates/
│   ├── person.md         ← template for Person/
│   ├── video.md          ← template for Video/ (watched / bookmarked)
│   ├── video-archived.md ← template for Video/ with status: archived
│   ├── author.md         ← template for Author/
│   └── book.md           ← template for Book/
└── scripts/
    ├── youtube_export.py ← fetches video/channel data
    ├── book_lookup.py    ← looks up book metadata
    ├── cache.py          ← SQLite cache for channel metadata (30-day TTL)
    ├── utils.py          ← sanitize_filename() — shared helper
    ├── requirements.txt  ← dependencies
    └── .cache/           ← cache.sqlite (runtime, gitignored)

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.