From 57003e2c69a857927f0502ba837ece5498821034 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 16 Sep 2026 09:37:22 +0000 Subject: [PATCH 1/3] docs(aw-sync): document the working sync path and drop stale limitations Bare `aw-sync` / `aw-sync daemon` still no-ops on the 3-level layout (ActivityWatch/aw-server-rust#682); lead with `aw-sync sync` instead. Android is supported via the official app; default is all buckets. Fixes #690 Git-Session-Id: 18872a44-370f-5bf9-845d-0a9c162f660f --- aw-sync/README.md | 55 +++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/aw-sync/README.md b/aw-sync/README.md index 69cebfc5..b430ebf5 100644 --- a/aw-sync/README.md +++ b/aw-sync/README.md @@ -5,6 +5,8 @@ Synchronization for ActivityWatch. Works by syncing local buckets with a special folder, which in turn should be synchronized by rsync/Syncthing/Dropbox/GDrive/etc. +Android is supported: the official app drives this same crate over JNI. + The latest beta versions of ActivityWatch ship with the `aw-sync` binary, but it's not enabled by default. You can start it from aw-qt or the command line, but due to the early state of development might not have the best UX. Please report issues and submit PRs! Was originally prototyped as a PR to aw-server: https://github.com/ActivityWatch/aw-server/pull/50 @@ -12,27 +14,27 @@ Was originally prototyped as a PR to aw-server: https://github.com/ActivityWatch ## Usage -This will start a daemon which pulls and pushes events with the sync directory (`~/ActivityWatchSync` by default) every 5 minutes: +The command that actually pulls and pushes today is a one-shot pass. Share the sync directory first (see below), then: ```sh -# Basic sync daemon (syncs all buckets every 5 minutes) -aw-sync - -# Same as above -aw-sync daemon +# Pull every 3-level peer and push this device, then exit +aw-sync sync -# Sync daemon with specific buckets only -aw-sync daemon --buckets "aw-watcher-window,aw-watcher-afk" --start-date "2024-01-01" +# Doctor: why is pull empty / which peers exist in the folder? +aw-sync status -# Sync daemon in push-only or pull-only mode -aw-sync daemon --mode push -aw-sync daemon --mode pull +# One-shot with filters or a single direction +aw-sync sync --buckets "aw-watcher-window,aw-watcher-afk" --start-date "2024-01-01" +aw-sync sync --mode push +aw-sync sync --mode pull +``` -# Sync all buckets once and exit -aw-sync sync --start-date "2024-01-01" +`aw-sync` / `aw-sync daemon` currently **does not pull** from the 3-level `{hostname}/{device_id}/` layout that Android and `aw-sync sync` write. The daemon stages `{device_id}/test.db` at the sync-folder root and only walks two directory levels, so those peers are invisible ([#682](https://github.com/ActivityWatch/aw-server-rust/issues/682)). Until that switch lands, use `aw-sync sync` (or a systemd/cron timer around it) — not the daemon. -# Doctor: why is pull empty / which peers exist in the folder? -aw-sync status +```sh +# Daemon — currently broken for mixed / Android layouts (see above) +aw-sync +aw-sync daemon ``` For more options, see `aw-sync --help`. Some notable options: @@ -47,18 +49,26 @@ For more options, see `aw-sync --help`. Some notable options: ### Setting up sync -Once you have aw-sync running, you need to set up syncing with the sync directory using your preferred syncing tool. +Share the sync directory with Syncthing, Dropbox, Drive, or rsync **before** running aw-sync. aw-sync only reads and writes files in that folder; it does not transport them between devices. + +Default directory: `~/ActivityWatchSync` (`--sync-dir` or `AW_SYNC_DIR`). + +Working paths (`aw-sync sync`, Android) write: + +```txt +~/ActivityWatchSync/{hostname}/{device_id}/test.db +``` -The default sync directory is `~/ActivityWatchSync`, but you can change it using the `--sync-dir` option or by setting the `AW_SYNC_DIR` environment variable. +The default daemon still writes `~/ActivityWatchSync/{device_id}/test.db` (two levels). Other devices cannot see that file. ### Running from source If you want to run it from source, in the root of the repository run: ```sh -cargo run --bin aw-sync +cargo run --bin aw-sync -- sync ``` -For more options, see `cargo run --bin aw-sync -- --help`. +For more options, see `cargo run --bin aw-sync -- --help`. Bare `cargo run --bin aw-sync` starts the daemon, which currently does not pull (see Usage). ## FAQ @@ -74,10 +84,9 @@ We also avoid having to implement complex features such as conflict resolution, ### What are the limitations? -- It only syncs afk and window buckets by default (since bucket IDs need to be unique) - - It will work a lot better once proper `hostname -> device ID` migration is complete. -- It doesn't sync settings -- It doesn't support Android, yet. +- The default `aw-sync` / `aw-sync daemon` command does not pull from the 3-level layout (see Usage). `aw-sync sync` and the Android app do. +- By default all buckets are synced. `--buckets` is opt-in filtering, not a window/afk-only default. +- It doesn't sync settings. - It mirrors events to all devices, - If you have a lot of devices you'll get a lot of duplicates, taking up a lot of space and potentially impacting performance. - It doesn't support modifying/deleting events, yet. From 2448184b4fca35380b8e4e21a7f716dec8f2e5e2 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 16 Sep 2026 09:48:46 +0000 Subject: [PATCH 2/3] docs(aw-sync): precise who cannot see daemon-layout files A peer running the same bare daemon can see `{device_id}/test.db`. `aw-sync sync` and the Android app cannot. Git-Session-Id: 327ea5e1-5f57-58fa-8e6a-9a5e8479bd92 --- aw-sync/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aw-sync/README.md b/aw-sync/README.md index b430ebf5..53774890 100644 --- a/aw-sync/README.md +++ b/aw-sync/README.md @@ -59,7 +59,7 @@ Working paths (`aw-sync sync`, Android) write: ~/ActivityWatchSync/{hostname}/{device_id}/test.db ``` -The default daemon still writes `~/ActivityWatchSync/{device_id}/test.db` (two levels). Other devices cannot see that file. +The default daemon still writes `~/ActivityWatchSync/{device_id}/test.db` (two levels). `aw-sync sync` and the Android app cannot see that file. ### Running from source From 7e0e58eb096f7e1bed25001ac3e4968199682873 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 16 Sep 2026 09:54:40 +0000 Subject: [PATCH 3/3] docs(aw-sync): do not present --mode/--buckets as the 3-level path Those flags route aw-sync sync through sync_run, which uses the two-level {device_id}/test.db layout. Only bare aw-sync sync walks and writes hostname/device_id. Git-Session-Id: 327ea5e1-5f57-58fa-8e6a-9a5e8479bd92 --- aw-sync/README.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/aw-sync/README.md b/aw-sync/README.md index 53774890..3f146191 100644 --- a/aw-sync/README.md +++ b/aw-sync/README.md @@ -22,11 +22,6 @@ aw-sync sync # Doctor: why is pull empty / which peers exist in the folder? aw-sync status - -# One-shot with filters or a single direction -aw-sync sync --buckets "aw-watcher-window,aw-watcher-afk" --start-date "2024-01-01" -aw-sync sync --mode push -aw-sync sync --mode pull ``` `aw-sync` / `aw-sync daemon` currently **does not pull** from the 3-level `{hostname}/{device_id}/` layout that Android and `aw-sync sync` write. The daemon stages `{device_id}/test.db` at the sync-folder root and only walks two directory levels, so those peers are invisible ([#682](https://github.com/ActivityWatch/aw-server-rust/issues/682)). Until that switch lands, use `aw-sync sync` (or a systemd/cron timer around it) — not the daemon. @@ -45,7 +40,7 @@ For more options, see `aw-sync --help`. Some notable options: - `--start-date`: Only sync events after this date (YYYY-MM-DD) - `--sync-db`: Specify a specific database file in the sync directory - `--mode`: Choose sync mode: "push", "pull", or "both" (default: "both") - - For `aw-sync sync`, passing `--mode` (with no other options) is enough to opt into the per-bucket sync path where it's respected; without it, or any of `--buckets`/`--start-date`/`--sync-db`, `aw-sync sync` falls back to the legacy host-based mode, which always does both a pull and a push + - On `aw-sync sync`, `--mode` / `--buckets` / `--start-date` / `--sync-db` switch to `sync_run`, which uses the two-level `{device_id}/test.db` layout (same as the daemon). Those flags will not see Android or bare-`aw-sync sync` peers. Bare `aw-sync sync` (no extra flags) is the 3-level path and always does both a pull and a push. ### Setting up sync @@ -53,7 +48,7 @@ Share the sync directory with Syncthing, Dropbox, Drive, or rsync **before** run Default directory: `~/ActivityWatchSync` (`--sync-dir` or `AW_SYNC_DIR`). -Working paths (`aw-sync sync`, Android) write: +Working paths (bare `aw-sync sync`, Android) write: ```txt ~/ActivityWatchSync/{hostname}/{device_id}/test.db @@ -84,7 +79,7 @@ We also avoid having to implement complex features such as conflict resolution, ### What are the limitations? -- The default `aw-sync` / `aw-sync daemon` command does not pull from the 3-level layout (see Usage). `aw-sync sync` and the Android app do. +- The default `aw-sync` / `aw-sync daemon` command does not pull from the 3-level layout (see Usage). Bare `aw-sync sync` and the Android app do. `aw-sync sync --mode`/`--buckets`/`--start-date` use the two-level path. - By default all buckets are synced. `--buckets` is opt-in filtering, not a window/afk-only default. - It doesn't sync settings. - It mirrors events to all devices,