Claude-skill-registry documentation-asset-manager
Manages Tallyfy documentation assets on Cloudflare R2. Uploads images, generates AI captions using Claude Code native vision, maintains CSV inventory with build-time integration. Use when managing docs screenshots or media files.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/documentation-asset-manager" ~/.claude/skills/majiayu000-claude-skill-registry-documentation-asset-manager && rm -rf "$T"
skills/data/documentation-asset-manager/SKILL.mdDocumentation Asset Manager
Purpose
Automates the complete workflow for Tallyfy documentation asset management with Claude Code native vision:
- Upload assets to Cloudflare R2 storage (screenshots bucket)
- Generate AI captions using Claude Code native vision (alt text, descriptive, SEO)
- Maintain CSV inventory at
$GITHUB_ROOT/documentation/documentation_assets.csv - Build-time integration - Automatic alt text injection during Starlight builds
- Return public URLs immediately (screenshots.tallyfy.com domain)
- Track asset usage across documentation files
Recent Updates (v2.0.0)
✅ Completed:
- 287 images captioned with vision-based analysis (100% coverage for native images)
- Claude Code native - No external API key needed
- Build-time integration - Remark plugin auto-injects alt text from CSV
- Parallel Task agents - Batch processing support
- Path portability - Auto-detection, works on any developer machine
Activation Triggers
- "upload documentation asset"
- "upload screenshot to R2"
- "add image to docs"
- "manage documentation media"
- "generate image caption"
- "update documentation screenshot"
- When user provides image/asset path for documentation
Prerequisites
Required Credentials (in parent directory):
with fields:$GITHUB_ROOT/cloudflare_credentials.json
- Cloudflare account IDaccount_id
- Cloudflare API token with R2 accessapi_token
Required Packages (auto-check):
pip3 install pillow requests
Claude Code Native (Recommended):
- No external API key needed - Uses Claude Code's native vision capabilities
- For batch operations: Use Task agents (see Batch Vision Captioning section)
- For single images:
uses subprocess to call claude nativeimage_captioner.py
Instructions
Step 1: Validate Prerequisites
# Check credentials exist test -f $GITHUB_ROOT/cloudflare_credentials.json || echo "❌ Credentials missing" # Check Anthropic API key test -f ~/.anthropic/api_key || echo "⚠️ Set ANTHROPIC_API_KEY or create ~/.anthropic/api_key" # Check Python packages python3 -c "import anthropic, PIL, requests" 2>/dev/null || echo "⚠️ Run: pip3 install anthropic pillow requests"
Step 2: Upload Asset to R2
Use the R2 uploader script to upload any file:
# Single file upload python3 ~/.claude/skills/documentation-asset-manager/scripts/r2_uploader.py \ --file /path/to/screenshot.png \ --key "tallyfy/pro/desktop-light-new-feature.png" \ --credentials $GITHUB_ROOT/cloudflare_credentials.json # Returns JSON with public URL: # { # "success": true, # "url": "https://screenshots.tallyfy.com/tallyfy/pro/desktop-light-new-feature.png", # "key": "tallyfy/pro/desktop-light-new-feature.png", # "size": "125.4KB" # }
Step 3: Generate AI Captions
Generate all three caption types using Claude Code native vision:
For Single Images:
# Generate captions using Claude Code native (no API key needed) python3 ~/.claude/skills/documentation-asset-manager/scripts/image_captioner.py \ --url "https://screenshots.tallyfy.com/tallyfy/pro/desktop-light-new-feature.png" \ --output /tmp/captions.json # Returns: # { # "captions": { # "alt_text": "Task assignment interface showing user selection dropdown", # "descriptive": "Tallyfy task assignment screen with dropdown menu...", # "seo": "Tallyfy task assignment feature showing how to assign tasks..." # } # }
For Batch Operations (Recommended for >10 images):
# Use Task agents for parallel processing # See "Batch Vision Captioning" section below
Step 4: Update CSV Inventory
Add asset to master inventory CSV:
# Add to inventory python3 ~/.claude/skills/documentation-asset-manager/scripts/asset_inventory.py \ --action add \ --r2-key "tallyfy/pro/desktop-light-new-feature.png" \ --url "https://screenshots.tallyfy.com/tallyfy/pro/desktop-light-new-feature.png" \ --captions /tmp/captions.json \ --article-ids "pro-tasks-assign,pro-getting-started"
Step 5: Complete Workflow (Orchestrator)
For one-command complete workflow:
# Upload + Caption + Inventory in one go python3 ~/.claude/skills/documentation-asset-manager/scripts/orchestrator.py \ --file /path/to/screenshot.png \ --key "tallyfy/pro/desktop-light-new-feature.png" \ --article-ids "pro-tasks-assign" \ --credentials $GITHUB_ROOT/cloudflare_credentials.json # Complete output: # ✅ Uploaded: https://screenshots.tallyfy.com/tallyfy/pro/desktop-light-new-feature.png # ✅ Alt text: "Task assignment interface showing user selection dropdown" # ✅ Added to inventory: $GITHUB_ROOT/documentation/documentation_assets.csv
Build-Time Integration
Automatic Alt Text Injection:
The master CSV is integrated with Starlight documentation builds via a remark plugin:
Location:
/support-docs/src/plugins/remark/inject-alt-text.ts
How It Works:
- During build, remark plugin reads
/documentation/documentation_assets.csv - Matches image URLs in markdown to CSV entries
- Auto-injects
as alt textai_caption_alt - Handles URL encoding/decoding automatically
- Falls back gracefully if CSV unavailable
Local Development:
cd /support-docs # CSV symlinked to ../documentation/documentation_assets.csv npm run dev # Alt text injected automatically
CI/CD (Netlify):
# package.json prebuild script copies CSV npm run prebuild # Copies CSV before build npm run build # Alt text injected during build
Example:
<!-- Before build: -->  <!-- After build: --> 
Batch Vision Captioning
For Large-Scale Caption Regeneration:
When regenerating captions for many images (>10), use parallel Task agents for efficiency:
Process:
- Prepare images - Download and resize to max 1800px (Claude vision constraint)
- Launch Task agents - Process in parallel batches of ~48 images
- Consolidate results - Merge all batch outputs
- Update CSV - Apply new captions to master inventory
Example (287 images completed in ~60 minutes):
# See /temporary/asset-inventory/ for reference implementation: # - prepare_images_for_vision.py (download + resize) # - Task agents launched in parallel (6 batches of ~48 images) # - consolidate_and_update.py (merge results → CSV)
Why Task Agents:
- Native Claude Code vision (no API keys)
- Parallel processing (6x speedup)
- Automatic retry and error handling
- Real-time progress tracking
Workflow Patterns
Pattern 1: Upload New Screenshot
# User: "Upload this screenshot to docs" # Skill detects image file path, generates reasonable R2 key from filename # Executes: upload → generate captions → update inventory → return URL
Pattern 2: Replace Existing Screenshot
# User: "Replace screenshot at /tallyfy/pro/desktop-light-tasks.png" # Skill: uploads with same key (overwrites), regenerates captions, updates inventory
Pattern 3: Batch Upload
# User: "Upload all screenshots in /docs/images/" # Skill: processes each file sequentially with delays to avoid rate limits
Pattern 4: Generate Caption Only
# User: "Generate caption for existing image at https://screenshots.tallyfy.com/..." # Skill: skips upload, generates captions using Claude Code native, updates inventory
Pattern 5: Regenerate All Captions (Completed)
# All 287 native images now have vision-based captions (completed 2025-11) # Location: /documentation/documentation_assets.csv (columns: ai_caption_alt, ai_caption_descriptive, ai_caption_seo) # Build integration: Auto-injected during Starlight builds via remark plugin
Temporary Assets
Working Directory:
$GITHUB_ROOT/temporary/asset-manager/
Files Created:
- R2 upload responseupload_result.json
- Alt text captioncaptions_alt.json
- Descriptive captioncaptions_descriptive.json
- SEO captioncaptions_seo.json
- Combined metadataasset_metadata.json
- Processing logprocessing.log
Cleanup: Temporary files auto-cleaned after successful completion
Master Asset Inventory
Location:
$GITHUB_ROOT/documentation/documentation_assets.csv
CSV Columns:
- Asset filenamefilename
- Full R2 bucket keyr2_key
- Public URL (screenshots.tallyfy.com)production_url
- native|orphaned|external|missingsource_type
- File extensionfile_type
- Human-readable sizefile_size
- Size in bytesfile_size_bytes
- Boolean (URL accessible)url_exists
- Comma-separated article IDsarticle_ids
- Number of articles referencingarticle_count
- R2 last modified timestamplast_modified
- R2 ETagetag
- Alt text captionai_caption_alt
- Detailed captionai_caption_descriptive
- SEO-optimized captionai_caption_seo
- yes|no (based on file type)needs_caption
Auto-Update: CSV automatically updated on any upload/delete/caption operation
Error Handling
Scenario 1: Credentials Missing
ERROR: Credentials file not found ACTION: Check $GITHUB_ROOT/cloudflare_credentials.json exists PROMPT: "Cannot find Cloudflare credentials. Ensure file exists with: - account_id - api_token"
Scenario 2: R2 Upload Fails
ERROR: R2 upload failed (API error) ACTION: Retry once after 5s, then notify user PROMPT: "Upload to R2 failed: {error_message} Retrying once..."
Scenario 3: Caption Generation Fails
ERROR: Claude API error (rate limit, network, etc) ACTION: Complete upload, skip caption, mark for later PROMPT: "File uploaded successfully to {url} Caption generation failed: {error} You can generate captions later with: python3 scripts/image_captioner.py --url {url}"
Scenario 4: Rate Limit Hit
ERROR: Anthropic API rate limit ACTION: Wait 60s, retry once, then defer PROMPT: "Rate limit reached. Waiting 60s before retry... If persistent, use --skip-captions flag to upload without captions"
Scenario 5: Inventory CSV Locked
ERROR: CSV file in use (another process) ACTION: Wait 2s, retry 3 times, then warn PROMPT: "Inventory CSV busy. Retried 3 times. Upload succeeded but inventory not updated. Run: python3 scripts/asset_inventory.py --sync to update manually"
Advanced Usage
Skip Caption Generation
# For quick uploads without AI captions python3 scripts/orchestrator.py --file screenshot.png --skip-captions
Regenerate Captions for Existing Assets
# Regenerate all captions for specific asset python3 scripts/image_captioner.py \ --url "https://screenshots.tallyfy.com/tallyfy/pro/desktop-light-tasks.png" \ --update-inventory
Bulk Operations
# Process all images in directory for img in /docs/screenshots/*.png; do python3 scripts/orchestrator.py --file "$img" --batch-mode sleep 3 # Delay between uploads done
Verify Inventory Integrity
# Check all URLs in inventory are accessible python3 scripts/asset_inventory.py --verify-urls
Generate Statistics
# Get inventory statistics python3 scripts/asset_inventory.py --stats # Output: # Total assets: 812 # Active (used in docs): 290 # Orphaned (not referenced): 499 # Missing (404s): 23 # Images with captions: 288
R2 Bucket Configuration
Bucket Name:
screenshots
Account ID: ac9046789c9ad74c8704a143b442f918
Public Domain: screenshots.tallyfy.com
API Endpoint: https://api.cloudflare.com/client/v4/accounts/{account_id}/r2/buckets/screenshots/objects
CDN: Cloudflare global edge cache
Naming Conventions
Recommended R2 Key Patterns:
-
Structured (Preferred):
tallyfy/pro/desktop-light-{action}-{context}.png tallyfy/pro/mobile-dark-{feature}.png manufactory/{feature}-{version}.png -
Legacy (Auto-generated):
file-{random_id}.png
Examples:
tallyfy/pro/desktop-light-assign-task.pngtallyfy/pro/desktop-light-sidebar-numerated.pngmanufactory-triggers-v2.png
Security Notes
- Credentials stored in parent directory (not in skill)
- No API keys embedded in skill files
- Anthropic API key from environment or user's ~/.anthropic/
- R2 bucket is private with public domain mapping
- All uploads go through Cloudflare API authentication
Troubleshooting
"Module not found" errors:
pip3 install pillow requests
"Credentials not found":
cat $GITHUB_ROOT/cloudflare_credentials.json # Should show account_id and api_token
"Claude Code not available":
# Ensure Claude Code CLI is installed and accessible which claude # Should return path to claude executable
For external API usage (legacy):
# Not recommended - use Claude Code native instead export ANTHROPIC_API_KEY="your-api-key-here"
"R2 upload succeeds but URL 404":
- Check bucket name is "screenshots"
- Verify custom domain screenshots.tallyfy.com is configured
- Wait 30-60s for CDN cache
"CSV inventory out of sync":
# Rebuild inventory from R2 + documentation python3 scripts/asset_inventory.py --rebuild
See Also
- Complete Cloudflare R2 API docsreferences/r2_api_reference.md
- Supported file types and limitsreferences/supported_formats.md
- Usage examples and tutorialsreferences/examples.md
- Documentation repo guidelines$GITHUB_ROOT/documentation/CLAUDE.md
Maintenance
Regular Tasks:
- Weekly: Verify inventory CSV integrity
- Monthly: Review orphaned assets (consider cleanup)
- Quarterly: Check for missing images (404s) and fix
- As needed: Regenerate captions for improved quality
Inventory Location:
- Primary:
(version controlled)$GITHUB_ROOT/documentation/documentation_assets.csv - Working Directory:
(generated master)$GITHUB_ROOT/temporary/asset-inventory/asset_inventory_master.csv