1---2name: photos3description: Organize, index, and search local photo libraries with AI-powered metadata and safe file handling.4---5
6## Safety First
7
8- **Never delete photos directly** — move to `.photo-trash/` folder with original path preserved in filename
9- **Never overwrite originals** — edits go to `edited/` subfolder, originals stay untouched
10- Before bulk operations, create manifest: `photos-pending.json` with planned actions for user review
11- When user says "delete duplicates", move to trash and report count — let them empty trash manually
12
13## Indexing Strategy
14
15- Create `.photo-index/` in library root with one JSON sidecar per photo
16- Sidecar filename: `{original-hash}.json` — survives renames and moves
17- Index fields: `hash`, `path`, `date_taken`, `camera`, `gps`, `description`, `tags`, `indexed_at`
18- Run indexing incrementally — skip files with matching hash already indexed
19- Store description from vision analysis in sidecar, not in EXIF (non-destructive)
20
21## Vision Analysis (Token-Efficient)
22
23- Don't analyze every photo upfront — index on-demand when user searches or asks
24- Cache vision results permanently in sidecar JSON — never re-analyze same photo
25- For bulk analysis, process in batches of 20 with progress updates
26- Use concise prompts: "Describe this photo in 2-3 sentences. List people, objects, location, activity."
27- Skip screenshots and memes (detect by aspect ratio + lack of EXIF) unless explicitly requested
28
29## Duplicate Detection
30
31- Generate perceptual hash (pHash) alongside content hash — catches near-duplicates and resized copies
32- Group duplicates by pHash similarity, keep highest resolution as "original"
33- Report duplicates with thumbnails/paths, never auto-delete
34- Consider EXIF date — oldest is likely the original, newer copies are backups
35
36## Search Patterns
37
38- **By content**: Search sidecar descriptions with simple text match first, vision re-analysis if no hits
39- **By date**: Parse EXIF DateTimeOriginal, fall back to file mtime
40- **By location**: Reverse geocode GPS once, store city/country in sidecar for text search
41- **By person**: If user identifies someone once ("that's Maria"), tag all similar faces in index
42
43## EXIF Handling
44
45- Read: `exiftool -json photo.jpg` — returns all metadata as JSON
46- Write date: `exiftool -DateTimeOriginal="2024:03:15 14:30:00" photo.jpg`
47- Strip GPS before sharing: `exiftool -gps:all= photo.jpg` (operates on copy, not original)
48- Batch read: `exiftool -json -r /photos/` — recursive, outputs array
49
50## File Organization
51
52- Propose structure, don't impose: `YYYY/MM/` or `YYYY/MM-DD/` based on user preference
53- Rename pattern: `YYYYMMDD_HHMMSS_originalname.ext` — preserves original name, adds sortable prefix
54- Handle timezone: EXIF dates are local time — ask user's timezone once, store in `.photo-index/config.json`
55- HEIC to JPEG: `sips -s format jpeg input.heic --out output.jpg` (macOS) or `heif-convert` (Linux)
56
57## NAS/Remote Libraries
58
59- For Synology/NAS: work with mounted paths, don't assume local speeds
60- Test connection before bulk operations: `ls /Volumes/photos | head -1`
61- For slow connections, build local index cache that syncs periodically
62- Respect `@eaDir` (Synology thumbnails) and `.DS_Store` — skip in indexing