Install
$ agentstack add skill-tga-cheetung-yt-digest-yt-digest Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ✓ 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.
About
yt-digest
Process a YouTube video into a single markdown research note in your notes vault. Drop a link, get a digest that's faster to consume than the video.
Output contract
- Digest:
vault/research/youtube/.md— frontmatter + TL;DR + numbered takeaways (each with timestamp deep-link + screenshot if visual) + collapsed transcript - Screenshots:
vault/attachments/youtube//frame-MM-SS.png— embedded in digest via Obsidian's![[...]]syntax - Staging:
/tmp/yt-digest//— video + raw VTT, deleted at end of run
Headless-safe: all inputs come from CLI args, no interactive prompts, deterministic output path so an orchestrator can read the result back.
Workflow
0. Parse args
Required: a YouTube URL (any form — youtu.be/x, youtube.com/watch?v=x, youtube.com/shorts/x).
Optional flags:
--no-screenshots— skip video download + frame extraction (transcript-only, ~$0.01, ~5s)--tags a,b,c— add to frontmattertags:list--slug name— override auto-generated slug
If no URL is provided, abort with a one-line error — do NOT prompt the user (this skill runs headless).
1. Fetch transcript + video
mkdir -p /tmp/yt-digest
META_JSON=$(.claude/skills/yt-digest/scripts/fetch.sh "$URL" "/tmp/yt-digest/staging-$$" ${NO_SCREENSHOTS:+--no-video})
Parse META_JSON (one-line JSON) for: id, title, channel, duration_seconds, upload_date (YYYYMMDD), slug, transcript_path, video_path.
Override slug if --slug was passed.
Set up paths:
WORK_DIR="/tmp/yt-digest/staging-$$"
ATTACH_DIR="vault/attachments/youtube/$SLUG"
DIGEST_PATH="vault/research/youtube/$SLUG.md"
mkdir -p "$ATTACH_DIR" "$(dirname "$DIGEST_PATH")"
If transcript_path is empty: YouTube has no captions for this video. Abort with: "No captions available for this video. Re-run with audio re-transcription (not yet implemented) or skip." Clean up $WORK_DIR before exiting.
2. Flatten the VTT
TRANSCRIPT_JSON=$(.claude/skills/yt-digest/scripts/parse_vtt.py "$TRANSCRIPT_PATH")
TRANSCRIPT_JSON is [{start_seconds, text}, ...] with rolling-caption duplicates removed.
3. Pick key learning moments
Read the full transcript. Identify 5-10 key moments that earn a bullet in the digest. Each moment is:
{
"start_seconds": 754,
"title": "Concise one-line insight (≤ 12 words)",
"quote": "Verbatim line from the transcript that earned this bullet",
"needs_screenshot": true,
"rationale": "Why a screenshot would help — e.g. 'slide showing the 6-bucket framework'"
}
Selection criteria:
- Concrete frameworks, models, or step-by-step processes
- Specific numbers, data points, or benchmarks
- Counterintuitive claims with reasoning
- Moments where the speaker references something on-screen ("as you can see here…", "this chart shows…", "the formula is…")
Set needs_screenshot: true ONLY when the speaker is clearly referencing a visual (slide, demo, chart, code). Pure talking-head insights get needs_screenshot: false.
Anti-patterns — don't pick:
- Intros, outros, sponsor reads, channel housekeeping
- Filler restatements ("so what I'm saying is…")
- Repeated points (pick the strongest framing only)
4. Extract frames
If --no-screenshots was passed, skip this step.
Collect timestamps where needs_screenshot: true:
.claude/skills/yt-digest/scripts/extract_frames.sh "$VIDEO_PATH" "$ATTACH_DIR" 754 1230 1890
Frames land as frame-MM-SS.png in $ATTACH_DIR.
5. Assemble the digest
Write $DIGEST_PATH using this exact structure:
---
source: youtube
url: https://youtube.com/watch?v=
channel:
title:
duration:
published:
digested:
tags: [youtube, research, ]
---
#
**Channel:** · **Length:** · **Published:** · [Watch ↗]()
## TL;DR
- 3-5 punchy bullets capturing the video's thesis. Each bullet stands alone.
## Key Takeaways
### 1. · [](&t=s)
![[frame-MM-SS.png]]
>
### 2.
...
## Open Questions
- 1-3 questions the video raises but doesn't answer, or things worth trying
- Skip this section if nothing concrete comes to mind — don't manufacture filler
## Full Transcript
Click to expand
[00:00] First line of transcript text. [00:08] Second line...
Notes on assembly:
&t=s— YouTube timestamp deep-link. Use&if URL already has?v=, else?t=.- Format duration as
H:MM:SSif ≥ 1hr, elseMM:SS. - The screenshot path is relative — Obsidian's
![[frame-MM-SS.png]]resolves via the vault's attachment folder config. If that fails for any reader, use the explicit form `` as fallback. - Full transcript block: timestamp each line as
[MM:SS]so future search lands you at the right second.
6. Cleanup
Use Python rather than rm -rf — Claude Code's safety policy hard-blocks rm -rf even when explicitly allowlisted, which would break headless dispatch:
python3 -c "import shutil, sys; shutil.rmtree(sys.argv[1], ignore_errors=True)" "$WORK_DIR"
This deletes the source MP4 + raw VTT. The vault keeps only: digest markdown + screenshots (~2-3 MB total per video).
7. Print result
Final line of output must be:
DIGEST:
Any orchestrator can parse this to surface the file back to the originating thread.
Cost
| Component | Cost per 30-min video | |---|---| | yt-dlp transcript + video | $0 | | Model digest pass (~7K in / 800 out) | ~$0.01–0.04 | | ffmpeg frame extraction | $0 | | Vault storage (digest + screenshots) | ~3 MB |
Source MP4 (~100 MB) is deleted in step 6.
Headless / remote dispatch
The skill writes to a deterministic path and prints DIGEST: as its final line, so it composes with any orchestrator that can shell out — cron, CI, or a chat bot. The pattern worth building: a Slack/Telegram bot that runs the skill on a pasted URL and posts the path (or the rendered TL;DR) back into the thread. "Drop a link in chat, get a digest in your vault" becomes a one-message workflow.
Model note for unattended runs: in a headless claude -p run, a small/cheap model will sometimes describe what the skill would do rather than invoking the scripts (turns burned, zero tool calls, nothing written). Route the unattended dispatch to a more capable model. The interactive run is fine on the cheap model.
Failure modes
- No captions: abort cleanly per step 1 — do not silently produce an empty digest.
- yt-dlp 403 / age-restricted: print the actual yt-dlp error and abort. Don't paper over with cookies-based workarounds without explicit user request.
- ffmpeg fails on a timestamp: log the failure but continue with the other frames. The digest still ships; the missing screenshot is just omitted (don't leave broken
![[...]]syntax). - Vault path collision: if
vault/research/youtube/.mdalready exists, append a-2suffix to the slug. Don't overwrite.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: tga-cheetung
- Source: tga-cheetung/yt-digest
- License: MIT
- Homepage: https://www.thegtmarchitects.com/lm/yt-digest
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.