-
-
Notifications
You must be signed in to change notification settings - Fork 5
Sync
Download photos from iCloud. This is the default command - running kei without a subcommand does the same thing as kei sync.
# These are equivalent
kei sync -u my@email.address -d /photos
kei -u my@email.address -d /photos
# Dry run to preview what would be downloaded
kei sync -u my@email.address -d /photos --dry-run
# Sync specific albums
kei sync -u my@email.address -d /photos -a "Favorites" -a "Travel"
# Watch mode - sync every hour
kei sync -u my@email.address -d /photos --watch-with-interval 3600Assets stream from iCloud's API directly into the download pipeline. Downloads start as soon as the first page of results arrives - no waiting for the full library count. On subsequent runs, a stored CloudKit syncToken detects changes in 1-2 API calls, skipping full enumeration entirely.
Files download concurrently (default: 10 threads), resume from partial .kei-tmp files via HTTP Range, and go through a two-phase cleanup pass that re-fetches expired CDN URLs for any failures.
See Download Pipeline, Retry & Resilience, and State Tracking for details.
Global flags (--username, --config, --data-dir, --domain, --log-level) apply to this command.
| Flag | Description |
|---|---|
-p, --password |
iCloud password |
--password-file |
Read password from a file |
--password-command |
Run a command to get the password |
--save-password |
Persist password to credential store after auth |
| Flag | Description |
|---|---|
-a, --album |
Album(s) to download (repeatable) |
--exclude-album |
Album(s) to exclude (repeatable) |
--library |
Library to sync (PrimarySync, all, or a specific name) |
--recent |
Download only N most recent photos |
--skip-videos |
Don't download videos |
--skip-photos |
Don't download photos |
--live-photo-mode |
Live photo handling: both, image-only, video-only, skip
|
--filename-exclude |
Exclude files by glob pattern (repeatable) |
--skip-created-before |
Skip assets older than a date or interval |
--skip-created-after |
Skip assets newer than a date or interval |
See Content Filtering for how these interact.
| Flag | Description |
|---|---|
-d, --download-dir |
Local download directory (required). Renamed from --directory in v0.12.0; old name still parses with a deprecation warning. |
--size |
Image size: original, medium, thumb, adjusted, alternative
|
--live-photo-size |
Live photo MOV size variant |
--force-size |
Skip assets that don't have the exact requested size |
--align-raw |
RAW/JPEG alignment: as-is, original, alternative
|
--folder-structure |
Date-based folder template (default: %Y/%m/%d) |
--file-match-policy |
File deduplication policy |
--live-photo-mov-filename-policy |
MOV filename style: suffix or original
|
--keep-unicode-in-filenames |
Preserve Unicode characters in filenames |
--set-exif-datetime |
Write EXIF date tags if missing |
--set-exif-rating |
Write EXIF Rating tag (0x4746) from iCloud favorite / rating |
--set-exif-gps |
Write EXIF GPS tags from iCloud location (only if missing) |
--set-exif-description |
Write EXIF ImageDescription from iCloud title / caption |
--embed-xmp |
Embed a full XMP packet into the downloaded media bytes |
--xmp-sidecar |
Write a .xmp sidecar next to each media file |
--threads |
Concurrent downloads (default: 10). Renamed from --threads-num in v0.12.0; old name still parses with a deprecation warning. |
--bandwidth-limit |
Cap total throughput (e.g. 10M, 500K, 2Mi) |
--no-progress-bar |
Disable progress bar |
--temp-suffix |
Temp file suffix (default: .kei-tmp) |
| Flag | Description |
|---|---|
--max-retries |
Retry attempts per download (default: 3, max: 100). The initial backoff delay is now derived from this value; the explicit --retry-delay flag is deprecated and removed in v0.20.0. |
--max-download-attempts |
Max total attempts per asset before skipping (default: 10) |
--retry-failed |
Re-sync only previously failed assets |
See Retry & Resilience for backoff behavior and error classification.
| Flag | Description |
|---|---|
--watch-with-interval |
Re-sync every N seconds (minimum: 60) |
--dry-run |
Preview without writing files |
--only-print-filenames |
Print download paths for scripting |
--no-incremental |
Force full library enumeration |
--notification-script |
Run a script on sync events |
--report-json |
Write a JSON summary after each sync cycle |
--http-port |
Port for the built-in /healthz + /metrics HTTP server (default 9090, watch mode only) |
--notify-systemd |
systemd sd_notify integration |
--pid-file |
Write PID file for service managers |
See Watch Mode for continuous sync details.