Bridge Android camera media into the macOS / iCloud Photos library via an always-on Mac.
Project description
icsync
Sync Android camera photos & videos into your iCloud Photo Library — as full-resolution originals, in the real Photos app, not some third-party gallery.
There is no public Apple API to write into the iCloud Photo Library. icsync
uses the only robust path: an always-on Mac signed into iCloud, importing media
via osxphotos and letting Photos sync
it up.
Android DCIM/Camera ──Syncthing send-only──▶ Mac inbox
Mac inbox ──icsync (launchd)──▶ osxphotos import ──▶ Photos.app ──▶ iCloud Photos
icsync is the Mac-side bridge: a small CLI that watches an inbox folder,
imports stable media into Photos, archives the originals, and installs itself as
a launchd agent. The Android→Mac transport is off-the-shelf
(Syncthing — no port-forwarding, no exposing the Mac).
Install
pipx install icsync # pulls in osxphotos automatically
icsync install # creates dirs + loads the LaunchAgent (runs every 60s)
icsync doctor # check prerequisites
From source:
git clone https://github.com/akurach/icsync && cd icsync
pipx install .
Prerequisites
- Photos.app signed into your Apple ID, iCloud Photos ON (Photos → Settings → iCloud).
- Syncthing on the Mac with a Receive Only folder at the icsync inbox
(
~/Documents/icsync/data/inboxby default), paired to the Android device's Send Only folder onDCIM/Camera. - On first import macOS will ask to grant Automation → Photos;
osxphotosmay also need Full Disk Access (System Settings → Privacy & Security).
Commands
| Command | Does |
|---|---|
icsync install |
Create data dirs, write + load the LaunchAgent. |
icsync uninstall |
Unload + remove the LaunchAgent. |
icsync start / stop |
Load / unload the agent. |
icsync status |
Show install state, pending media, paths. |
icsync run |
Run one import cycle (what launchd calls). |
icsync watch |
Loop cycles in the foreground (no launchd). |
icsync doctor |
Check osxphotos, dirs, agent, reminders. |
How it behaves
- Idempotent —
osxphotos import --skip-dups; re-delivered files don't duplicate. - Safe — imported originals are moved to
data/archive/<date>/, not deleted; a retention prune removes them afterICSYNC_RETENTION_DAYS(default 7). Set it high to keep originals indefinitely. - One-way — Syncthing send-only → receive-only; nothing flows back to the phone.
- Mac off = delay, not loss — Syncthing on Android queues and retries; icsync catches up when the Mac returns.
- Partial-write safe — only files older than
ICSYNC_STABLE_SECONDS(default 20) are imported, so half-synced files are skipped until complete.
Configuration (env vars)
| Var | Default | Meaning |
|---|---|---|
ICSYNC_ROOT |
~/Documents/icsync/data |
Base data dir. |
ICSYNC_INBOX |
…/inbox |
Watched folder (Syncthing target). |
ICSYNC_ARCHIVE |
…/archive |
Where originals land after import. |
ICSYNC_STABLE_SECONDS |
20 |
Min file age before import. |
ICSYNC_RETENTION_DAYS |
7 |
Archive purge age. |
ICSYNC_OSXPHOTOS |
autodetect | Explicit path to the osxphotos binary. |
To override for the agent, add them to the EnvironmentVariables dict in
~/Library/LaunchAgents/com.icsync.import.plist and icsync start.
Limitations
- Requires an always-on Mac as the bridge — no Apple device means no reliable path.
- Android "motion photos" import as stills (no Apple Live Photo pairing).
- Not affiliated with Apple; uses the public Photos import surface only.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file icsync-0.1.0.tar.gz.
File metadata
- Download URL: icsync-0.1.0.tar.gz
- Upload date:
- Size: 9.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ed457e6998ebc3b2573fefbf98689db69b46336f12c0a368af4140c26aca69a
|
|
| MD5 |
8945254137b6ee8301e0248eadbf23b1
|
|
| BLAKE2b-256 |
997fb8bab60beedd69c1cb7e93ef9481d2c816d0d27844c5d13d607e204c48c3
|
Provenance
The following attestation bundles were made for icsync-0.1.0.tar.gz:
Publisher:
release.yml on akurach/icsync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
icsync-0.1.0.tar.gz -
Subject digest:
5ed457e6998ebc3b2573fefbf98689db69b46336f12c0a368af4140c26aca69a - Sigstore transparency entry: 1923170533
- Sigstore integration time:
-
Permalink:
akurach/icsync@930db4bd85d1a6f0b482f86db0242ce16b23d622 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/akurach
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@930db4bd85d1a6f0b482f86db0242ce16b23d622 -
Trigger Event:
push
-
Statement type:
File details
Details for the file icsync-0.1.0-py3-none-any.whl.
File metadata
- Download URL: icsync-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0643aaec3e4d61f868dfb0861b129e0ea8db0346d2a6908ba8cf10948d47d061
|
|
| MD5 |
7cecdba6f5506a6bc45d32056dbc1f6b
|
|
| BLAKE2b-256 |
94a02379760829f480121a38f91ee728c6bf070ec0037dd9d0f1c7eed91fd889
|
Provenance
The following attestation bundles were made for icsync-0.1.0-py3-none-any.whl:
Publisher:
release.yml on akurach/icsync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
icsync-0.1.0-py3-none-any.whl -
Subject digest:
0643aaec3e4d61f868dfb0861b129e0ea8db0346d2a6908ba8cf10948d47d061 - Sigstore transparency entry: 1923170691
- Sigstore integration time:
-
Permalink:
akurach/icsync@930db4bd85d1a6f0b482f86db0242ce16b23d622 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/akurach
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@930db4bd85d1a6f0b482f86db0242ce16b23d622 -
Trigger Event:
push
-
Statement type: