Local-first YouTube AI CLI: download, transcribe (captions -> whisper), embed in LanceDB, discover subscriptions, and summarize/highlight/Q&A.
Project description
yt-mem-ai — YouTube AI CLI
Install
# zero-install run (recommended)
uvx yt-mem-ai --help
# or bootstrap uv + warm the cache
curl -LsSf https://raw.githubusercontent.com/dasein108/yt-mem-ai/main/install.sh | sh
The desktop UI lives in a separate repo: yt-mem-ai-desktop.
It depends on this yt-mem-ai package and runs its own local REST API.
Download YouTube audio, transcribe (captions → faster-whisper fallback), store everything in an embedded LanceDB with per-chunk embeddings, discover subscription uploads, and search your library semantically. Summaries, highlights, and Q&A are produced by Claude Code skills, not an API.
Setup
uv sync --extra dev
cp .env.example .env # fill WEBSHARE_* + YT_COOKIES_BROWSER; pick embedding backend
Config (.env): YT_STORE_PATH (LanceDB dir), YT_EMBEDDING_BACKEND=local|openai,
YT_EMBEDDING_MODEL, YT_CHUNK_TARGET_S, OPENAI_API_KEY (openai backend),
WEBSHARE_PROXY_*, YT_COOKIES_BROWSER.
Proxy / VLESS: YT_USE_WEBSHARE defaults off. If you already run a
system-level proxy/VPN (VLESS/Xray etc.), leave it off — traffic rides that
tunnel. Stacking the Webshare proxy on top breaks the authenticated
subscription feed (its CONNECT tunnel returns 405). Only set
YT_USE_WEBSHARE=true if you have no other proxy and YouTube rate-limits your
raw IP. Discover tuning: YT_DISCOVER_FEED_LIMIT (newest-N cap, default 60),
YT_DISCOVER_OVERLAP_S (incremental overlap, default 3600), YT_DISCOVER_TIMEOUT_S.
Commands
yt-ai fetch <url> # download + transcribe + embed + store one video
yt-ai fetch <url> --captions-only # captions only: no audio download / no whisper (fails if none)
yt-ai transcript <url> # same pipeline
yt-ai discover # new subscription uploads (--after/--deep/--min-duration/--json); incremental by default
yt-ai fetch-pending # batch-fetch pending 'discovered' videos (since --since, default today; --limit)
yt-ai list # list stored videos (--status/--since/--json)
yt-ai show <video_id> # metadata + transcript (--json)
yt-ai status # counts by status
yt-ai search "<query>" # semantic search (--hybrid/--fts/--vector, -k N)
yt-ai save-summary <id> "<summary>" --highlights '<json>' --qa '<json>' # persist a summary (used by skills)
yt-ai like <video_id> # mark liked (feeds recommendations)
yt-ai dislike <video_id> # mark disliked
yt-ai recommend # rank your unrated fetched videos by taste (--limit/--json)
yt-ai compile # deep-linked highlights doc, budget-bounded (--since/--max-minutes/--json/--out)
yt-ai supercut # video reel of highlights, re-downloaded + labeled (--since/--max-minutes/--out/--keep-clips)
Rate & recommend
Like/dislike videos you've fetched (yt-ai like <id> / dislike <id>), then
yt-ai recommend ranks your other fetched-but-unrated videos by similarity to
what you liked (minus what you disliked), using their transcript embeddings.
Before you've liked anything, it falls back to most-recently-published.
Daily routine
yt-ai discover # find new subscription uploads → 'discovered'
yt-ai fetch-pending # download+transcribe+embed today's batch (robust, skips failures)
# then in Claude Code:
/daily-digest # per-video summaries + digests/YYYY-MM-DD.md
yt-ai compile # compile the day's highlights into a deep-linked markdown you can click into
yt-ai discover is incremental: it pulls the newest feed entries (one flat
call, capped by YT_DISCOVER_FEED_LIMIT), stamps each with an approximate
timestamp (yt-dlp youtubetab:approximate_date), and keeps only those newer
than the last run's stored high-water mark minus a 1h overlap
(YT_DISCOVER_OVERLAP_S) — so hour-rounded dates never miss a boundary video,
and already-processed videos (is_seen) are filtered out. Pass --after YYYY-MM-DD to override the cutoff manually. Full per-video metadata
(description, tags, exact time) is fetched later at ingest, not during discover.
yt-ai compile builds compilations/<DATE>.md: each highlight from the day's
summarized videos becomes a deep link (watch?v=ID&t=<start>s) that jumps
straight to its moment, newest-video-first and budget-bounded by
--max-minutes (default 20). Fast — no downloading, just the same
compile_highlights selection rendered as markdown.
yt-ai supercut renders that same highlight selection as an actual video
reel instead of a doc: it re-downloads each highlight's section (720p,
yt-dlp --download-sections), burns a label onto each clip (title/timestamp),
and concats them into one mp4 — so it needs network access and a local
ffmpeg, and is much slower than compile. Output is
supercuts/<since-or-today>.mp4 plus a sidecar supercuts/<...>.mp4.refs.md
listing each rendered clip's source link (and any clips skipped because their
download/render failed). Use compile for a quick clickable digest; use
supercut when you want a shareable video.
Single video on demand: yt-ai fetch <url> then the /summarize-video skill.
Logging
The CLI writes structured JSON events to logs/common.jsonl (via
obs.log_event/blog) — one object per line, {ts, source, level, event, msg, ...ctx}. Override the path with YT_LOG_FILE; it's gitignored. Inspect with jq:
jq -c 'select(.level=="error")' logs/common.jsonl # every error
tail -f logs/common.jsonl | jq -c '{ts,event,msg}' # live tail, compact
Tests
uv run pytest -q # offline unit tests (fake embedder)
YT_RUN_INTEGRATION=1 uv run pytest -q # + real sentence-transformers integration
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yt_mem_ai-0.1.0.tar.gz.
File metadata
- Download URL: yt_mem_ai-0.1.0.tar.gz
- Upload date:
- Size: 298.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2ddca4518a5d5a82ad1e2439db20b232ad0e3e8a92b869958bc72561ea811cb
|
|
| MD5 |
61d1b45887633e1c625d52e5a31666da
|
|
| BLAKE2b-256 |
d920ebf2718c4e1b7f84200fa1f4ed48ac711483b14401ac1c0f846d4cc7fe4d
|
Provenance
The following attestation bundles were made for yt_mem_ai-0.1.0.tar.gz:
Publisher:
publish-pypi.yml on dasein108/yt-mem-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
yt_mem_ai-0.1.0.tar.gz -
Subject digest:
b2ddca4518a5d5a82ad1e2439db20b232ad0e3e8a92b869958bc72561ea811cb - Sigstore transparency entry: 2248618119
- Sigstore integration time:
-
Permalink:
dasein108/yt-mem-ai@42b8663593b56317bbd1ec6f1d3f28e219dd0503 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/dasein108
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@42b8663593b56317bbd1ec6f1d3f28e219dd0503 -
Trigger Event:
push
-
Statement type:
File details
Details for the file yt_mem_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: yt_mem_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 30.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8e60f0e5055acf3241fec45cc8671b02fb7bcfe37f762d897f4e5c8bd6bcfc3
|
|
| MD5 |
961f03bc1ecc9c471be3200370579cac
|
|
| BLAKE2b-256 |
facd917b4b3f32fddaab8d9f12658f6d25a21f66fe10260436b449124ee9d8bd
|
Provenance
The following attestation bundles were made for yt_mem_ai-0.1.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on dasein108/yt-mem-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
yt_mem_ai-0.1.0-py3-none-any.whl -
Subject digest:
c8e60f0e5055acf3241fec45cc8671b02fb7bcfe37f762d897f4e5c8bd6bcfc3 - Sigstore transparency entry: 2248618423
- Sigstore integration time:
-
Permalink:
dasein108/yt-mem-ai@42b8663593b56317bbd1ec6f1d3f28e219dd0503 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/dasein108
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@42b8663593b56317bbd1ec6f1d3f28e219dd0503 -
Trigger Event:
push
-
Statement type: