{
  "schemaVersion": "1.0",
  "item": {
    "slug": "gifhorse",
    "name": "GifHorse",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/Coyote-git/gifhorse",
    "canonicalUrl": "https://clawhub.ai/Coyote-git/gifhorse",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/gifhorse",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=gifhorse",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "_meta.json",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/gifhorse"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/gifhorse",
    "agentPageUrl": "https://openagent3.xyz/skills/gifhorse/agent",
    "manifestUrl": "https://openagent3.xyz/skills/gifhorse/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/gifhorse/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "GifHorse - Dialogue Search & GIF Creator",
        "body": "Create reaction GIFs from your video library by searching dialogue and adding timed subtitles."
      },
      {
        "title": "What GifHorse Does",
        "body": "Transcribe videos - Extract dialogue with timestamps by downloading subtitles, using local .srt files, or Whisper AI\nSearch dialogue - Find quotes across your entire video library instantly\nPreview clips - See exactly what will be captured before creating the GIF\nCreate GIFs - Generate GIFs with perfectly timed subtitles and optional watermarks"
      },
      {
        "title": "First Time Setup",
        "body": "Install gifhorse (via install button above)\nInstall FFmpeg-full for subtitle rendering (via install button above)\nTranscribe your video library (downloads subtitles automatically):\n\ncd ~/gifhorse && source venv/bin/activate\ngifhorse transcribe ~/Movies\n\nThe gifhorse command must be run from within its virtual environment. You can activate it with:\n\ncd ~/gifhorse && source venv/bin/activate\n\nOr use the activation helper:\n\nsource ~/gifhorse/activate.sh"
      },
      {
        "title": "Transcribe Videos",
        "body": "Extract dialogue from your videos (one-time per video):\n\n# Default: downloads subtitles from online providers (fast, recommended)\ngifhorse transcribe /path/to/videos\n\n# Use only local .srt files (no downloading, no Whisper)\ngifhorse transcribe /path/to/videos --use-subtitles\n\n# Use Whisper AI (slow but works for any video)\ngifhorse transcribe /path/to/video.mp4 --use-whisper\n\n# Re-transcribe videos already in database\ngifhorse transcribe /path/to/videos --force"
      },
      {
        "title": "Download Subtitles Only",
        "body": "Download .srt files without storing in the database:\n\ngifhorse fetch-subtitles /path/to/videos\ngifhorse fetch-subtitles /path/to/videos --skip-existing"
      },
      {
        "title": "Search Dialogue",
        "body": "Find quotes across your entire library:\n\n# Basic search\ngifhorse search \"memorable quote\"\n\n# Search with surrounding context\ngifhorse search \"memorable quote\" --context 2\n\n# Show all results (no limit)\ngifhorse search \"memorable quote\" --all\n\n# Custom result limit (default: 100)\ngifhorse search \"memorable quote\" --limit 50"
      },
      {
        "title": "Preview Before Creating",
        "body": "See exactly what will be captured:\n\ngifhorse preview \"memorable quote\" 1\ngifhorse preview \"quote\" 1 --include-before 1 --include-after 1"
      },
      {
        "title": "Create GIF",
        "body": "Generate the GIF with subtitles:\n\n# Basic GIF (auto-named from dialogue, saved to exports/)\ngifhorse create \"memorable quote\" 1\n\n# Explicit output path\ngifhorse create \"memorable quote\" 1 -o reaction.gif\n\n# High quality for social media\ngifhorse create \"quote\" 1 --width 720 --fps 24 --quality high\n\n# Include conversation context\ngifhorse create \"quote\" 1 --include-before 2 --include-after 1\n\n# Substitute words in subtitles (repeatable, target segments by number from preview)\ngifhorse create \"the age of men\" 1 --include-after 1 \\\n  -s 1 \"men\" \"standardized software\" \\\n  -s 2 \"orc\" \"custom applications\"\n\n# Clean replace (no strikethrough)\ngifhorse create \"quote\" 1 -r 1 \"old word\" \"new word\"\n\n# Create and send via iMessage\ngifhorse create \"quote\" 1 --send\ngifhorse create \"quote\" 1 --send-to \"+15551234567\""
      },
      {
        "title": "Manage Database",
        "body": "# Remove videos by path pattern (SQL LIKE wildcards)\ngifhorse remove \"%Adventure Time%\"\ngifhorse remove \"%S01%\" --yes\n\n# Check subtitle status for a directory\ngifhorse subtitle-status ~/Videos\ngifhorse subtitle-status ~/Videos --missing-only"
      },
      {
        "title": "Check Status",
        "body": "# See transcription stats\ngifhorse stats\n\n# List all transcribed videos\ngifhorse list"
      },
      {
        "title": "Configuration",
        "body": "# Set phone number for iMessage sending\ngifhorse config --set-phone \"+15551234567\"\n\n# Show current configuration\ngifhorse config --show"
      },
      {
        "title": "Timing Options",
        "body": "Control exactly what gets captured:\n\n--include-before N - Include N dialogue segments before the match\n--include-after N - Include N dialogue segments after the match\n--padding-before SECS - Add buffer seconds before dialogue starts (default: 1.0)\n--padding-after SECS - Add buffer seconds after dialogue ends (default: 1.0)\n--start-offset SECS - Manual adjustment to start time (can be negative)\n--end-offset SECS - Manual adjustment to end time (can be negative)\n\nImportant: For reactions after dialogue, use --padding-after instead of --include-after. The include-after option captures ALL time until the next dialogue segment (could be 30+ seconds!)."
      },
      {
        "title": "Quality Options",
        "body": "--quality low|medium|high - Color palette quality (affects file size)\n--fps N - Frames per second (default: 15, use 24 for smooth)\n--width N - Width in pixels (default: 480, use 720 for HD)"
      },
      {
        "title": "Subtitle Options",
        "body": "-s, --sub NUM OLD NEW - Substitute words in a segment (repeatable). Replaced words render struck through in red, replacements in red. Segment numbers shown by preview.\n-r, --replace NUM OLD NEW - Replace words cleanly (no strikethrough). Repeatable.\n--no-subtitles - Create GIF without subtitle overlay"
      },
      {
        "title": "Output",
        "body": "Default output filename is auto-derived from dialogue text (e.g., i_dont_think_so.gif) and saved to exports/\nUse -o PATH to override. Collision handling appends _2, _3, etc."
      },
      {
        "title": "iMessage",
        "body": "--send - Send created GIF to configured phone number via iMessage (macOS only)\n--send-to NUMBER - Send to a specific phone number (overrides config)\n\nNote: All GIFs automatically include a subtle \"gifhorse\" watermark in the bottom-right corner."
      },
      {
        "title": "Quick Reaction GIF",
        "body": "gifhorse search \"perfect\"\ngifhorse create \"perfect\" 1 --padding-after 2.0"
      },
      {
        "title": "Full Conversation Exchange",
        "body": "gifhorse search \"key phrase\"\ngifhorse preview \"key phrase\" 1 --include-before 2 --include-after 1\ngifhorse create \"key phrase\" 1 --include-before 2 --include-after 1"
      },
      {
        "title": "Meme with Word Substitution",
        "body": "gifhorse preview \"the age of men\" 1 --include-after 1\ngifhorse create \"the age of men\" 1 --include-after 1 \\\n  -s 1 \"men\" \"standardized software\" \\\n  -s 2 \"orc\" \"custom applications\""
      },
      {
        "title": "High Quality for Twitter/X",
        "body": "gifhorse create \"quote\" 1 --width 720 --fps 24 --quality high -o tweet.gif"
      },
      {
        "title": "Scene with Reaction After Dialogue",
        "body": "gifhorse create \"memorable line\" 1 --padding-after 3.0"
      },
      {
        "title": "Create and Send via iMessage",
        "body": "gifhorse config --set-phone \"+15551234567\"\ngifhorse create \"quote\" 1 --send"
      },
      {
        "title": "Tips & Tricks",
        "body": "Always preview first - Use preview to verify timing before creating\nDefault downloads subtitles - Just run gifhorse transcribe and subtitles are fetched automatically\nWatch file sizes - High quality + long duration = large files (20s can be 20+ MB)\nPadding vs Include - For reactions, use --padding-after not --include-after\nSearch with context - Add --context 2 to see surrounding dialogue\nRe-transcribe with --force - Use --force to update transcriptions after getting better subtitles\nCheck subtitle coverage - Use subtitle-status to see which videos need subtitles"
      },
      {
        "title": "File Size Guide",
        "body": "Low quality, 10s, 360p: ~1-2 MB\nMedium quality, 10s, 480p: ~3-5 MB\nHigh quality, 20s, 720p: ~20+ MB"
      },
      {
        "title": "\"command not found: gifhorse\"",
        "body": "Activate the virtual environment:\n\ncd ~/gifhorse && source venv/bin/activate"
      },
      {
        "title": "Subtitle rendering errors",
        "body": "Make sure FFmpeg-full is installed:\n\nbrew install ffmpeg-full"
      },
      {
        "title": "Video file not found",
        "body": "The database stores absolute paths. If you moved videos after transcription, re-transcribe in the new location."
      },
      {
        "title": "Network Share Support",
        "body": "GifHorse works with network-mounted videos:\n\n# Mount network share (macOS)\nopen \"smb://server-ip/share-name\"\n\n# Transcribe from network\ngifhorse transcribe \"/Volumes/server-ip/Movies\""
      },
      {
        "title": "When to Use This Skill",
        "body": "Invoke gifhorse when the user wants to:\n\nSearch for dialogue or quotes in their video library\nCreate a reaction GIF from a movie or TV show\nMake a meme GIF with substituted words\nAdd subtitles to a video clip\nTranscribe videos for searchable dialogue\nPreview what a GIF will look like before creating it\nSend a GIF via iMessage\nRemove videos from the database\nCheck subtitle status for their video collection"
      },
      {
        "title": "Learn More",
        "body": "GitHub: https://github.com/Coyote-git/gifhorse\nUsage Guide: https://github.com/Coyote-git/gifhorse/blob/main/USAGE_GUIDE.md\nRoadmap: https://github.com/Coyote-git/gifhorse/blob/main/ROADMAP.md"
      },
      {
        "title": "License",
        "body": "MIT"
      }
    ],
    "body": "GifHorse - Dialogue Search & GIF Creator\n\nCreate reaction GIFs from your video library by searching dialogue and adding timed subtitles.\n\nWhat GifHorse Does\nTranscribe videos - Extract dialogue with timestamps by downloading subtitles, using local .srt files, or Whisper AI\nSearch dialogue - Find quotes across your entire video library instantly\nPreview clips - See exactly what will be captured before creating the GIF\nCreate GIFs - Generate GIFs with perfectly timed subtitles and optional watermarks\nSetup\nFirst Time Setup\nInstall gifhorse (via install button above)\nInstall FFmpeg-full for subtitle rendering (via install button above)\nTranscribe your video library (downloads subtitles automatically):\ncd ~/gifhorse && source venv/bin/activate\ngifhorse transcribe ~/Movies\n\n\nThe gifhorse command must be run from within its virtual environment. You can activate it with:\n\ncd ~/gifhorse && source venv/bin/activate\n\n\nOr use the activation helper:\n\nsource ~/gifhorse/activate.sh\n\nAvailable Commands\nTranscribe Videos\n\nExtract dialogue from your videos (one-time per video):\n\n# Default: downloads subtitles from online providers (fast, recommended)\ngifhorse transcribe /path/to/videos\n\n# Use only local .srt files (no downloading, no Whisper)\ngifhorse transcribe /path/to/videos --use-subtitles\n\n# Use Whisper AI (slow but works for any video)\ngifhorse transcribe /path/to/video.mp4 --use-whisper\n\n# Re-transcribe videos already in database\ngifhorse transcribe /path/to/videos --force\n\nDownload Subtitles Only\n\nDownload .srt files without storing in the database:\n\ngifhorse fetch-subtitles /path/to/videos\ngifhorse fetch-subtitles /path/to/videos --skip-existing\n\nSearch Dialogue\n\nFind quotes across your entire library:\n\n# Basic search\ngifhorse search \"memorable quote\"\n\n# Search with surrounding context\ngifhorse search \"memorable quote\" --context 2\n\n# Show all results (no limit)\ngifhorse search \"memorable quote\" --all\n\n# Custom result limit (default: 100)\ngifhorse search \"memorable quote\" --limit 50\n\nPreview Before Creating\n\nSee exactly what will be captured:\n\ngifhorse preview \"memorable quote\" 1\ngifhorse preview \"quote\" 1 --include-before 1 --include-after 1\n\nCreate GIF\n\nGenerate the GIF with subtitles:\n\n# Basic GIF (auto-named from dialogue, saved to exports/)\ngifhorse create \"memorable quote\" 1\n\n# Explicit output path\ngifhorse create \"memorable quote\" 1 -o reaction.gif\n\n# High quality for social media\ngifhorse create \"quote\" 1 --width 720 --fps 24 --quality high\n\n# Include conversation context\ngifhorse create \"quote\" 1 --include-before 2 --include-after 1\n\n# Substitute words in subtitles (repeatable, target segments by number from preview)\ngifhorse create \"the age of men\" 1 --include-after 1 \\\n  -s 1 \"men\" \"standardized software\" \\\n  -s 2 \"orc\" \"custom applications\"\n\n# Clean replace (no strikethrough)\ngifhorse create \"quote\" 1 -r 1 \"old word\" \"new word\"\n\n# Create and send via iMessage\ngifhorse create \"quote\" 1 --send\ngifhorse create \"quote\" 1 --send-to \"+15551234567\"\n\nManage Database\n# Remove videos by path pattern (SQL LIKE wildcards)\ngifhorse remove \"%Adventure Time%\"\ngifhorse remove \"%S01%\" --yes\n\n# Check subtitle status for a directory\ngifhorse subtitle-status ~/Videos\ngifhorse subtitle-status ~/Videos --missing-only\n\nCheck Status\n# See transcription stats\ngifhorse stats\n\n# List all transcribed videos\ngifhorse list\n\nConfiguration\n# Set phone number for iMessage sending\ngifhorse config --set-phone \"+15551234567\"\n\n# Show current configuration\ngifhorse config --show\n\nTiming Options\n\nControl exactly what gets captured:\n\n--include-before N - Include N dialogue segments before the match\n--include-after N - Include N dialogue segments after the match\n--padding-before SECS - Add buffer seconds before dialogue starts (default: 1.0)\n--padding-after SECS - Add buffer seconds after dialogue ends (default: 1.0)\n--start-offset SECS - Manual adjustment to start time (can be negative)\n--end-offset SECS - Manual adjustment to end time (can be negative)\n\nImportant: For reactions after dialogue, use --padding-after instead of --include-after. The include-after option captures ALL time until the next dialogue segment (could be 30+ seconds!).\n\nQuality Options\n--quality low|medium|high - Color palette quality (affects file size)\n--fps N - Frames per second (default: 15, use 24 for smooth)\n--width N - Width in pixels (default: 480, use 720 for HD)\nSubtitle Options\n-s, --sub NUM OLD NEW - Substitute words in a segment (repeatable). Replaced words render struck through in red, replacements in red. Segment numbers shown by preview.\n-r, --replace NUM OLD NEW - Replace words cleanly (no strikethrough). Repeatable.\n--no-subtitles - Create GIF without subtitle overlay\nOutput\nDefault output filename is auto-derived from dialogue text (e.g., i_dont_think_so.gif) and saved to exports/\nUse -o PATH to override. Collision handling appends _2, _3, etc.\niMessage\n--send - Send created GIF to configured phone number via iMessage (macOS only)\n--send-to NUMBER - Send to a specific phone number (overrides config)\n\nNote: All GIFs automatically include a subtle \"gifhorse\" watermark in the bottom-right corner.\n\nCommon Workflows\nQuick Reaction GIF\ngifhorse search \"perfect\"\ngifhorse create \"perfect\" 1 --padding-after 2.0\n\nFull Conversation Exchange\ngifhorse search \"key phrase\"\ngifhorse preview \"key phrase\" 1 --include-before 2 --include-after 1\ngifhorse create \"key phrase\" 1 --include-before 2 --include-after 1\n\nMeme with Word Substitution\ngifhorse preview \"the age of men\" 1 --include-after 1\ngifhorse create \"the age of men\" 1 --include-after 1 \\\n  -s 1 \"men\" \"standardized software\" \\\n  -s 2 \"orc\" \"custom applications\"\n\nHigh Quality for Twitter/X\ngifhorse create \"quote\" 1 --width 720 --fps 24 --quality high -o tweet.gif\n\nScene with Reaction After Dialogue\ngifhorse create \"memorable line\" 1 --padding-after 3.0\n\nCreate and Send via iMessage\ngifhorse config --set-phone \"+15551234567\"\ngifhorse create \"quote\" 1 --send\n\nTips & Tricks\nAlways preview first - Use preview to verify timing before creating\nDefault downloads subtitles - Just run gifhorse transcribe and subtitles are fetched automatically\nWatch file sizes - High quality + long duration = large files (20s can be 20+ MB)\nPadding vs Include - For reactions, use --padding-after not --include-after\nSearch with context - Add --context 2 to see surrounding dialogue\nRe-transcribe with --force - Use --force to update transcriptions after getting better subtitles\nCheck subtitle coverage - Use subtitle-status to see which videos need subtitles\nFile Size Guide\nLow quality, 10s, 360p: ~1-2 MB\nMedium quality, 10s, 480p: ~3-5 MB\nHigh quality, 20s, 720p: ~20+ MB\nTroubleshooting\n\"command not found: gifhorse\"\n\nActivate the virtual environment:\n\ncd ~/gifhorse && source venv/bin/activate\n\nSubtitle rendering errors\n\nMake sure FFmpeg-full is installed:\n\nbrew install ffmpeg-full\n\nVideo file not found\n\nThe database stores absolute paths. If you moved videos after transcription, re-transcribe in the new location.\n\nNetwork Share Support\n\nGifHorse works with network-mounted videos:\n\n# Mount network share (macOS)\nopen \"smb://server-ip/share-name\"\n\n# Transcribe from network\ngifhorse transcribe \"/Volumes/server-ip/Movies\"\n\nWhen to Use This Skill\n\nInvoke gifhorse when the user wants to:\n\nSearch for dialogue or quotes in their video library\nCreate a reaction GIF from a movie or TV show\nMake a meme GIF with substituted words\nAdd subtitles to a video clip\nTranscribe videos for searchable dialogue\nPreview what a GIF will look like before creating it\nSend a GIF via iMessage\nRemove videos from the database\nCheck subtitle status for their video collection\nLearn More\nGitHub: https://github.com/Coyote-git/gifhorse\nUsage Guide: https://github.com/Coyote-git/gifhorse/blob/main/USAGE_GUIDE.md\nRoadmap: https://github.com/Coyote-git/gifhorse/blob/main/ROADMAP.md\nLicense\n\nMIT"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/Coyote-git/gifhorse",
    "publisherUrl": "https://clawhub.ai/Coyote-git/gifhorse",
    "owner": "Coyote-git",
    "version": "1.2.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/gifhorse",
    "downloadUrl": "https://openagent3.xyz/downloads/gifhorse",
    "agentUrl": "https://openagent3.xyz/skills/gifhorse/agent",
    "manifestUrl": "https://openagent3.xyz/skills/gifhorse/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/gifhorse/agent.md"
  }
}