From armory
Searches YouTube by keyword using yt-dlp to return structured video metadata: title, URL, channel, views, duration, upload date. Supports sorting by views or date client-side. No API keys needed.
npx claudepluginhub mathews-tom/armory --plugin armoryThis skill uses the workspace's default tool permissions.
Search YouTube by keyword and return structured video metadata — title, URL,
Implements Playwright E2E testing patterns: Page Object Model, test organization, configuration, reporters, artifacts, and CI/CD integration for stable suites.
Guides Next.js 16+ Turbopack for faster dev via incremental bundling, FS caching, and HMR; covers webpack comparison, bundle analysis, and production builds.
Discovers and evaluates Laravel packages via LaraPlugins.io MCP. Searches by keyword/feature, filters by health score, Laravel/PHP compatibility; fetches details, metrics, and version history.
Search YouTube by keyword and return structured video metadata — title, URL,
channel, views, duration, upload date. Uses yt-dlp for scraping with no API
keys or OAuth required.
uv tool install yt-dlp
Verify:
yt-dlp --version
yt-dlp "ytsearch10:claude code skills" --dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -r '[.title, .url, .channel, .view_count, .duration_string, .upload_date] | @tsv'
ytsearch10: — search YouTube, return 10 results (adjust number as needed)--dump-json — output metadata as JSON--flat-playlist — don't download, just list--no-warnings — suppress non-error outputyt-dlp "ytsearch5:claude code mcp servers" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq '{
title: .title,
url: .url,
channel: .channel,
views: .view_count,
duration: .duration_string,
upload_date: .upload_date,
description: (.description // "" | .[0:200])
}'
yt-dlp does not support server-side sort. To sort by views or date, capture all results and sort client-side:
# Sort by view count (descending)
yt-dlp "ytsearch20:AI agents 2026" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -s 'sort_by(-.view_count) | .[:10][] | {title, url, channel, views: .view_count}'
# Sort by upload date (newest first)
yt-dlp "ytsearch20:claude code tutorial" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -s 'sort_by(-.upload_date) | .[:10][] | {title, url, channel, upload_date}'
The number after ytsearch controls how many results to fetch:
| Pattern | Results |
|---|---|
ytsearch5:query | 5 results |
ytsearch10:query | 10 results (default recommendation) |
ytsearch20:query | 20 results |
ytsearch50:query | 50 results (slow, may hit rate limits) |
Recommendation: Fetch 15-20 results, then filter/sort client-side to the top N the user wants. This provides enough data for meaningful sorting without being excessive.
User provides search query
|
v
+---------------------+
| Step 0: Deps check |
+----------+----------+
v
+---------------------+
| Step 1: Search |
| (yt-dlp ytsearch) |
+----------+----------+
v
+---------------------+
| Step 2: Parse JSON |
| (jq formatting) |
+----------+----------+
v
+---------------------+
| Step 3: Present |
| results to user |
+---------------------+
yt-dlp "ytsearch${COUNT}:${QUERY}" \
--dump-json --flat-playlist --no-warnings 2>/dev/null
Extract relevant fields with jq. The full metadata object from yt-dlp contains
many fields; the useful subset for search results:
| Field | Description |
|---|---|
.title | Video title |
.url | Full YouTube URL |
.channel | Channel name |
.view_count | Total views (integer) |
.duration_string | Duration as H:MM:SS or MM:SS |
.upload_date | Upload date as YYYYMMDD |
.description | Video description (can be long — truncate) |
.like_count | Likes (may be null) |
.comment_count | Comments (may be null) |
Format as a markdown table for the user:
yt-dlp "ytsearch10:${QUERY}" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -s 'sort_by(-.view_count) | .[] | "| \(.title[:60]) | \(.channel) | \(.view_count) | \(.duration_string) | \(.upload_date) |"' -r
Prefix with a header row:
| Title | Channel | Views | Duration | Date |
|-------|---------|-------|----------|------|
# Only videos longer than 10 minutes (600 seconds)
yt-dlp "ytsearch20:deep dive AI agents" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -s '[.[] | select(.duration >= 600)] | sort_by(-.view_count) | .[:10][]'
# Only videos from the last 30 days
CUTOFF=$(date -v-30d +%Y%m%d 2>/dev/null || date -d "30 days ago" +%Y%m%d)
yt-dlp "ytsearch20:claude code" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -s --arg cutoff "$CUTOFF" '[.[] | select(.upload_date >= $cutoff)] | sort_by(-.view_count) | .[]'
# Search within a specific channel
yt-dlp "ytsearch10:skills site:youtube.com/c/ChannelName" \
--dump-json --flat-playlist --no-warnings 2>/dev/null
Or use the channel URL directly:
yt-dlp "https://www.youtube.com/@ChannelName/search?query=skills" \
--dump-json --flat-playlist --no-warnings 2>/dev/null
# Get just URLs for feeding into other tools (youtube-analysis, notebooklm)
yt-dlp "ytsearch10:claude code MCP" \
--dump-json --flat-playlist --no-warnings 2>/dev/null \
| jq -r '.url'
This skill produces URLs and metadata that feed into other skills:
notebooklm source add "URL"Example pipeline (manual steps, not automated):
/yt-search — discover 10 relevant videosnotebooklm source add or youtube-analysis| Error | Cause | Resolution |
|---|---|---|
| No results | Query too specific or misspelled | Broaden the search terms |
| Empty JSON | yt-dlp rate limited by YouTube | Wait a few minutes, retry |
yt-dlp: command not found | Not installed | uv tool install yt-dlp |
| Partial results | Some videos geo-blocked or private | Normal behavior; results are best-effort |
| Timeout | Network or YouTube slowness | Reduce result count or retry |
.like_count, .comment_count) may be null for certain videos. Always handle nulls in jq filters.