config/claude/skills/photo-exif/SKILL.md
Backfill EXIF on Alp's film-scan JPEGs — camera, lens, sequenced DateTimeOriginal, and GPS — so they sort and identify correctly when imported into Photos.app. Use when the user wants to set/fix camera, lens, date, or location on a folder of images (typically under `~/Library/Mobile Documents/com~apple~CloudDocs/Pictures/To Import/`).
npx skillsauth add alexpopov/dots photo-exifInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Alp shoots film, sends rolls to a lab, and receives JPEGs scanned by a Noritsu Koki HS-1800. The scanner writes its own identity into EXIF (Make=NORITSU KOKI, Model=EZ Controller) and leaves DateTimeOriginal / CreateDate empty. Before these import into Photos.app cleanly, EXIF needs backfilling.
set-exif.sh wraps exiftool with three batched concerns:
cameras.jsonDateTimeOriginal plus N-second increments so Photos.app preserves frame orderExample:
~/dots/config/claude/skills/photo-exif/set-exif.sh \
--camera canon-7 --lens canon-50-1.8 \
--date "2025-07-06 12:00:00" --step 1 --tz "+02:00" \
--gps "47.2913799,8.5277585" \
/path/to/000071040001.jpg /path/to/000071040002.jpg ...
Always pass files in the order they should sort. For lab scans the filename order is already the frame order, so a shell glob works:
set-exif.sh ... "$DIR"/000071040{0001..0024}.jpg
Default to --no-backup. Alp doesn't want <file>_original files cluttering the scan dirs. Omit it only if there's specific reason to keep a backup for that run. To clean up backups left by an earlier run, move them to /tmp/ (don't delete outright — Alp prefers a recoverable step).
Use --dry-run to preview the exiftool commands before running.
locations.local.json)For locations that shouldn't be in the public repo (home, friends' places, etc.), use --location KEY instead of --gps. The script reads locations.local.json from the skill dir; that filename is gitignored (config/claude/skills/photo-exif/*.local.json).
Schema:
{
"locations": {
"home": { "description": "Home", "lat": "47.xxx", "lon": "8.xxx" }
}
}
When the user names a private location, add it to locations.local.json (which already exists if they've used the feature before). Do not put private coords in cameras.json, the SKILL.md, or anywhere else under version control — that includes commit messages and PR descriptions.
cameras.json)Two flat dictionaries: cameras and lenses, keyed by short slugs. Each entry has a human description and an exif map that becomes -Tag=Value args.
When the user mentions a camera or lens that isn't in cameras.json yet, add it:
Make, Model.LensMake, LensModel, FocalLength, FocalLengthIn35mmFormat, MaxApertureValue (lens's widest aperture — not per-shot FNumber, which we don't know for film).Confirm the slug and description with the user before saving the preset.
The user can give a location in any form — proceed without asking them to convert:
maps.app.goo.gl/..., google.com/maps/..., goo.gl/maps/...): follow the redirect and pull coords out of the resolved URL:
curl -sIL "<url>" | grep -i '^location:'
The resolved URL has both @LAT,LON,ZOOMz (map-view center) and !3dLAT!4dLON (the actual pin). Prefer !3d!4d — for pinned places those can differ from @ by 100m+. If only @ is present (a "dropped pin" with no place data), use that.47.38, 8.54): use directly with --gps.For private locations, save under a key in locations.local.json instead of passing --gps (see above).
exiftool <file>) — confirm what's missing.cameras.json and confirm slug.--dry-run first if anything's uncertain.exiftool -DateTimeOriginal -Model -LensModel -GPSPosition <file>).Lab/home TIF scans are 100+ MB each (16-bit, uncompressed). For Photos.app import they should be downscaled + compressed first so the iCloud Photos library doesn't bloat. The canonical workflow:
~/Library/Mobile Documents/com~apple~CloudDocs/Pictures/Imported/...).tif-to-heic.sh — defaults to 3840 long-edge max, q=80, output to a separate dir (typically ~/Desktop/Scans/... or similar).open -a Photos <dir>/*.heic).sips is fast (hardware HEIC encode on Apple Silicon) and preserves most EXIF — except Keywords and XMP Subject are silently dropped during TIF→HEIC. So film-stock tags vanish unless you re-copy them. tif-to-heic.sh does the sips encode then runs exiftool -tagsfromfile to put Keywords/Subject back.
~/dots/config/claude/skills/photo-exif/tif-to-heic.sh \
--out "$HOME/Desktop/Scans/Canon 7/Porta 1" \
"/Users/alp/Library/Mobile Documents/com~apple~CloudDocs/Pictures/Imported/Canon 7/Porta 1"/*.tif
Defaults: 3840 max long edge, quality 80, 8 parallel workers. For 34 frames expect ~50–60 seconds and ~50 MB output.
Quality reference (from earlier benchmarks on a 5034×3437, 108 MB TIF):
DateTimeOriginal is a wall-clock string with no zone. Photos.app uses the file's location to infer the zone, but setting OffsetTimeOriginal explicitly avoids surprises. Common values for Alp:
+02:00+01:00devops
Retroactively edit location, date, or timezone on photos that already live inside macOS Photos.app (and iCloud Photos) — including applying a GPX track. Use when the user wants to geotag, fix a wrong-TZ camera clock, shift timestamps, or apply GPS coordinates to photos that are NOT loose files but are inside Photos.app. Distinct from the `photo-exif` skill, which edits loose JPEG/RAW files before import.
tools
Use when the user says "open", "show me", "nvr", "open in editor", "open in nvr", "open in neovim", or wants to view a file in their editor rather than in the CLI. Also use proactively after creating or editing a file the user will want to review.
tools
Use this skill when working with the token-based Notion MCP servers (e.g. `mcp__notion-wife__API-*`) that wrap the raw Notion REST API — distinct from the OAuth `mcp__notion__*` server covered by notion-tricks. Covers native API JSON property shapes, the two-step page-then-content creation flow, and using `curl` with the `NOTION_TOKEN_*` env var to bypass MCP entirely for bulk/precise operations.
tools
Use this skill when adding, querying, or updating recipes in Cay's Notion (the `notion-wife` MCP). Covers the Recipes data source schema, tag conventions, the `recipes-helper.sh` script for fast tag/recipe operations via curl, and the rule that new tags must be confirmed with the user before creation.