Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Slides

ASecurity

Extract relevant frames from a video or animated image (GIF, APNG, animated WebP) so the model can view them as a timeline. Use when the user shares a video or an animated image. DO NOT use for static images — the model can already read those natively.

67 stars
0 votes
0 copies
0 views
Added 9/19/2026
ai-agentsbashapi

Works with

claude codecliapi

Security Analysis

A92/100
mediumInstalls packages at runtime which could introduce malicious dependencies

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add t0mtaylor/peepshow --skill slides --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Slides?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Slides
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/t0mtaylor-slides/badge)](https://www.skillsdirectory.com/skills/t0mtaylor-slides)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
description: Extract relevant frames from a video or animated image (GIF, APNG, animated WebP) so the model can view them as a timeline. Use when the user shares a video or an animated image. DO NOT use for static images — the model can already read those natively.
---

# Slides

Static images (JPG/PNG/static WebP) can be read natively. **This skill is only for video and animated images** — anything that has multiple frames across time. It uses `peepshow` (ffmpeg under the hood) to extract a sequence of relevant still frames so they can be viewed as a timeline.

## Input

The user may provide the video (or animated image — GIF, APNG, animated WebP) in any of these forms:

- A local file path (absolute, relative, or a network mount like `/Volumes/share/...`)
- An `http://` or `https://` URL
- A `data:video/...;base64,...` or `data:image/(gif|apng|webp|png);base64,...` URI pasted into the prompt
- The literal `-` to read bytes from stdin (you would pipe via `Bash`)

If `$ARGUMENTS` contains the video reference, use it directly. Otherwise ask the user to share one of the above.

## Steps

1. **Run the CLI** with the `Bash` tool. JSON is the most reliable output for parsing:

   ```
   PEEPSHOW_CLIENT=claude-code PEEPSHOW_SESSION="${CLAUDE_SESSION_ID:-}" peepshow "$ARGUMENTS" --emit json
   ```

   The `PEEPSHOW_CLIENT` + `PEEPSHOW_SESSION` env vars tag the run in the manifest and the access log so a shared `peepshow serve` instance can attribute every run + HTTP call back to the right Claude Code session. Both are optional — peepshow runs fine without them — but setting them costs nothing.

   (If the path contains spaces, quote it. Use `--emit paths` if you prefer reading the human-readable list.)

2. **Parse the output**. In JSON mode, `frames[].path` is the ordered list of absolute paths. The `video` object gives you container, codec, resolution, fps, duration, and file size — useful context for the user's question without extra prompting. The `video.tags` object carries container-level metadata embedded in the file (title, artist, album_artist, director, producer, publisher, copyright, genre, description, creation_time, show, episode_id, season_number, etc.) — use it to ground your answer in what the video *says it is* before describing what you see. The `extraction` object tells you which strategy (`scene` vs `fps`) was used, how many frames were pruned, how many were dropped by the perceptual-hash dedup pass (`framesDeduped` + `dedupDistance`), and a coarse motion signal across the kept frames (`motionSignalAvg` numeric + `motionSignalLevel` `low`/`medium`/`high`). Use the motion signal to colour your narration (e.g. "rapid action segment" vs "near-static timelapse"); combine with `framesDeduped == 0` + `motionSignalLevel == "high"` to recognise a high-information clip where the LLM should pay close attention to every frame.

3. **Read the audio transcript**, if present. When the input had an audio track, the JSON payload's `audio` object has:
   - `audio.path` — the extracted `audio.m4a` on disk.
   - `audio.durationSeconds`, `audio.codec`, `audio.peakDbfs`, `audio.silenceRatio` — audio metadata.
   - `audio.transcript` — when transcription ran (whisper.cpp or a cloud provider), this contains `text` (full concatenated transcript) and `segments[]` (each with `start` / `end` / `text` in seconds). Use the transcript to understand **what was said** in addition to what was shown. For conversational or narration-heavy videos the transcript is often more informative than the frames alone. Cross-reference segment timestamps against frame indices so you can quote who said what when.

   If `audio.path === null` the input had no audio track (GIF, APNG, animated WebP, silent video). Skip the audio step cleanly.

   If `audio.transcript === null` or `audio.transcript.skippedReason` is set, transcription didn't run — just work with the frames.

4. **Read each frame as an image** with the `Read` tool, **in order**. They are named `frame_0001.jpg`, `frame_0002.jpg`, etc. and represent the timeline from earliest to latest.

5. **Answer the user's question** using both the frames and the transcript together. Reference timestamps when helpful (derive from `video.durationSeconds`, frame ordering, and transcript `segments[].start`). A useful pattern for longer clips: summarise the visual timeline in 2-3 beats, then weave in direct quotes from the transcript to ground what was said at those moments.

6. **Annotate the report — MANDATORY.** The JSON payload from step 1 includes an `annotate` block with the exact command. Without this step the manifest stays empty and the run shows up as `no-analysis` on the /runs page. Pipe a JSON object with your `summary` and **`perFrame` covering every frame** back into peepshow:

   ```bash
   echo '{"summary":"<2-4 sentences describing the timeline>","perFrame":[{"idx":0,"text":"<frame 0 caption>"},{"idx":1,"text":"<frame 1 caption>"},{"idx":2,"text":"<frame 2 caption>"},…,{"idx":N-1,"text":"<frame N-1 caption>"}],"provider":"claude-code","model":"claude-opus-4-7"}' \
     | peepshow report annotate "$OUTPUT_DIR"
   ```

   `$OUTPUT_DIR` is the run's `outputDir` (the JSON payload's `outputDir` field — typically a `/tmp/peepshow-...` path). The annotate step rewrites `manifest.json` and `report.html` atomically; users opening the HTML now see your synthesis under the "LLM analysis" section.

   **`perFrame.length` MUST equal `frames.length`.** Every extracted frame gets its own caption — no skipping, no key-beats-only summaries. The /runs page surfaces sparse coverage as `partial-captions`; agents that ship sparse perFrame are doing it wrong. peepshow logs a warning to stderr when sparse uploads are detected (and rejects them with `--strict`).

   Run this for **every** invocation, including ones that didn't end with a question — the manifest is the durable record of what you understood. Only skip when the user explicitly asks for raw frames with no synthesis.

