An open-source Syncthing client for iPhone and Android, powered by the Syncthing daemon via gomobile.
Syncthing's official Android client was archived in December 2024.
No single client ran on both phones from one codebase, so I built
this. The daemon runs in-process via
gomobile, with a React
Native UI scaffolded from
react-native-go.
| Status | Folders | Devices | Settings |
|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
- In-process daemon. The Go daemon lives inside the app via
gomobile. No subprocess, no IPC, no service-restart juggling. - Real-time UI. Long-polling on
/rest/eventskeeps folder state, config, and incoming offers fresh in about a second. - QR pairing, both ways. Show your device QR or scan a peer's. The 56-character device ID never has to be typed.
- Auto-accept folders. Trust a peer and any folder they share gets added automatically. Untrusted offers show up as accept or ignore cards.
- Onboarding tour. First-launch coach marks walk new users through adding a device, a folder, and reading sync state.
- Search. Find any file across folders, preview it inline (images, text, markdown, PDF).
- SAF on Android. Sync into folders outside the app sandbox (Documents, SD card, USB drive).
- Auto-start on boot. Android picks up where it left off after a reboot.
- External automation. Start, stop, or rescan from Tasker, MacroDroid, or any
am broadcastcaller. Off by default, see docs/AUTOMATION.md. - Port fallback. If
8384is taken, SyncUp picks the next free port. - Reproducible Android builds. F-Droid metadata in
fastlane/, armv7a + arm64 APKs.
- Folder browser with thumbnails, file preview, and per-folder statistics.
- Versioning and ignore editors. Edit
.stignoreand versioning policy from the folder detail screen. - Conflict resolver. Pick a version, or use the markdown-aware 3-way merge for
.mdconflicts. - Transfers view and recent changes for what just moved.
- Quick capture. Open the camera, snap, and drop the photo straight into a synced folder.
- Photo backup. Background upload of new photos and videos into a chosen folder, with flat, by-date, or by-year/month layouts.
- Obsidian vault preset. Picks the right rescan interval, watcher setting, and ignore patterns so
workspace.jsonstops causing conflicts. Apply retroactively when.obsidian/is detected. Setup guide: docs/OBSIDIAN.md.
Release process lives in docs/RELEASE.md. Currently at v1.1.13.
The React Native UI talks to the embedded daemon over its REST API at
127.0.0.1:8384. A TurboModule implemented in Swift and Kotlin
handles daemon lifecycle, preferences, and sandbox filesystem helpers.
The Go side (backend/wrapper.go) wraps
github.com/syncthing/syncthing/lib/syncthing and is bound through
gomobile.
Folders, devices, and events are not re-exported as gomobile types.
That path runs into the marshaller's constraints quickly. Everything
outside lifecycle calls goes through fetch('/rest/...') instead,
which has been simpler to work with.
Every make target runs inside a Nix shell automatically, so you don't
need to install Go, Node, or JDK yourself. Prerequisites:
- Nix (with flakes enabled)
- Xcode 16+ (iOS, macOS only)
- Android SDK with NDK r27 (install via Android Studio)
make setup # install Go toolchain + Node deps
make ios # Go backend + iOS simulator build
make android # Go backend + debug-signed APK
make sim-ios # build + install + launch on simulator
make sim-android # build + install + launch on emulator
make test # Go + Android + iOS + JS tests
make clean
A cold build takes about six minutes for iOS and three for Android on
an M2. Subsequent builds are faster once gomobile is cached.
For iterative development with hot reload:
make dev-ios # build Go backend + start Expo dev client (iOS)
make dev-android # build Go backend + start Expo dev client (Android)
JS/TS changes reload instantly. Go changes require restarting the dev target.
cd mobile-app
yarn lint
yarn typecheck
CI runs lint, typecheck, and go vet -tags noassets ./....
Android keeps the daemon running in the background while the system allows it. Settings exposes wifi-only and charging-only toggles that drive the run-condition monitor. The app also restarts on boot.
iOS is more constrained. Apple does not permit continuous background
execution for apps outside the VoIP and audio categories, and this
app does not qualify. It registers two BGTaskScheduler jobs and gets
roughly one to two hours of opportunistic sync per day, sometimes with
multi-hour gaps between runs.
If you want a node that is genuinely always online, run Syncthing on a desktop or server that stays up 24/7. Your phone remains opportunistic on its own, but it reconciles against a complete copy whenever it wakes up, instead of depending on other peers being online at the same time.
Android folders live under app-scoped external storage at
/storage/emulated/0/Android/data/com.siddarthkay.syncup/... by
default, or anywhere SAF can reach. App-scoped folders are deleted
when the app is uninstalled; SAF folders are not.
See CONTRIBUTING.md.
If this is useful to you, a GitHub star is the signal I watch to decide what's worth continuing. Sponsorships cover the Apple developer account and testing devices, and they let me spend time on the harder iOS background work instead of billable client work.
MPL-2.0. See LICENSE.




