Pull photos from an SD or CF memory card into organized folders, import into Lightroom Classic, and clean up after cloud sync. Use this skill whenever the user mentions importing photos, ingesting images from a camera card, pulling photos off an SD card or CF card, organizing camera photos by date, importing into Lightroom, or managing a photo workflow from card to cloud. Also trigger when the user says "photo ingest", "pull my photos", "import from card", "camera card", "ingest", or references memory cards, photo dates, or Lightroom import.
A repeatable workflow for pulling photos off camera memory cards, filtering by EXIF capture date, organizing into named subfolders, importing into Lightroom Classic, and cleaning up after cloud sync.
When invoked, collect these four pieces of information (ask for anything not provided):
/Volumes/The root destination is always: /Users/mbowdish/photos_temporary
Camera cards mount under /Volumes/ on macOS. Run the detect command:
python3 <skill-path>/scripts/photo_ingest.py detect
This finds volumes with a DCIM directory (the universal camera folder standard). Common
Canon volume names include "EOS_DIGITAL" and "Untitled". The user shoots on a Canon EOS 5D
Mark IV which writes to both CF and SD simultaneously.
The script scans all subfolders inside DCIM (Canon creates numbered folders like 100EOS5D, 101EOS5D, etc. as it fills up — these are just auto-numbering and should all be scanned).
First create the destination:
mkdir -p "/Users/mbowdish/photos_temporary/<subfolder-name>"
Then run the copy. Always include --file-type based on the user's choice (jpeg, raw, or both):
python3 <skill-path>/scripts/photo_ingest.py copy \
--source "/Volumes/<card-name>/DCIM" \
--dest "/Users/mbowdish/photos_temporary/<subfolder-name>" \
--date "2026-03-31" \
--file-type jpeg
For a date range, add --date-end:
python3 <skill-path>/scripts/photo_ingest.py copy \
--source "/Volumes/<card-name>/DCIM" \
--dest "/Users/mbowdish/photos_temporary/<subfolder-name>" \
--date "2026-03-15" \
--date-end "2026-03-17" \
--file-type raw
For all photos (no date filter):
python3 <skill-path>/scripts/photo_ingest.py copy \
--source "/Volumes/<card-name>/DCIM" \
--dest "/Users/mbowdish/photos_temporary/<subfolder-name>" \
--all \
--file-type both
The script handles JPG and RAW files (CR2, CR3, NEF, ARW, RAF, DNG, ORF, RW2, TIFF). It reads EXIF DateTimeOriginal to determine capture date. It copies (not moves) — originals stay on the card until the user formats in-camera.
After the copy, report to the user:
The script reads EXIF dates using three methods in priority order:
For Canon 5D Mark IV CR2 files specifically, Pillow needs to check the EXIF sub-IFD
(exif.get_ifd(0x8769)) because DateTimeOriginal (tag 36867) lives there, not in the
root IFD.
Lightroom Classic needs to import the photos into its catalog, and each shoot should go into its own folder within Lightroom. The user has a consistent import preset they use every time.
Run the import helper script:
bash <skill-path>/scripts/lightroom_import.sh "/Users/mbowdish/photos_temporary/<subfolder-name>"
This script:
Cmd+Shift+I using AppleScriptOnce the Import dialog is open, tell the user:
"Lightroom's Import dialog should be open. Here's what to do:
- On the left panel, navigate to
/Users/mbowdish/photos_temporary/<subfolder-name>- Make sure your import preset is selected
- On the right panel under 'Destination', create or select a folder for this shoot (e.g.,
<subfolder-name>)- Click Import
Once the import finishes and your photos have synced to Adobe's cloud, come back and let me know."
The key point: each upload gets its own destination folder in Lightroom's catalog. The subfolder name from step 1 is a good default — suggest it to the user but let them override.
Stop and wait. Do not proceed to the next step until the user confirms that:
After Lightroom import is confirmed, ask:
"Do you also want to publish these photos to the baseball photo gallery website?"
photo-gallery-publish skill, pointing it at /Users/mbowdish/photos_temporary/<subfolder-name>. The local copies must stay until that workflow is complete.Do not delete local copies until both this step and cloud sync are confirmed done.
This requires two explicit confirmations:
Gate 1 — Ask: "Have your photos finished syncing to Adobe's cloud?"
Gate 2 — Ask: "Ready for me to delete the local copies from
/Users/mbowdish/photos_temporary/<subfolder-name>? This cannot be undone."
rm -rf "/Users/mbowdish/photos_temporary/<subfolder-name>"
After deletion, confirm what was removed. Remind user that originals are still on the memory card (format in-camera when ready).
IMG_1234_2.CR3)