Turn videos, articles, posts, and voice notes into a searchable personal knowledge base.
ytk captures the things you watch and read, enriches them with Claude Haiku,
writes plain markdown notes into an Obsidian vault, and indexes everything
locally with ChromaDB. You can search it from the CLI, browse it in a local web
hub, or expose the vault to Claude Code through MCP.
It is built for people who still watch the video. The goal is not to replace attention with summaries; it is to make the exact tools, commands, names, timestamps, and personal annotations findable weeks later.
Most saved links become a graveyard. ytk turns each capture into a useful
memory:
- Save from where you already are: YouTube, web articles, Instagram, TikTok, Pinterest, iMessage, voice memos, and a local inbox.
- Keep the source inspectable: transcripts, metadata, thumbnails, extracted frames, and timestamped key moments stay linked to the original.
- Search by meaning, not filenames: embeddings are stored locally in ChromaDB for semantic search across sources and your own notes.
- Bring your own context: notes and annotations are embedded alongside the source so your reasons for saving something remain searchable.
- Use normal files: the long-term store is plain markdown in an Obsidian
vault, so the data is useful without
ytk.
flowchart LR
A[Capture] --> B[Fetch]
B --> C[Enrich]
C --> D[Write notes]
D --> E[Index]
E --> F[Retrieve]
flowchart TD
A[ytk] --> B[CLI]
A --> C[Local hub]
A --> D[Obsidian vault]
A --> E[MCP server]
B --> F[Capture commands]
B --> G[Search commands]
C --> H[Inbox]
C --> I[Embedding map]
E --> J[Vault tools]
Requires Python 3.11+, uv, and ffmpeg for voice
memos, frame extraction, and audio fallbacks.
git clone https://github.com/pablomoli/ytk
cd ytk
uv sync
uv run ytk --helpTo install the CLI globally:
uv tool install .
# after pulling repo changes
uv tool install --reinstall .Copy .env.example to .env and point ytk at your vault:
ANTHROPIC_API_KEY=sk-ant-...
OBSIDIAN_VAULT_PATH=/path/to/your/obsidian/vault
CHROMA_PATH=~/.ytk/chroma
# Optional, only for Instagram capture
INSTAGRAM_SESSIONID=
INSTAGRAM_PEER=Runtime settings live in ~/.ytk/config.yaml, which is created on first run.
It controls ingest filters, source fetch cadence, inbox annotation chips, hub
host and port, map colors, and interest-model settings. The hub also provides a
validated settings editor at /settings.
# Capture
ytk add https://www.youtube.com/watch?v=VIDEO_ID
ytk add <url> --note "why I saved this"
ytk ingest <article-url>
ytk feed urls.txt
ytk memo
# Retrieve
ytk search "that terminal TV demo"
ytk dive VIDEO_ID "the command he used"
ytk profile
ytk uiytk profile writes a machine-checkable portrait: every theme summary cites
vault evidence and every portrait claim additionally cites at least one item
captured within the decay half-life. Each full regeneration also prints
and persists a fixed-cohort visual ranking score (multi-positive nDCG), warning
when a comparable score drops beyond the configured tolerance. Run
uv run scripts/check_profile_grounding.py to audit the rendered profile.
ytk ui starts the local hub on port 6969.
The hub is a small local web app for capture, review, and exploration:
/shows recent ingests with thumbnails and enrichment tags./inboxcollects queued links and lets you add annotations before ingest./tagshelps merge tag variants produced by enrichment./maprenders a 3D UMAP projection of every text embedding, colored by provenance, with anchored cluster names that survive rebuilds./gardengrows procedural trees whose branch structure is the measured cluster hierarchy of each topic bucket — knowledge as a garden./settingsedits~/.ytk/config.yamlwith validation.
On macOS, ytk ui install registers the hub as a launchd daemon. Use
ytk ui status, ytk ui restart, and ytk ui uninstall to manage it.
packaging/macos/build_app.sh additionally wraps the daemon in a small
ytk.app bundle so permission prompts and Full Disk Access show "ytk" with
an icon instead of a bare python binary — and the TCC grant survives
package reinstalls because it keys on the app's launcher stub.
ytk ships an MCP server through the ytk-mcp entry point. It exposes tools
for vault reads, writes, semantic search, remembering facts, reindexing, and
visual similarity.
# with the CLI installed globally
claude mcp add --scope user ytk -- ytk-mcp
# or from a checkout
claude mcp add --scope user ytk -- uv run --directory /path/to/ytk ytk-mcpThis lets a Claude Code session search everything you have saved and write decisions or memories back into the vault.
Common commands:
| Command | Purpose |
|---|---|
ytk add <youtube-url> |
Ingest one YouTube video |
ytk ingest <url> |
Ingest a web article |
ytk feed urls.txt |
Batch ingest URLs |
ytk search "query" |
Search the whole vault semantically |
ytk dive VIDEO_ID "query" |
Search timestamped video segments |
ytk memo |
Record, transcribe, and route a voice memo |
ytk profile |
Synthesize, ground, and held-out-score an interest profile |
ytk ui |
Start the local hub |
Other commands include add-instagram, add-tiktok, add-pinterest, reels,
triage, review, graph, tags, remember, reindex, gc, snap,
index, dashboard, schedule, chat, visual index, and similar. Run
ytk --help for the full list.
- YouTube transcripts come from
youtube-transcript-apifirst, thenyt-dlpsubtitle fallback, then localfaster-whisperfor audio-only cases. - Enrichment uses
claude-haiku-4-5to produce a thesis, dense summary, key concepts, insights, tags, and timestamped key moments. - Text embeddings run locally on
Qwen/Qwen3-Embedding-0.6B(1024d, whole-document, instruction-aware: documents embed plain, queries carry a retrieval prefix). The encoder was chosen by a measured bake-off on the real corpus — 156 known-item queries, paired bootstrap, geometry gates — documented indocs/research/encoder-audit/. Encoder swaps are versioned as epochs: fresh collections, one migration pass, instant rollback. - Covers and frames embed with SigLIP-2 for visual similarity search.
- Markdown notes and media are written into your Obsidian vault.
- ChromaDB stores the local vector index.
- The only default external AI call is enrichment through the Anthropic API.
- Long-running jobs (migrations, re-embeds) report to an ops status file and
journal;
scripts/watchboard.pyrenders them live in a terminal pane.
This is a personal tool that has grown into a portable repo. The core
ingest/search/vault flow should be useful anywhere Python and ffmpeg run, but
some features reflect the original setup:
- Instagram capture needs a
sessionidcookie from a logged-in browser session and may be sensitive to platform rate limits. ytk ui install,ytk schedule, macOS notifications, and iMessage ingestion are macOS-oriented.- The default vault conventions assume a
second-brain/style Obsidian layout, but the notes are plain markdown and can be adapted. - Enrichment has Anthropic API cost; transcription, embeddings, indexing, and search run locally.
Issues, docs improvements, and focused pull requests are welcome. The most useful contributions are usually:
- clearer setup notes for non-macOS environments,
- small bug fixes with tests,
- capture-source improvements,
- examples of vault layouts or workflows that make
ytkeasier to adopt.
MIT. See LICENSE.


