Give Claude the ability to watch any video. /watch downloads, extracts frames, transcribes, hands it all to Claude.
This report summarizes scanner evidence for bradautomates/claude-video, a Python project with 18,340 GitHub stars. SynthScan examined 6,065 lines of code across 42 source files, recording 217 pattern matches distributed across 8 syntactic categories. The legacy adjusted pattern signal is 47.8 (High pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 186 finding(s).
Are imports declared and package/API names verified? 23 finding(s).
Are wrappers, guards, and repeated structures necessary? 182 finding(s).
Which changes need focused human review? 217 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 217 distinct pattern matches across 8 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_dedup.py | 11 | def test_frame_delta_identical_is_zero(): | CODE |
| LOW⚡ | tests/test_dedup.py | 16 | def test_frame_delta_is_mean_absolute_difference(): | CODE |
| LOW⚡ | tests/test_dedup.py | 22 | def test_frame_delta_mismatched_length_is_infinite(): | CODE |
| LOW⚡ | tests/test_dedup.py | 42 | def test_dedupe_collapses_identical_run(tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 52 | def test_dedupe_keeps_all_distinct(tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 61 | def test_dedupe_compares_against_last_kept_not_previous(tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 71 | def test_dedupe_threshold_is_inclusive(tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 81 | def test_dedupe_empty_and_single_are_noops(tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 89 | def test_dedupe_mismatched_thumb_count_is_noop(tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 99 | def test_thumb_frames_match_candidate_count(cut_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 106 | def test_dedupe_perceptual_collapses_static_clip(static_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 116 | def test_dedupe_perceptual_keeps_distinct_cuts(cut_clip: Path, tmp_path: Path): | CODE |
| LOW | tests/test_dedup.py | 127 | def test_scene_engine_reports_zero_dedup_on_distinct(cut_clip: Path, tmp_path: Path): | CODE |
| LOW | tests/test_dedup.py | 136 | def test_uniform_fallback_dedupes_static(static_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 148 | def test_keyframe_uniform_fallback_dedupes_static(static_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 155 | def test_dedup_false_disables_collapse(static_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_dedup.py | 165 | def test_equal_brightness_different_colors_survive(tmp_path): | CODE |
| LOW⚡ | tests/test_setup.py | 16 | def test_json_reports_watch_detail(monkeypatch, capsys): | CODE |
| LOW⚡ | tests/test_setup.py | 22 | def test_keyless_completed_setup_proceeds_silently(capsys): | CODE |
| LOW⚡ | tests/test_setup.py | 30 | def test_keyless_first_run_can_proceed(capsys): | CODE |
| LOW⚡ | tests/test_setup.py | 36 | def test_key_present_is_ready(monkeypatch): | CODE |
| LOW⚡ | tests/test_setup.py | 42 | def test_missing_binaries_are_independent_of_keys(monkeypatch): | CODE |
| LOW⚡ | tests/test_setup.py | 49 | def test_project_marker_cannot_complete_setup(monkeypatch): | CODE |
| LOW⚡ | tests/test_setup.py | 56 | def test_marker_replacement_preserves_comments_and_key(): | CODE |
| LOW⚡ | tests/test_setup.py | 66 | def test_failed_atomic_write_preserves_original(monkeypatch): | CODE |
| LOW | tests/test_setup.py | 77 | def test_config_write_refuses_bad_encoding(): | CODE |
| LOW | tests/test_setup.py | 86 | def test_permission_diagnostics(monkeypatch, tmp_path, capsys, system, mode, warns): | CODE |
| LOW⚡ | tests/test_setup.py | 97 | def test_check_never_launches_whisperx(monkeypatch): | CODE |
| LOW⚡ | tests/test_setup.py | 103 | def test_none_backend_completion(): | CODE |
| LOW⚡ | tests/test_setup.py | 110 | def test_gemini_engine_is_ready_without_media_binaries(monkeypatch): | CODE |
| LOW⚡ | tests/test_setup.py | 123 | def test_local_engine_still_requires_binaries(monkeypatch): | CODE |
| LOW⚡ | tests/test_setup.py | 131 | def test_engine_gemini_without_key_writes_choice_and_asks_for_key(monkeypatch, capsys): | CODE |
| LOW⚡ | tests/test_setup.py | 139 | def test_engine_gemini_with_key_completes_setup_and_preserves_lines(monkeypatch): | CODE |
| LOW⚡ | tests/test_download.py | 17 | def test_original_track_overrides_dubbed_metadata(language): | CODE |
| LOW⚡ | tests/test_download.py | 26 | def test_unknown_language_prefers_english(): | CODE |
| LOW⚡ | tests/test_download.py | 34 | def test_requested_translation_and_unknown_source(): | CODE |
| LOW⚡ | tests/test_download.py | 41 | def test_cookie_modes_and_conflict(): | CODE |
| LOW | tests/test_download.py | 72 | def test_fetch_captions_requests_one_exact_track(monkeypatch, tmp_path): | CODE |
| LOW⚡ | tests/test_download.py | 86 | def test_failed_download_never_returns_old_media(monkeypatch, tmp_path): | CODE |
| LOW⚡ | tests/test_download.py | 96 | def test_rejects_partial_final_paths(monkeypatch, tmp_path, name): | CODE |
| LOW⚡ | tests/test_download.py | 104 | def test_rejects_outside_final_path(monkeypatch, tmp_path): | CODE |
| LOW | tests/test_download.py | 119 | def test_actual_ytdlp_exact_track_with_inherited_all(monkeypatch, tmp_path, static_clip): | CODE |
| LOW | tests/test_download.py | 155 | def test_explicit_regional_language_is_not_silently_replaced(): | CODE |
| LOW | tests/test_frames.py | 10 | def test_keyframe_engine_on_cut_clip(cut_clip: Path, tmp_path: Path): | CODE |
| LOW | tests/test_frames.py | 19 | def test_keyframe_even_sampling_caps_and_spans(cut_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_frames.py | 31 | def test_keyframe_fallback_on_static_clip(static_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_frames.py | 39 | def test_scene_engine_on_cut_clip(cut_clip: Path, tmp_path: Path): | CODE |
| LOW⚡ | tests/test_frames.py | 48 | def test_scene_even_sampling_caps_and_spans(cut_clip: Path, tmp_path: Path): | CODE |
| LOW | tests/test_frames.py | 66 | def test_scene_fallback_on_static_clip(static_clip: Path, tmp_path: Path): | CODE |
| LOW | tests/test_frames.py | 74 | def test_uniform_pixels_match_source_time(tmp_path): | CODE |
| LOW | tests/test_frames.py | 88 | def test_fractional_seek_and_cap_use_actual_span(tmp_path): | CODE |
| LOW | tests/test_frames.py | 99 | def test_nonzero_input_pts_are_source_relative(tmp_path): | CODE |
| LOW⚡ | tests/test_frames.py | 110 | def test_invalid_fps_rejected_before_extraction(static_clip, tmp_path, fps): | CODE |
| LOW⚡ | tests/test_frames.py | 115 | def test_gap_with_corrupt_input_still_fails(tmp_path): | CODE |
| LOW⚡ | tests/test_frames.py | 122 | def test_variable_rate_timestamps_are_actual_source_frames(tmp_path): | CODE |
| LOW | tests/test_frames.py | 135 | def test_single_frame_cap_keeps_first_real_frame(static_clip, tmp_path): | CODE |
| LOW | tests/test_frames.py | 140 | def test_uniform_candidate_count_includes_deduplicated_frames(static_clip, tmp_path): | CODE |
| LOW⚡ | tests/test_packaging.py | 13 | def test_frontmatter_uses_only_agent_skills_keys(): | CODE |
| LOW⚡ | tests/test_packaging.py | 21 | def test_release_versions_match_canonical_skill(): | CODE |
| LOW⚡ | tests/test_packaging.py | 30 | def test_copied_skill_runs_outside_repository(tmp_path, static_clip): | CODE |
| 114 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | skills/watch/scripts/runtime.py | 15 | except (OSError, ValueError): | CODE |
| HIGH | skills/watch/scripts/setup.py | 50 | except OSError: | CODE |
| HIGH | skills/watch/scripts/frames.py | 510 | except OSError: | CODE |
| HIGH | skills/watch/scripts/frames.py | 412 | except OSError: | CODE |
| HIGH | skills/watch/scripts/frames.py | 641 | except OSError: | CODE |
| HIGH | skills/watch/scripts/local_whisperx.py | 116 | except queue.Empty: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_dedup.py | 2 | CODE | |
| LOW | tests/conftest.py | 2 | CODE | |
| LOW | tests/test_frames.py | 2 | CODE | |
| LOW | tests/test_watch.py | 2 | CODE | |
| LOW | tests/test_local_whisperx.py | 2 | CODE | |
| LOW | tests/test_timestamps.py | 2 | CODE | |
| LOW | tests/test_whisper.py | 2 | CODE | |
| LOW | tests/test_release_regressions.py | 2 | CODE | |
| LOW | tests/test_release_regressions.py | 3 | CODE | |
| LOW | tests/test_release_regressions.py | 4 | CODE | |
| LOW | tests/test_config.py | 2 | CODE | |
| LOW | tests/test_fixtures.py | 2 | CODE | |
| LOW | tests/test_gemini.py | 2 | CODE | |
| LOW | skills/watch/scripts/config.py | 3 | CODE | |
| LOW | skills/watch/scripts/download.py | 3 | CODE | |
| LOW | skills/watch/scripts/gemini.py | 7 | CODE | |
| LOW | skills/watch/scripts/runtime.py | 2 | CODE | |
| LOW | skills/watch/scripts/whisper.py | 11 | CODE | |
| LOW | skills/watch/scripts/setup.py | 3 | CODE | |
| LOW | skills/watch/scripts/frames.py | 9 | CODE | |
| LOW | skills/watch/scripts/transcribe.py | 3 | CODE | |
| LOW | skills/watch/scripts/local_whisperx.py | 2 | CODE | |
| LOW | skills/watch/scripts/watch.py | 7 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | skills/watch/scripts/config.py | 96 | CODE | |
| LOW | skills/watch/scripts/download.py | 48 | CODE | |
| LOW | skills/watch/scripts/whisper.py | 177 | CODE | |
| LOW | skills/watch/scripts/setup.py | 239 | CODE | |
| LOW | skills/watch/scripts/frames.py | 158 | CODE | |
| LOW | skills/watch/scripts/frames.py | 177 | CODE | |
| LOW | skills/watch/scripts/watch.py | 94 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | README.md | 132 | **Fastest path — let Gemini watch it.** Get a free [Google AI Studio key](https://aistudio.google.com/apikey). When the | CODE |
| MEDIUM⚡ | tests/test_gemini.py | 81 | assert payload['input'][0] == {'type': 'video', 'uri': 'https://youtu.be/abc', 'processing': 'agentic'} | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | dev-sync.sh | 1 | #!/usr/bin/env bash | COMMENT |
| LOW | skills/watch/scripts/frames.py | 21 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | skills/watch/scripts/whisper.py | 256 | except Exception: | CODE |
| LOW | skills/watch/scripts/whisper.py | 262 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | dev-sync.sh | 10 | # Usage: | COMMENT |