{
  "schemaVersion": "1.0",
  "item": {
    "slug": "photos",
    "name": "Photos",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/ivangdavila/photos",
    "canonicalUrl": "https://clawhub.ai/ivangdavila/photos",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/photos",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=photos",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "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/photos"
    },
    "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/photos",
    "agentPageUrl": "https://openagent3.xyz/skills/photos/agent",
    "manifestUrl": "https://openagent3.xyz/skills/photos/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/photos/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": "Safety First",
        "body": "Never delete photos directly — move to .photo-trash/ folder with original path preserved in filename\nNever overwrite originals — edits go to edited/ subfolder, originals stay untouched\nBefore bulk operations, create manifest: photos-pending.json with planned actions for user review\nWhen user says \"delete duplicates\", move to trash and report count — let them empty trash manually"
      },
      {
        "title": "Indexing Strategy",
        "body": "Create .photo-index/ in library root with one JSON sidecar per photo\nSidecar filename: {original-hash}.json — survives renames and moves\nIndex fields: hash, path, date_taken, camera, gps, description, tags, indexed_at\nRun indexing incrementally — skip files with matching hash already indexed\nStore description from vision analysis in sidecar, not in EXIF (non-destructive)"
      },
      {
        "title": "Vision Analysis (Token-Efficient)",
        "body": "Don't analyze every photo upfront — index on-demand when user searches or asks\nCache vision results permanently in sidecar JSON — never re-analyze same photo\nFor bulk analysis, process in batches of 20 with progress updates\nUse concise prompts: \"Describe this photo in 2-3 sentences. List people, objects, location, activity.\"\nSkip screenshots and memes (detect by aspect ratio + lack of EXIF) unless explicitly requested"
      },
      {
        "title": "Duplicate Detection",
        "body": "Generate perceptual hash (pHash) alongside content hash — catches near-duplicates and resized copies\nGroup duplicates by pHash similarity, keep highest resolution as \"original\"\nReport duplicates with thumbnails/paths, never auto-delete\nConsider EXIF date — oldest is likely the original, newer copies are backups"
      },
      {
        "title": "Search Patterns",
        "body": "By content: Search sidecar descriptions with simple text match first, vision re-analysis if no hits\nBy date: Parse EXIF DateTimeOriginal, fall back to file mtime\nBy location: Reverse geocode GPS once, store city/country in sidecar for text search\nBy person: If user identifies someone once (\"that's Maria\"), tag all similar faces in index"
      },
      {
        "title": "EXIF Handling",
        "body": "Read: exiftool -json photo.jpg — returns all metadata as JSON\nWrite date: exiftool -DateTimeOriginal=\"2024:03:15 14:30:00\" photo.jpg\nStrip GPS before sharing: exiftool -gps:all= photo.jpg (operates on copy, not original)\nBatch read: exiftool -json -r /photos/ — recursive, outputs array"
      },
      {
        "title": "File Organization",
        "body": "Propose structure, don't impose: YYYY/MM/ or YYYY/MM-DD/ based on user preference\nRename pattern: YYYYMMDD_HHMMSS_originalname.ext — preserves original name, adds sortable prefix\nHandle timezone: EXIF dates are local time — ask user's timezone once, store in .photo-index/config.json\nHEIC to JPEG: sips -s format jpeg input.heic --out output.jpg (macOS) or heif-convert (Linux)"
      },
      {
        "title": "NAS/Remote Libraries",
        "body": "For Synology/NAS: work with mounted paths, don't assume local speeds\nTest connection before bulk operations: ls /Volumes/photos | head -1\nFor slow connections, build local index cache that syncs periodically\nRespect @eaDir (Synology thumbnails) and .DS_Store — skip in indexing"
      }
    ],
    "body": "Safety First\nNever delete photos directly — move to .photo-trash/ folder with original path preserved in filename\nNever overwrite originals — edits go to edited/ subfolder, originals stay untouched\nBefore bulk operations, create manifest: photos-pending.json with planned actions for user review\nWhen user says \"delete duplicates\", move to trash and report count — let them empty trash manually\nIndexing Strategy\nCreate .photo-index/ in library root with one JSON sidecar per photo\nSidecar filename: {original-hash}.json — survives renames and moves\nIndex fields: hash, path, date_taken, camera, gps, description, tags, indexed_at\nRun indexing incrementally — skip files with matching hash already indexed\nStore description from vision analysis in sidecar, not in EXIF (non-destructive)\nVision Analysis (Token-Efficient)\nDon't analyze every photo upfront — index on-demand when user searches or asks\nCache vision results permanently in sidecar JSON — never re-analyze same photo\nFor bulk analysis, process in batches of 20 with progress updates\nUse concise prompts: \"Describe this photo in 2-3 sentences. List people, objects, location, activity.\"\nSkip screenshots and memes (detect by aspect ratio + lack of EXIF) unless explicitly requested\nDuplicate Detection\nGenerate perceptual hash (pHash) alongside content hash — catches near-duplicates and resized copies\nGroup duplicates by pHash similarity, keep highest resolution as \"original\"\nReport duplicates with thumbnails/paths, never auto-delete\nConsider EXIF date — oldest is likely the original, newer copies are backups\nSearch Patterns\nBy content: Search sidecar descriptions with simple text match first, vision re-analysis if no hits\nBy date: Parse EXIF DateTimeOriginal, fall back to file mtime\nBy location: Reverse geocode GPS once, store city/country in sidecar for text search\nBy person: If user identifies someone once (\"that's Maria\"), tag all similar faces in index\nEXIF Handling\nRead: exiftool -json photo.jpg — returns all metadata as JSON\nWrite date: exiftool -DateTimeOriginal=\"2024:03:15 14:30:00\" photo.jpg\nStrip GPS before sharing: exiftool -gps:all= photo.jpg (operates on copy, not original)\nBatch read: exiftool -json -r /photos/ — recursive, outputs array\nFile Organization\nPropose structure, don't impose: YYYY/MM/ or YYYY/MM-DD/ based on user preference\nRename pattern: YYYYMMDD_HHMMSS_originalname.ext — preserves original name, adds sortable prefix\nHandle timezone: EXIF dates are local time — ask user's timezone once, store in .photo-index/config.json\nHEIC to JPEG: sips -s format jpeg input.heic --out output.jpg (macOS) or heif-convert (Linux)\nNAS/Remote Libraries\nFor Synology/NAS: work with mounted paths, don't assume local speeds\nTest connection before bulk operations: ls /Volumes/photos | head -1\nFor slow connections, build local index cache that syncs periodically\nRespect @eaDir (Synology thumbnails) and .DS_Store — skip in indexing"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/ivangdavila/photos",
    "publisherUrl": "https://clawhub.ai/ivangdavila/photos",
    "owner": "ivangdavila",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/photos",
    "downloadUrl": "https://openagent3.xyz/downloads/photos",
    "agentUrl": "https://openagent3.xyz/skills/photos/agent",
    "manifestUrl": "https://openagent3.xyz/skills/photos/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/photos/agent.md"
  }
}