A native desktop GUI for kei, the iCloud photo sync CLI tool written in Rust.
This app does not modify kei's source. It wraps the existing binary: spawning it as a child process, streaming its output, reading and writing its TOML config, and querying its SQLite state database.
The kei binary is bundled inside the app β end users do not need to install it separately.
| Platform | Status |
|---|---|
| macOS 13+ | Primary target; native overlay title bar |
| Windows 10+ | Supported; native window decorations |
| Linux | Supported; native window decorations |
The macOS build is not notarized, so Gatekeeper will block it on first launch. To open it anyway:
Option 1 β System Settings
- Try to open the app normally β it will be blocked
- Go to System Settings β Privacy & Security
- Scroll down and click Open Anyway next to the blocked app
Option 2 β Terminal (removes the quarantine flag permanently)
xattr -cr "/Applications/Kei PhotoSync.app"- Rust + Cargo (via rustup)
- Node.js 18+
- On macOS: Xcode Command Line Tools (
xcode-select --install) - On Linux:
libwebkit2gtk,libgtk-3,libayatana-appindicator3(see Tauri Linux dependencies)
kei itself is downloaded automatically by pnpm run prepare-sidecar β no separate installation needed.
# Install JS dependencies
pnpm install
# Download the latest kei release from GitHub into src-tauri/binaries/
pnpm run prepare-sidecar
# Launch in development mode
pnpm run devThe first build takes a few minutes (Tauri compiles the WebView bindings). Subsequent runs are fast.
prepare-sidecar is a no-op if the binary is already present. The downloaded version is pinned in src-tauri/binaries/.kei-version so cross-platform builds always use the same release.
To update the bundled kei to the latest release:
node scripts/prepare-sidecar.js --force
git add src-tauri/binaries/.kei-version
git commit -m "update kei sidecar to vX.Y.Z"pnpm run prepare-sidecar # ensure sidecar is up to date
pnpm run buildOutput locations:
- macOS:
src-tauri/target/release/bundle/macos/Kei PhotoSync.app - Windows:
src-tauri/target/release/bundle/msi/ornsis/ - Linux:
src-tauri/target/release/bundle/deb/orappimage/
Kei PhotoSync/
βββ index.html # App shell β sidebar + 4 views + modals
βββ scripts/
β βββ prepare-sidecar.js # Downloads kei binary into src-tauri/binaries/
β βββ build-windows.sh # Cross-compiles Windows .exe on macOS (cargo-xwin)
βββ src/
β βββ app.js # Frontend: Tauri invoke/listen calls, view logic
β βββ log-parsers.js # Extensible log parser registry
β βββ styles.css # Native-style theming with full dark-mode support
βββ src-tauri/
βββ binaries/
β βββ .kei-version # Pinned kei release tag (committed)
βββ Cargo.toml
βββ tauri.conf.json
βββ capabilities/
β βββ default.json # Tauri v2 permission grants
βββ icons/
β βββ icon.png # Replace with your own 512Γ512 RGBA PNG
βββ src/
βββ main.rs # All backend commands
| View | What it shows |
|---|---|
| Dashboard | Asset counts (downloaded / pending / failed / total) and last sync run summary, read from kei's SQLite DB |
| Sync | Start/Stop button, live streaming log with structured formatting, indeterminate progress bar, automatic 2FA prompt dialog |
| History | Table of the last 100 sync runs with duration and status |
| Settings | Form that reads and writes the kei config file |
All backend logic lives in src-tauri/src/main.rs.
| Command | Description |
|---|---|
check_kei |
Returns the resolved kei binary path, or an error if not found |
get_config |
Reads kei's config file; returns defaults if absent |
save_config |
Serialises the config struct back to TOML |
get_app_settings |
Reads UI-only settings (folder structure, system kei toggle, etc.) |
save_app_settings |
Writes UI-only settings |
get_kei_versions |
Returns paths and version strings for bundled and system kei |
get_status |
Queries the kei SQLite DB for asset counts and last sync_run |
get_history |
Returns the last 100 rows from the sync_runs table |
start_sync |
Spawns kei sync, streams output as batched Tauri events |
stop_sync |
Sends SIGKILL to the running kei process |
submit_password |
Writes a password to kei's stdin |
request_2fa_code |
Runs kei login get-code to push a 2FA prompt to trusted devices |
submit_2fa |
Runs kei login submit-code <CODE> as a separate process |
clear_kei_session |
Deletes kei session/cookie files to force re-authentication |
list_kei_albums |
Runs kei list albums and returns the album names |
| Platform | Config file | Database |
|---|---|---|
| macOS / Linux | ~/.config/kei/config.toml |
~/.config/kei/cookies/<user>.db |
| Windows | %USERPROFILE%\.config\kei\config.toml |
%USERPROFILE%\.config\kei\cookies\<user>.db |
[auth]
username = "you@icloud.com"
domain = "com" # or "cn" for China
[download]
directory = "~/Photos/iCloud"
threads_num = 10
folder_structure = "%Y/%m/%d" # unfiled photos
folder_structure_albums = "{album}/%Y/%m" # user albums
folder_structure_smart_folders = "{smart-folder}" # Apple smart folders
set_exif_datetime = false
[download.retry]
max_download_attempts = 10
[filters]
skip_videos = false
libraries = ["primary"]
albums = ["Vacation", "!Screenshots"]
smart_folders = ["Favorites"]
unfiled = true
recent = 0 # 0 = all
[watch]
interval = 3600 # seconds; omit to disable watch mode
log_level = "info"Passwords are never stored in the config file. kei stores credentials in the system keychain. Set up credentials once with kei config setup or kei password set.
# Generates all required sizes from a single source image
npx tauri icon path/to/your-icon.pngkei not found β Run pnpm run prepare-sidecar. If kei itself is missing, install it with cargo install kei first.
No data in Dashboard β kei creates its SQLite database only after the first successful sync. Run kei sync once from the terminal to initialise it, or use the Sync view.
Advanced Data Protection (ADP) β kei cannot sync if ADP is enabled on your iCloud account. Disable it in System Settings β Apple ID β iCloud β Advanced Data Protection.
2FA loop β If the 2FA dialog keeps appearing, your kei session may have expired. Run kei verify in the terminal to re-authenticate.
-- Icon from IO Images: https://pixabay.com/de/vectors/wolke-cloud-herunterladen-speichern-2044822/