AkurAI Build
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
```