{
  "schema": "snappy-card/1",
  "skill": "snappy-video",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "You are operating the video and audio post-production pipeline. Everything runs on the Mac Mini via SSH (`robertboulos@Roberts-Mac-mini.local`). The single entry point is `caption-video.sh` which wraps Whisper transcription, SRT/ASS generation, ffmpeg caption burning, and optional auto-clip extraction.",
  "verbs": [
    {
      "name": "caption",
      "args": [
        "path"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-video/api.ts caption <path>"
    },
    {
      "name": "clip",
      "args": [
        "path",
        "start",
        "duration"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-video/api.ts clip <path> <start> <duration>"
    },
    {
      "name": "transcribe",
      "args": [
        "path",
        "model?"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-video/api.ts transcribe <path>"
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [],
  "used_by": [
    "snappy-ads",
    "snappy-ffmpeg",
    "snappy-remotion",
    "snappy-voice-control"
  ],
  "checks": {
    "pass": 27,
    "fail": 7,
    "defer": 27,
    "line": "27 of 34 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-client-feisst, snappy-runner"
      },
      {
        "id": 10,
        "rule": "One term names each concept",
        "says": "mixed synonym sets: endpoint/url/route/path"
      },
      {
        "id": 11,
        "rule": "Each task presents one default, not a menu",
        "says": "1 line(s) present three-way alternative menus"
      },
      {
        "id": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~248 tokens; body ~3614 tokens"
      },
      {
        "id": 54,
        "rule": "At least three eval scenarios precede ready status",
        "says": "0 eval scenario(s); ready=true"
      },
      {
        "id": 55,
        "rule": "Eval scenarios are multi-call with ground truth",
        "says": "eval manifest missing"
      },
      {
        "id": 57,
        "rule": "Eval manifest contains a disjoint holdout",
        "says": "0 disjoint holdout scenario(s)"
      }
    ]
  },
  "coverage": null,
  "spec": null,
  "evals": null,
  "files": [
    "AGENTS.md",
    "SKILL.md",
    "api.ts",
    "caption-styles.md",
    "ffmpeg-recipes.md",
    "refusals.test.ts"
  ],
  "total_size": 46469,
  "checksum": "sha256:4bcae8a2bf788bc49a9f26eef503c46e7cf10b1f37dea8b8aa6513e65064d4c8",
  "built_at": "2026-09-09T22:11:21.363Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-video",
      "version": "0.0.0",
      "description": "Video and audio processing pipeline for Snappy, run on the Mac Mini via SSH (caption-video.sh wrapper around video-pipeline.py): Whisper transcription, SRT and ASS subtitles, word-level karaoke, ffmpeg caption burning, auto-clip detection by speech density, thumbnail extraction, audio extraction (m4a/mp3), 16:9 / 9:16 / 1:1 conversion, screen recording + voiceover merge, web compression. THE DEFAULT for any video or audio task. Use when Robert says: /snappy-video, \\\"caption this video\\\", \\\"burn the subtitles\\\", \\\"transcribe this with whisper\\\", \\\"clip the best parts\\\", \\\"make it vertical for shorts / reels\\\", \\\"compress the video for web\\\", \\\"extract the audio\\\", \\\"video for youtube\\\", \\\"video for ads\\\". Triggers on: video, captions, subtitles, whisper, ffmpeg burn, vertical clip, b-roll, thumbnail. NOT local ffmpeg on this Mac (see snappy-ffmpeg). NOT the Charlotte mac_mini_exec argument table (see video-pipeline). NOT scripting or retention structure (see retention-script)."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-video/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/caption": {
        "post": {
          "operationId": "snappy_video_caption",
          "summary": "snappy-video caption",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string",
                      "description": "Path to the video file to caption",
                      "x-snappy-position": 0
                    }
                  },
                  "required": [
                    "path"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/clip": {
        "post": {
          "operationId": "snappy_video_clip",
          "summary": "snappy-video clip",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string",
                      "description": "Path to the source video",
                      "x-snappy-position": 0
                    },
                    "start": {
                      "type": "string",
                      "description": "Start offset into the source video as HH:MM:SS",
                      "x-snappy-position": 1
                    },
                    "duration": {
                      "type": "string",
                      "description": "Clip length in seconds",
                      "x-snappy-position": 2
                    }
                  },
                  "required": [
                    "path",
                    "start",
                    "duration"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/transcribe": {
        "post": {
          "operationId": "snappy_video_transcribe",
          "summary": "snappy-video transcribe",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "path": {
                      "type": "string",
                      "description": "Path to the video or audio file to transcribe",
                      "x-snappy-position": 0
                    },
                    "model": {
                      "type": "string",
                      "description": "Model id to transcribe with",
                      "x-snappy-position": 1
                    }
                  },
                  "required": [
                    "path"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      }
    },
    "components": {
      "schemas": {
        "SnappyRefusal": {
          "type": "object",
          "required": [
            "outcome",
            "code",
            "message"
          ],
          "properties": {
            "outcome": {
              "type": "string",
              "const": "refused"
            },
            "code": {
              "type": "string",
              "description": "A row of the closed refusal table."
            },
            "message": {
              "type": "string"
            },
            "fix": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}