About claude-watch
claude-watch is a Claude skill that extracts frames and transcript content from videos or video URLs, then organizes them into timestamped study notes. It is for studying tutorials, lectures, and recordings, with notes saved as files.
Key features
- 01Process video URLs and local videos
- 02Extract frames and transcript text
- 03Organize timestamped notes by scene
- 04Focus on sections and adjust frame sampling
- 05Reuse cached content on repeat viewing
Use cases
- 01Turn an online tutorial into study notes
- 02Extract key points from a local screen recording
- 03Focus on a specific section of a lecture
- 04Ask follow-up questions about a previously watched video
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ devinilabs/ claude-watch --skill claude-watchAfter installing, type/claude-watchin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
.gitignoreCHANGELOG.md.gitattributesLICENSEREADME.mdconftest.pypyproject.toml.claude-plugin/marketplace.jsonplugin.json.codex-plugin/skill.json.github/workflows/release.ymlcommands/claude-watch.mdhooks/hooks.jsonhooks/scripts/session_start.shscripts/__init__.pylibrary.pyframes.pydownload.pybuild-skill.shresolve.pyscenes.pysetup.pywhisper.pywatch.pytranscribe.pytests/__init__.pytest_download.pytest_library.pytest_frames.pytests/fixtures/build_fixture.shDetails
From the project README/claude-watch — Claude turns a video into study notes
You don't have a video input. This skill gives you one and turns each viewing into a saved notes artifact.
Step 0 — Setup preflight (silent on success)
Run on every /claude-watch invocation:
python3 "${CLAUDE_SKILL_DIR}/scripts/setup.py" --check
Exit codes: 0 ready (silent — proceed), 2 missing binaries, 3 missing API key, 4 both. On non-zero, run the installer:
python3 "${CLAUDE_SKILL_DIR}/scripts/setup.py"
On macOS this auto-brew installs ffmpeg + yt-dlp. On Linux/Windows it prints the right commands. It scaffolds ~/.config/claude-watch/.env (mode 0600) with commented placeholders.
If a Whisper key is still missing afterwards, use AskUserQuestion to ask whether the user has a Groq key (preferred — cheaper, faster) or an OpenAI key, and write it to ~/.config/claude-watch/.env. If they don't want to, run with --no-whisper; videos without native captions will come back frames-only.
When to use
- User pastes a tutorial / lecture / talk URL and asks to study it
- User points at a local screen recording or video and wants notes
- User types
/claude-watch <url-or-path> [topic]
How to invoke
Step 1 — parse input. Separate the source (URL or path) from any topic the user mentioned. The topic shapes which sections you emphasize in the notes — pass it through to your synthesis, not to the script.
Step 2 — run the watch script.
python3 "${CLAUDE_SKILL_DIR}/scripts/watch.py" "<source>"
Optional flags:
--start T/--end T— focus on a section (SS,MM:SS, orHH:MM:SS)--max-frames N— lower budget (default 80)--resolution W— bump frame width to 1024 px when on-screen text is tiny--scene-threshold X— sensitivity (default 0.30; raise for fewer cuts, lower for more)--max-gap S— coverage floor in seconds (default 45)--whisper groq|openai— force backend--no-whisper— disable Whisper entirely--out-dir DIR— override library root
Step 3 — read every frame. The script ends with a structured === frames === block listing each frame's path and timestamp. Read them all in parallel — they render as images in your context.
Step 4 — load the transcript. The === transcript === block points to transcript.json (or transcript.window.json for focused mode). Read it — it's a list of {t_start, t_end, text, speaker_break}.
Step 5 — write notes.md to the library directory. Use the strict template below. Save to <library_dir>/notes.md. Then print a 3-line summary to chat:
- Title and slug
- Number of sections + key concepts
- Path to the notes file
Do not delete the library dir. It is the artifact.
Notes template (non-negotiable structure)
# <Video Title>
**Source:** <URL or path> · **Duration:** MM:SS · **Watched:** YYYY-MM-DD
## TLDR
<3-4 sentences: what the video is about and the single most important takeaway.>
## Key Concepts
- **<concept>** — <one-line definition> · `[t=MM:SS]`
- ...
## Notes
### [t=00:04] <Section title you derive from on-screen + spoken content>

**On screen:** <Transcribe / describe the slide, code, diagram. If code, transcribe verbatim.>
**Said:** <Relevant transcript excerpt for this scene, lightly cleaned.>
**Synthesis:** <Your connection — what this section is teaching, how it links to prior section.>
### [t=00:31] <next section>
...
## Code & Commands
<every code-on-screen frame's content as a runnable fenced block, language-tagged, with [t=MM:SS] back-link>
```python
# [t=03:45]
def forward(x):
return x @ W + b
```
## Diagrams Referenced
- `[t=02:10]` — <one-line description of the diagram in frame 0008>
- ...
## Open Questions
- <things mentioned but not fully covered, or follow-ups to explore>
Rules baked into the template
- One scene = one section. Use the
t=MM:SSfrom each frame as the section anchor. - Adjacent scenes that are clearly the same topic can be merged. When you do, mention it parenthetically: (merged scenes at t=02:10 and t=02:42)
- Code blocks must be fenced with the right language tag, transcribed verbatim from the frame.
- The "On screen" block is required even for title slides. Keeps the structure parallel.
- Timestamps are absolute (real video timeline) — for YouTube sources, a viewer can paste
<URL>&t=<seconds>to jump there.
Re-runs
If the user re-watches the same URL, the script reuses the cached download, transcript, and scenes. Only frames + notes regenerate. To force a full re-run, delete <library_dir>/meta.json first.
Failure modes
- Setup preflight non-zero → run
setup.py, then ask for a key viaAskUserQuestion. - No transcript → script emits
transcript_source: none. Generate notes frames-only and tell the user. - Long video sparse-scan warning → offer to re-run with
--start/--endfocused on the part the user cares about. - Whisper failure → retry with
--whisper openai(if Groq failed) or vice versa.
Token budget
Frames dominate cost (~50-80k input tokens for 60 frames at 512 px). Transcripts are cheap. --resolution 1024 quadruples per-frame cost — only when the user must read tiny on-screen text.
If the user asks a follow-up about a video you already watched in this session, do NOT re-run the script. The library directory is on disk; re-Read only the frames you need.
Security
- Runs
yt-dlp,ffmpeg,ffprobelocally - Sends extracted mono 16 kHz audio to Groq (preferred) or OpenAI Whisper API only when captions are missing
- Reads/writes
~/.config/claude-watch/.env(mode 0600) for keys - Persists artifacts to
~/claude-watch/library/<slug>/— review the directory after first run if you're cautious - Does NOT log or transmit API keys, video files, or the original URL outside the audio-to-Whisper call