YouTube Skill
Upload videos, manage playlists, search, and interact with YouTube.
Setup
Uses Google OAuth (same as gmail-skill). Enable YouTube Data API v3 in your Google Cloud project.
If you have gmail-skill set up, this should work. Otherwise:
- Enable YouTube Data API v3 at console.cloud.google.com
- Create OAuth credentials, Desktop app type, and download the JSON
- Save to
~/.claude/skills/youtube-skill/credentials.json
Dependencies. This machine's Homebrew Python is PEP 668 externally-managed, so a plain
pip install fails with externally-managed-environment. The libs live in a sibling venv:
uv venv ~/.claude/skills/youtube-skill/.venv --python 3.13
uv pip install --python ~/.claude/skills/youtube-skill/.venv/bin/python \
google-api-python-client google-auth-oauthlib google-auth-httplib2
youtube_skill.py re-execs into that venv automatically, so you still invoke it as plain
python3 ~/.claude/skills/youtube-skill/youtube_skill.py ... — no activation needed.
Commands
Channel & Videos
python3 ~/.claude/skills/youtube-skill/youtube_skill.py me
python3 ~/.claude/skills/youtube-skill/youtube_skill.py channels
python3 ~/.claude/skills/youtube-skill/youtube_skill.py videos [--channel CHANNEL_ID] [--limit N]
python3 ~/.claude/skills/youtube-skill/youtube_skill.py video VIDEO_ID
Search
python3 ~/.claude/skills/youtube-skill/youtube_skill.py search "query" [--limit N] [--type video|channel|playlist]
Playlists
python3 ~/.claude/skills/youtube-skill/youtube_skill.py playlists [--channel CHANNEL_ID]
python3 ~/.claude/skills/youtube-skill/youtube_skill.py playlist PLAYLIST_ID [--limit N] [--all]
python3 ~/.claude/skills/youtube-skill/youtube_skill.py create-playlist --title "Name" [--privacy public|private|unlisted]
python3 ~/.claude/skills/youtube-skill/youtube_skill.py add-to-playlist PLAYLIST_ID --video VIDEO_ID
python3 ~/.claude/skills/youtube-skill/youtube_skill.py remove-from-playlist PLAYLIST_ITEM_ID
Export without any Google Cloud setup (fastest)
The OAuth path below needs ~15 minutes of Cloud console clicking. To skip all of it:
- https://takeout.google.com → Deselect all → tick YouTube and YouTube Music → All YouTube data included → keep only playlists → export.
- The zip contains
Liked videos.csvand one CSV per playlist - video ids, no titles. - Resolve the titles and build a crate:
python3 ~/.claude/skills/youtube-skill/youtube_skill.py import-takeout \
"~/Downloads/Takeout/YouTube and YouTube Music/playlists/Liked videos.csv" \
--name friday-yt
import-takeout resolves each id through YouTube's oEmbed endpoint, which needs no API
key, no OAuth and has no quota. It reports ids it could not resolve (deleted or private
videos) rather than dropping them silently. --workers (default 8) controls concurrency.
Liked videos (earmarked tracks)
python3 ~/.claude/skills/youtube-skill/youtube_skill.py liked [--limit 50] [--all]
Returns your thumbs-upped videos already parsed into artist / title / mix, in crate
shape. --all follows pagination; without it you get one page of 50.
Export a DJ crate
python3 ~/.claude/skills/youtube-skill/youtube_skill.py export-crate --name friday-yt --all
python3 ~/.claude/skills/youtube-skill/youtube_skill.py export-crate --name friday-yt --playlist "https://youtube.com/playlist?list=PL..." --all
Writes ~/.claude/skills/beatport-skill/crates/<name>.json, then:
python3 ~/.claude/skills/beatport-skill/beatport_skill.py match ~/.claude/skills/beatport-skill/crates/friday-yt.json
YouTube crates are lower-confidence than Spotify ones. YouTube has no structured
artist/title and no ISRC, so artist/title are parsed heuristically from the video title
— stripping "(Official Video)", "[HD]", "| Out Now" and splitting on a dash, falling back
to the channel name (a " - Topic" channel is reliable). Every track keeps its
raw_title so you can check the parse, and export-crate reports unparsed_artist for
titles it could not split. Review those before buying anything; Beatport matching for these
is fuzzy-only.
Comments
python3 ~/.claude/skills/youtube-skill/youtube_skill.py comments VIDEO_ID [--limit N]
python3 ~/.claude/skills/youtube-skill/youtube_skill.py comment VIDEO_ID --text "Great video!"
python3 ~/.claude/skills/youtube-skill/youtube_skill.py reply COMMENT_ID --text "Thanks!"
Subscriptions
python3 ~/.claude/skills/youtube-skill/youtube_skill.py subscriptions
python3 ~/.claude/skills/youtube-skill/youtube_skill.py subscribe CHANNEL_ID
python3 ~/.claude/skills/youtube-skill/youtube_skill.py unsubscribe SUBSCRIPTION_ID
Upload
python3 ~/.claude/skills/youtube-skill/youtube_skill.py upload --file video.mp4 --title "My Video" [--description "..."] [--privacy private]
Video IDs
Found in URLs: youtube.com/watch?v=VIDEO_ID
Privacy Options
public- Anyone can seeunlisted- Only people with linkprivate- Only you
Output
All commands output JSON.
Notes
liked,playlist --all, andexport-cratefollow pagination; other listings return a single page.- The YouTube Data API has a 10,000 unit/day quota and
searchcosts 100 units per call. Listing playlist items and liked videos is 1 unit, so crate exports are cheap — repeatedsearchis what burns the quota. - Watch Later and history are not readable through the API (YouTube removed that access years ago). Use liked videos or a real playlist as the earmarking mechanism instead.