Menu
Public repository / 2d36cd6c72fc6a63a7edb87bb54a4020e50f2f8a
AkurAI-Drive / client/README.md
Latest change feb7ac86b5e60d55b429eacb7146cf0dc32c6628 - Add native Linux sync client (akurai-drive-sync) by olibuijr
# akurai-drive-sync A native Linux sync client for [AkurAI Drive](https://akurai-drive.olibuijr.com) — a Dropbox/Nextcloud-style desktop client that keeps a local folder in sync with your AkurAI Drive S3 storage. It talks **only** to the AkurAI Drive backend and to S3 via the **presigned URLs** the backend hands out. No AWS credentials ever touch this client, and no secrets are stored in code. ## Install ```bash ./install.sh ``` This builds the release binary, installs it to `~/.local/bin/akurai-drive-sync`, and installs the `.desktop` entry plus a `systemd --user` service. ## Usage ```bash akurai-drive-sync login # browser login → saves a device token akurai-drive-sync buckets # list your buckets akurai-drive-sync init ~/AkurAIDrive --bucket B # configure folder + bucket, initial sync akurai-drive-sync sync # one bidirectional sync akurai-drive-sync daemon # watch + poll, sync continuously akurai-drive-sync status # show config + last-sync summary ``` Run the daemon as a user service: ```bash systemctl --user enable --now akurai-drive-sync.service ``` ### Backend selection The backend defaults to `https://akurai-drive.olibuijr.com`. Override it with: ```bash export AKURAI_DRIVE_API=https://my-drive.example.com ``` (`$AKURAI_DRIVE_API` overrides the saved config, which overrides the default.) ## How sync works Each `sync` reconciles **three snapshots** of every key: 1. **state** — what we recorded at the last successful sync (`state.sqlite`: per-key SHA-256 + remote ETag + size + mtime). 2. **remote** — the current bucket listing (`GET /api/files`). 3. **local** — the current disk contents (walked; SHA-256 reused from state when size + mtime are unchanged, so unchanged files are not re-hashed). A pure decision engine (`src/engine.rs`, fully unit-tested) maps the three-way presence/identity of each key to one action: | state | remote | local | local≠ | remote≠ | action | |-------|--------|-------|--------|---------|--------| | – | – | yes | | | **upload** (new local) | | – | yes | – | | | **download** (new remote) | | – | yes | yes | | | **adopt** if same size, else **conflict** | | yes | yes | yes | no | no | nothing (in sync) | | yes | yes | yes | yes | no | **upload** | | yes | yes | yes | no | yes | **download** | | yes | yes | yes | yes | yes | **conflict** | | yes | yes | – | – | no | **delete remote** (local deleted) | | yes | yes | – | – | yes | **download** (remote won; resurrect local) | | yes | – | yes | no | – | **delete local** (remote deleted) | | yes | – | yes | yes | – | **upload** (local won; resurrect remote) | | yes | – | – | | | drop stale state row | **Conflict resolution (keep both):** the local copy is moved aside to `<name> (conflict <short-id>)<ext>` and uploaded; the remote version is then downloaded to the original name. Nothing is lost, and both copies propagate to every device. Conflicts are always logged. Downloads are written to a temp sibling and `rename`d into place (atomic). Subfolders are preserved as S3 key prefixes. The state DB and temp files live under `~/.config/akurai-drive/`, outside the sync folder, so they are never synced. ## Files & config - `~/.config/akurai-drive/config.toml` — api, token, folder, bucket (mode `600`). - `~/.config/akurai-drive/state.sqlite` — per-key sync state + last-sync summary. (Honors `$XDG_CONFIG_HOME`, falling back to `~/.config`.) ## Develop ```bash cargo fmt cargo clippy --all-targets -- -D warnings cargo test # decision-engine + conflict-naming + login-parsing tests cargo build --release ```