← ClaudeAtlas

immich-sdcard-sync-prunelisted

This skill should be used when building or debugging a macOS launchd automation that uploads a camera SD card's contents to Immich on insert (via @immich/cli), or when building a workflow to prune Immich assets that were deleted from their source card/folder after import. Covers the Immich CLI's non-obvious API key permission requirements (album.create vs albumAsset.create, the "Found 0 new files" scoped-key bug), launchd's StartOnMount trigger and its missing-Homebrew-PATH gotcha, parsing `immich upload -j` JSON output, the Immich bulk-delete (trash vs permanent) endpoint, and — critically — why a delete/prune workflow across multiple source cards feeding one album must scope its diff by a per-source manifest rather than diffing the whole album, or a second card mounted alone will make every surviving photo from the first card look deletable. Trigger phrases include "sd card to immich", "immich cli upload", "@immich/cli permissions", "albumAsset.create", "Found 0 new files and 0 duplicates", "launchd StartOn
jackson2w/claude-code-skills · ★ 1 · AI & Automation · score 64
Install: claude install-skill jackson2w/claude-code-skills
# Immich SD card auto-sync + safe prune Pattern for automatically uploading a camera's SD card to Immich when it's inserted on a Mac, plus a companion tool to safely prune Immich assets after the user deletes their local originals. Built for a Canon SD card reader on macOS; the mechanics generalize to any camera/reader that mounts as a normal volume with a `DCIM` folder. ## Architecture 1. **`immich upload` via `@immich/cli`** (`npm install -g @immich/cli`) — not `immich-go`, not the deprecated Docker-based CLI. Auth via `immich login-key <server-url> <api-key>`, which writes `~/.config/immich/auth.yml`. That file is created world-readable by the CLI — [immich#6911](https://github.com/immich-app/immich/issues/6911) — `chmod 600` it immediately. 2. **A macOS `launchd` LaunchAgent with `StartOnMount`** fires the sync script on *any* volume mount. The script itself filters for volumes with a top-level `DCIM` folder rather than matching a specific volume name/label — camera-formatted cards often mount with a generic name like `Untitled`, and the name isn't stable across reformats anyway. 3. **Dedup two different ways for two different purposes:** - A `synced.log` state file keyed by **Volume UUID** (`diskutil info "$vol" | grep "Volume UUID"`) stops the same already-fully-synced card from re-triggering a full re-upload on every incidental `/Volumes` change while it sits mounted. - Immich's own upload does checksum-based dedup server-side — re-