## Useful flags

Pass these after the input when the defaults are not right:

- `--max 20` — cap the number of frames returned (default 40)
- `--min 6` — ensure at least this many (falls back from scene detection to fps sampling)
- `--threshold 0.2` — more sensitive scene detection (default 0.3; lower = more frames)
- `--fps 0.5` — skip scene detection and sample at a fixed rate
- `--width 960` — max output width in pixels (default 1280)
- `--format png` — output PNG instead of JPG
- `--stats full` — include the full stats block (video + extraction details)
- `--stats off` — suppress stats entirely if context is tight

## Troubleshooting

- **`ffmpeg not found`**: run `npm install` inside the plugin directory once to fetch the bundled ffmpeg binary.
- **Zero frames returned**: lower `--threshold` or force `--fps 1`.
- **Too many frames**: raise `--threshold` or lower `--max`.

Attribution

t0mtaylort0mtaylor
View sourceMore from t0mtaylor →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra, wenyan-lite, wenyan-full, wenyan-ultra. Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens", "be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.

1023331 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

686011 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3331 votes

catchup

Recovers prior coding-agent session context by running `catchup <agent> --since-compact`, which extracts a clean summary of a previous Codex, Claude Code, Antigravity, OpenCode, or Pi Agent session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", or asks to recover/summarize a previous session before continuing. Do NOT use for the current conversation, git history, or any non-agent log.

611 votes

math-skill

A comprehensive mathematical reasoning skill for AI assistants — handles arithmetic to research-level problems with rigorous step-by-step reasoning, systematic verification, and transparent uncertainty handling

381 votes
View all in ai-agents →