Immich-photo-manager album-manager
git clone https://github.com/drolosoft/immich-photo-manager
T=$(mktemp -d) && git clone --depth=1 https://github.com/drolosoft/immich-photo-manager "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/album-manager" ~/.claude/skills/drolosoft-immich-photo-manager-album-manager && rm -rf "$T"
skills/album-manager/SKILL.mdAlbum Manager
⚠️ Connection Required — ALWAYS CHECK FIRST
Before doing ANYTHING else in this skill, call
on the Immich MCP server.ping
- If
succeeds → proceed with the skill normally.ping - If
fails or the MCP tools are not available → STOP. Do not continue. Tell the user:ping
❌ Immich is not connected. This plugin needs a running Immich MCP server to work.
Run /setup-immich-photo-manager to configure your Immich connection. You'll need:
- Your Immich server URL (e.g.,
)http://192.168.1.100:2283- An Immich API key (how to create one)
- The MCP server running (
)./immich-mcp-serverNothing in this plugin will work until the connection is configured.
Do NOT skip this check. Do NOT try to run any other tool first. Always ping, always block if it fails.
Intelligent album creation and curation for Immich photo libraries. Organizes photos geographically by default — albums represent places, not dates.
Core Principle
Geography first, chronology second. A user who visited Mexico twice gets one "Mexico" album (or sub-albums by city), not "Mexico 2018" and "Mexico 2023". Dates are metadata shown inside the album, never the organizing principle.
Available MCP Tools
Use the Immich MCP tools for all API interactions:
— Search by GPS coordinates, date range, city, country, camera, person, or smart/CLIP text queryimmich_search_assets
— Create a new album with name and descriptionimmich_create_album
— Add photos/videos to an album by asset IDsimmich_add_assets_to_album
— Remove assets from an albumimmich_remove_assets_from_album
— List all albums with asset countsimmich_list_albums
— Get album details including all assetsimmich_get_album
— Delete an album (does NOT delete the photos)immich_delete_album
— Create a public shared link for an album (makes it visible in Gallery)immich_create_shared_link
— Get full metadata for a specific asset (GPS, EXIF, dates)immich_get_asset_info
— Get library statistics (total photos, videos, storage)immich_get_statistics
— Get base64 thumbnail for an asset (used for gallery HTML generation)immich_get_asset_thumbnail
Album Creation Workflow
1. Discover photos for a location
Search by GPS bounding box OR by CLIP semantic search OR by date range:
# GPS-based (most accurate) immich_search_assets(latitude=41.87, longitude=12.49, radius_km=50) # Rome area # CLIP semantic search (when GPS is missing) immich_search_assets(query="Colosseum Rome Italy") # Date-based (supplement) immich_search_assets(date_from="2023-06-01", date_to="2023-06-15") # Combined immich_search_assets(latitude=41.87, longitude=12.49, radius_km=50, date_from="2023-06-01")
2. Filter and curate
From the search results, filter out:
- Screenshots (typical screen resolutions, no GPS, no lens info)
- Duplicate/near-duplicate images
- Blurry or very dark photos (if quality metadata available)
- Photos that don't match the location theme
Prefer photos that:
- Have strong composition or visual interest
- Show landmarks, landscapes, or characteristic scenes of the place
- Have good resolution and quality
- Tell the story of the place
Target: 20-50 photos per album for optimal gallery experience. Can go up to 100 for major destinations.
3. Create the album
Naming convention:
[Country emoji] Place, Country Examples: 🇮🇹 Cinque Terre, Italia 🇪🇬 Cairo & Luxor, Egypt 🇲🇽 Chiapas, México 🏝️ Lanzarote 🌴 La Palma 🏙️ Barcelona
For the description, include:
- When the photos were taken (year or date range)
- Brief context (e.g., "Summer road trip through coastal villages")
- Number of photos
4. Share for Gallery publication
After creating the album, create a shared link to make it visible in the Gallery frontend:
immich_create_shared_link(album_id="{id}", show_metadata=true, allow_download=false)
5. Verify
Confirm the album appears correctly:
- Check album name and description
- Verify photo count matches expectations
- Confirm shared link is active
Batch Album Creation
When creating multiple albums at once (e.g., "create albums for all my trips"):
- First, get library statistics and map view data to understand what locations exist
- Cluster photos by GPS coordinates to identify distinct locations
- Present a proposed album list to the user for approval BEFORE creating
- Create albums one by one, reporting progress
- Summarize all created albums at the end
Always err on the side of creating MORE albums — the user can merge or delete later. It's easier to remove an unwanted album than to discover a missing one.
Handling Missing GPS Data
Many photos (especially older ones or screenshots) lack GPS coordinates. Strategy:
- First search by GPS for photos that have it
- Then search by date range to find photos taken during the same trip
- Use CLIP semantic search as a fallback ("beach Lanzarote", "pyramid Egypt")
- Flag photos without GPS that were found by date/CLIP — they may or may not belong
Album Maintenance
When asked to update or refine an existing album:
- Get current album contents
- Search for additional photos that might belong (expanded date range, nearby GPS, related CLIP queries)
- Present additions and potential removals to the user
- Apply changes after approval
Gallery HTML Generation
When the user asks to "show me photos from [album]", "generate a gallery for [album]", "show me [album name]", or any variation of viewing/displaying album contents visually, generate an interactive HTML gallery page.
Template
Use the gallery template at
assets/viewer-template.html (from the plugin root). This is a self-contained, single-file HTML gallery with:
- Triple theme support — Light, System (auto-detects), and Dark modes
- 5 view modes: detail grid, icon grid, list, masonry, compact
- Full-screen gallery overlay with keyboard navigation (arrows, Escape, Space for slideshow)
- Touch/swipe gestures for mobile
- Lazy loading with intersection observers
- Manual pagination with "Load more" button (no infinite scroll)
- Slideshow mode with progress bar
- Polaroid-style album cards linking back to Immich
- Responsive design for all screen sizes
Placeholder Reference
The template uses these placeholders that MUST be replaced:
| Placeholder | Description | Example |
|---|---|---|
| Display name of the album | |
| Total number of photos in the album | |
| The query or description used to find photos | |
| Immich server base URL | |
| Number of photos per lazy-load page | |
| Total photos in the gallery (limit ~50 for file size) | |
| The photo data entries (see format below) | See below |
| JSON array of album links | See below |
Photo Entry Format (base64 embedded thumbnails)
The Cowork viewer runs in an
about: protocol sandbox that blocks ALL external network requests. Thumbnails MUST be embedded as base64 data: URIs.
Each entry in
{{PHOTO_ENTRIES}} includes the full thumbnail data:
{src:'data:image/jpeg;base64,/9j/4AAQ...',id:'<asset-id>',name:'<filename>',date:'<ISO-date>'}
: Base64 data URI of the thumbnail (fromsrc
, size=thumbnail, ~250px, ~15-25KB each)get_thumbnails_batch
: The Immich asset ID (for linking to Immich web UI)id
: Original filename (displayed as label)name
: ISO date string from the asset metadatadate
Always use
(250px) — never size="thumbnail"
preview (1440px). Thumbnails average ~18KB each, so 50 photos ≈ 0.9MB HTML file.
Entries are comma-separated, one per line.
Albums JSON Format
{{ALBUMS_JSON}} is injected raw into JS. It can be either a JSON array [{...}] or a single object {...} — the template handles both. Use standard JSON with quoted keys:
[{"id":"<album-id>","name":"<Album Name>","total":<count>}]
Each album object needs:
id (string), name (string), total (integer).
Generation Workflow
- Get album data: Call
to get the album ID, name, and full asset list (IDs, filenames, dates)get_album - Fetch thumbnails: Call
— call in batches of 50 if neededget_thumbnails_batch(asset_ids=[...], size="thumbnail", limit=50) - Read the template: Read
from the plugin rootassets/viewer-template.html - Replace placeholders: Fill in all
placeholders{{...}} - Build
:{{PHOTO_ENTRIES}}
for each asset with base64 thumbnail{src:'data:...',id:'...',name:'...',date:'...'} - Write the HTML: Save to the outputs directory as
(~0.9MB for 50 photos)<album-name-slug>.html - Present to user: Share the file link via
computer://
is REQUIRED. The Cowork sandbox blocks all external requests — base64 is the only way.get_thumbnails_batch
⚠️ Placeholder Rules (IMPORTANT)
,{{PAGE_SIZE}}
,{{PHOTO_COUNT}}
: Must be plain integers (e.g.{{ALBUM_TOTAL}}
, not200
or200+
). These are injected directly into JavaScript."200"
,{{ALBUM_NAME}}
,{{SEARCH_QUERY}}
: Can be any string (they are placed inside HTML or JS string literals).{{IMMICH_URL}}
: Must be valid JS object literals, comma-separated.{{PHOTO_ENTRIES}}
: Must be comma-separated JSON objects (NOT wrapped in array brackets — the template adds{{ALBUMS_JSON}}
). Example:[...]
. If no related albums, use empty string.{"id":"abc","name":"My Album","total":50}
CRITICAL: Related Albums = REAL Albums Only
The
placeholder must ONLY contain real, user-created albums. Never fabricate album entries. Never create temporary albums to populate this field.{{ALBUMS_JSON}}
When generating a gallery for an album, find OTHER real albums that are related (e.g., same country, same trip) and list them as Related Albums. If there are no related albums, use
[].
Performance Notes
- PAGE_SIZE: Keep at 20 for initial load. Pagination is manual ("Load more" button)
- PHOTO_COUNT: Limit to ~50 photos per gallery for reasonable file size (~0.9MB)
- Thumbnails: Embedded as base64 via
— ~18KB avg eachget_thumbnails_batch(size="thumbnail") - For albums with 100+ photos, show first 50 and tell the user the total count
Example: Generating a gallery
User: "Show me photos from Lanzarote Verde" 1. list_albums() -> find "Lanzarote Verde" album (id: abc123, 273 photos) 2. get_album(album_id="abc123") -> get full asset list with IDs, names, dates 3. Read assets/viewer-template.html 4. Replace: - {{ALBUM_NAME}} -> "Lanzarote Verde" - {{ALBUM_TOTAL}} -> 273 - {{SEARCH_QUERY}} -> "Lanzarote Verde" - {{IMMICH_URL}} -> "https://your-immich-server.com" - {{PAGE_SIZE}} -> 20 - {{PHOTO_COUNT}} -> 50 (first 50 of 273) - {{PHOTO_ENTRIES}} -> {src:'data:image/jpeg;base64,...',id:"abc",name:"IMG_001",date:"2023-06-15"},{src:'data:...',id:"def",...} - {{ALBUMS_JSON}} -> {"id":"abc123","name":"Lanzarote Verde","total":273} 5. Save as lanzarote-verde.html (~0.9MB) 6. Present computer:// link
Reference Files
— GPS bounding boxes of common destinations and search strategiesreferences/geographic-search-patterns.md
— Dashboard template listing all saved gallery HTML filesassets/index-template.html
— Self-contained HTML gallery template with dark/light themes, multiple view modes, slideshow, Cowork Actions Panel, and keyboard navigationassets/viewer-template.html