Help us improve
Share bugs, ideas, or general feedback.
From immich-photo-manager
Runs a comprehensive health check on an Immich photo library — asset counts, storage usage, metadata completeness, orphaned files, and quality indicators.
npx claudepluginhub drolosoft/immich-photo-manager --plugin immich-photo-managerHow this skill is triggered — by the user, by Claude, or both
Slash command
/immich-photo-manager:library-health-reportThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Before doing ANYTHING else in this skill, call `ping` on the Immich MCP server.**
Analyzes disk usage in an Immich photo library and identifies storage reclamation opportunities: redundant RAW+JPEG pairs, oversized videos, bloated sidecar files, and format inefficiencies.
Audits images for SEO and performance: alt text, file sizes, formats, responsive images, lazy loading, CLS prevention, and SERP rankings. Also handles WebP/AVIF conversion and IPTC/XMP metadata injection.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
Before doing ANYTHING else in this skill, call ping on the Immich MCP server.
ping succeeds → proceed with the skill normally.ping fails or the MCP tools are not available → STOP. Do not continue. Tell the user:❌ 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 configured (see /setup-immich-photo-manager)
Nothing 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.
Generate a comprehensive health assessment of an Immich photo library. Covers asset inventory, storage breakdown, metadata quality, and actionable recommendations.
Query Immich for the full library snapshot:
-- Total assets by type
SELECT type, count(*) as total,
pg_size_pretty(sum(("exifInfo"->>'fileSizeInByte')::bigint)) as total_size
FROM asset
WHERE "deletedAt" IS NULL
GROUP BY type;
-- Trash contents
SELECT type, count(*) as trashed
FROM asset
WHERE "deletedAt" IS NOT NULL
GROUP BY type;
Also use the MCP tool get_statistics for the official Immich counts.
Present as:
ASSET INVENTORY
Photos: 39,596
Videos: 4,983
Total live: 44,579
In trash: 8,433
Storage used: ~180 GB
Identify where photos came from:
SELECT
CASE
WHEN "originalPath" LIKE '%Apple Fotos%' OR "originalPath" LIKE '%Apple Photos%' THEN 'Apple Photos'
WHEN "originalPath" LIKE '%Google Fotos%' OR "originalPath" LIKE '%Google Photos%' THEN 'Google Photos'
WHEN "originalPath" LIKE '%upload%' THEN 'Direct Upload'
ELSE split_part("originalPath", '/', 5)
END as source,
count(*) as total,
min("localDateTime") as earliest,
max("localDateTime") as latest
FROM asset WHERE "deletedAt" IS NULL
GROUP BY source ORDER BY total DESC;
Check for gaps in critical metadata fields:
-- GPS coverage
SELECT
count(*) as total,
count(*) FILTER (WHERE "exifInfo"->>'latitude' IS NOT NULL) as has_gps,
round(100.0 * count(*) FILTER (WHERE "exifInfo"->>'latitude' IS NOT NULL) / count(*), 1) as gps_pct
FROM asset WHERE "deletedAt" IS NULL AND type = 'IMAGE';
-- Date quality
SELECT
count(*) FILTER (WHERE "exifInfo"->>'dateTimeOriginal' IS NOT NULL) as has_exif_date,
count(*) FILTER (WHERE extract(hour from "localDateTime") = 12
AND extract(minute from "localDateTime") = 0) as suspicious_noon,
count(*) FILTER (WHERE extract(hour from "localDateTime") = 0
AND extract(minute from "localDateTime") = 0) as suspicious_midnight
FROM asset WHERE "deletedAt" IS NULL AND type = 'IMAGE';
-- Camera info
SELECT
count(*) FILTER (WHERE "exifInfo"->>'make' IS NOT NULL) as has_camera_make,
count(*) FILTER (WHERE "exifInfo"->>'lensModel' IS NOT NULL) as has_lens
FROM asset WHERE "deletedAt" IS NULL AND type = 'IMAGE';
Present as:
METADATA QUALITY
GPS coverage: 72.3% (28,616 of 39,596 photos)
EXIF dates: 89.1% (35,280 photos)
Suspicious dates: 1,204 (noon/midnight — likely recovered from paths)
Camera info: 68.4% (27,072 photos)
Lens info: 52.1% (20,623 photos)
SELECT extract(year from "localDateTime") as year,
count(*) as photos,
count(*) FILTER (WHERE type = 'VIDEO') as videos
FROM asset WHERE "deletedAt" IS NULL
GROUP BY year ORDER BY year;
Highlight years with unusually low counts (potential missing imports).
SELECT
upper(split_part("originalPath", '.', -1)) as format,
count(*) as total,
pg_size_pretty(sum(("exifInfo"->>'fileSizeInByte')::bigint)) as size
FROM asset WHERE "deletedAt" IS NULL
GROUP BY format ORDER BY total DESC
LIMIT 15;
Based on findings, generate actionable recommendations:
The report can be presented as:
Always ask the user which format they prefer.