Move the skill into skills/watch/ so SKILL.md and its scripts/ runtime are
siblings inside one folder. `npx skills add` (Codex/Cursor/Copilot/agents) now
copies a working skill as a unit; previously it grabbed the root SKILL.md alone
and left scripts/ behind, so the skill was dead on arrival on every non-Claude
host. Mirrors the layout last30days-skill adopted for the same reason.
- skills/watch/{SKILL.md,scripts/}: self-contained skill folder
- SKILL.md: resolve a harness-agnostic $SKILL_DIR (the dir it was Read from)
instead of the Claude-Code-only ${CLAUDE_SKILL_DIR}; guard + 19 call sites
- drop commands/watch.md: /watch derives from frontmatter (name + user-invocable)
- .codex-plugin/plugin.json: full manifest with "skills": "./skills/" + interface
- add .agents/plugins/marketplace.json, AGENTS.md, CLAUDE.md, .skillignore
- build-skill.sh: archive the skills/watch subtree (one SKILL.md, no zip -d)
- fix paths in tests, hooks hint, .gitattributes, release.yml
- relocate dev-sync.sh to repo root and fix REPO_ROOT
- README: content-ideas structure, npx skills install, star history
Verified: 37/37 tests pass; npx skills add bundles the full scripts/ runtime;
manifests valid; versions synced at 0.1.3.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- #2: harden subprocess argv against option injection
- #4: read/write config files as UTF-8 on Windows
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Path.read_text()/write_text() default to the platform encoding (cp1252
on Windows), which mangles or crashes on UTF-8 files. yt-dlp's
video.info.json is UTF-8 and routinely contains non-ASCII bytes, so on
Windows the parse raised UnicodeDecodeError, was swallowed by a bare
except, and the /watch report came back missing Title/Uploader.
- download.py: read video.info.json as UTF-8; log parse failures to
stderr instead of swallowing them silently.
- whisper.py, setup.py: same UTF-8 fix on .env reads and writes for
symmetry across platforms.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- download.py: insert `--` before URL in yt-dlp argv so a `-`-prefixed
string can never be parsed as a flag (e.g. --exec, --config-location).
Tighten is_url to reject `-`-prefixed sources and require non-empty
netloc.
- frames.py, whisper.py: resolve video/audio paths to absolute via
Path.resolve() before passing to ffmpeg/ffprobe (which don't honor
`--` as end-of-options), so a relative path starting with `-` can
never be misinterpreted as a flag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- watch.py: drop the ⚠️ emoji from the long-video warning; cp1252
consoles on Windows couldn't encode it and the script crashed.
- setup.py: add a Windows branch that prints winget / pip install
commands, matching what the README already promised.
- SKILL.md: note that Windows users must invoke the scripts with
`python`, not `python3` (which is the Microsoft Store stub).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Claude Code plugins expose slash commands from commands/*.md; the root
SKILL.md alone isn't discovered. Thin shim delegates to the existing
skill contract. Strip commands/ from the claude.ai .skill bundle since
that surface uses SKILL.md directly. Bumped to 0.1.1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Give Claude the ability to watch any video — yt-dlp download, ffmpeg
frame extraction with auto-scaled fps, native-caption transcript with
Whisper (Groq/OpenAI) fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>