CLI reference

Setup & licensing

cdsync --version                # Show version + licensed email + license state
cdsync install                  # Interactive wizard: deps + config + systemd + tray
cdsync activate          # Activate license (browser or headless URL+code);
                                # auto-self-installs if run from outside ~/.cdsync/bin/

Daemon internals (called by systemd, also usable manually)

cdsync watcher                  # systemd ExecStart: inotify loop (daemon)
cdsync poll                     # systemd ExecStart: rclone bisync (timer)
cdsync poll --smart-sync  # Targeted single-file upload (internal)
cdsync poll --dir-event         # Full bisync for directory changes (internal)
cdsync poll --force-resync      # Manual database repair (internal)
cdsync poll --dedupe      # Remote dedupe: rename | newest (internal)
cdsync tray                     # Autostart: GTK3 tray applet (also implicit when
                                # launching cdsync-tray with no arguments)

Service control (mirrors systemctl --user + tray lifecycle)

CommandDaemonTray
cdsync stop systemctl --user stop cdsync-watcher.service cdsync-poll.timer (+ poll.service) SIGTERM → wait 3 s → SIGKILL if needed; PID file removed
cdsync start systemctl --user enable --now cdsync-watcher.service cdsync-poll.timer Launch ~/.cdsync/bin/cdsync-tray detached, PID file written
cdsync restart stop + start (preserves enable state) stop + start
cdsync status systemctl --user is-active cdsync-watcher.service Check PID file + pgrep fallback

Why stop/start instead of systemctl directly? Because the tray isn't a systemd unit. cdsync stop ensures both the daemon (via systemctl) and the tray (via PID file + pgrep) get the message — running systemctl --user stop cdsync-watcher.service alone would leave a zombie tray icon pointing at a service that's no longer running.

The tray PID file lives at ~/.cdsync/log/tray.pid. The tray also writes its own PID on startup (belt-and-suspenders), so even if the file is stale (e.g. process crashed and PID got recycled), the pgrep -f cdsync-tray fallback finds it.

Removal

CommandAction
cdsync uninstall Remove CDSync (services + binaries); prompts whether to also wipe ~/.cdsync/ (license, OAuth, config, logs)
cdsync uninstall --purge Skip the prompt — full purge of ~/.cdsync/. Destructive: license.lic + OAuth tokens are lost; re-activation requires a valid license.lic for this machine's fingerprint.

Tray applet

The tray icon (cdsync tray) runs in your session's systray:

IconMeaning
🟢 greenSync idle, all good
⚡ yellowSync in progress
🔴 redDisabled / error
🔒 lockLicense invalid — click Reactivate...

Menu actions

  • Activity → recent file events (create/update/delete/move)
  • Sync Now → immediate manual sync
  • Config → Set Interval → change poll frequency
  • Config → Force Resync → repair corrupted database
  • Config → Force Sync Newer → toggle conflict strategy
  • Config → Notifications → All / Errors only / Silent
  • Config → Deduplicate Remote → Rename / Keep Newest
  • Reactivate... → launches cdsync activate in a terminal (only appears when license is invalid)
  • Quit Tray → stops the applet only (daemon continues)

Configuration

File: ~/.cdsync/config/config.env (written by the install wizard; overridable for testing via the CDSYNC_HOME environment variable).

# Required (set by the install wizard from the rclone remote created by cdsync activate)
RCLONE_REMOTE="gdrive:"               # rclone remote name (with trailing colon)
LOCAL_SYNC_DIR="$HOME/gdrive"          # local directory to mirror
LOCK_FILE="/tmp/cdsync_default.lock"  # flock mutual-exclusion lock file

# Optional
CUSTOM_LOG_FILE=""                    # default: ~/.cdsync/log/cdsync.log
RCLONE_CONFIG_PATH=""                 # default: ~/.config/rclone/rclone.conf
NOTIFY_LEVEL=2                        # 0=Off, 1=Errors, 2=All (default)
POLL_INTERVAL=5                       # minutes between periodic bisync
FORCE_SYNC_NEWER=true                 # conflict: newer wins (true) vs .conflict files (false)
ENABLE_NOTIFICATIONS=true            # legacy key; mapped to NOTIFY_LEVEL when unset

First-run auto-resync

When cdsync poll runs for the first time on a fresh install, it checks three safety gates before bootstrapping the bisync database with --resync:

  1. No existing bisync state in ~/.cache/rclone/bisync/ for this remote
  2. The rclone remote is reachable (rclone lsd succeeds)
  3. The local sync directory is empty (refuses to auto-resync into a non-empty folder — could silently propagate local deletions to the cloud)

If all gates pass, the first poll runs rclone bisync --resync automatically (no Must run --resync error on the first run), and touches ~/.cdsync/config/.first_sync_done so subsequent polls run normal bisync. If any gate fails, the first poll is skipped with a clear log message — run cdsync poll --force-resync manually after verifying the config.