Skip to content

6. Sync architecture: resident daemon

  • Status: Accepted
  • Date: 2026-07-01
  • Deciders: kristof (owner), Claude (orchestrator)
  • Relates: architecture §2c, Components, GitHub issues #6, #7, #8

Context

M2 makes the brain multiplayer: local working copies must converge with a git remote, and same-file edits must serialize without data loss. Two shapes were considered: a lean sync library + CLI invoked by Claude Code hooks (no resident process), or a long-lived per-machine daemon that watches and continuously syncs.

Decision

A resident, per-machine daemon (@cmnwlth/sync, bin commonwealth-sync).

  • Watches each registered brain working copy for filesystem changes and, on change, commits and pushes.
  • Runs a periodic pull loop so inbound teammate changes land continuously — not only at session boundaries. This enables real-time background propagation, the differentiator over hook-only sync.
  • Owns the write queue: all git mutations run through one in-process serial queue (acquire → rebase → apply → push → retry), so concurrent changes never race (#7).
  • On a genuine same-file conflict, never overwrites: writes both versions as sibling notes and records a conflict marker for review (#8).
  • After every pull, rebuilds the derived index and regenerates COMMONWEALTH.md/INDEX.md.

The sync engine (pure-ish functions: syncOnce, commitChange, the queue, conflict resolution) is factored out from the long-running watcher so it is unit-testable against temp git repos (a bare remote + two clones) without running the daemon.

Consequences

  • Real-time cross-session propagation; the daemon is the natural host for later capture/curate hooks (M3) too.
  • More moving parts than a library: process lifecycle (start/stop/status via PID file), a filesystem watcher, a poll loop. Mitigated by keeping all correctness-critical logic in the testable engine and treating the daemon as a thin runner.
  • Claude Code hooks (M4) still exist but become thin — they can nudge the daemon (or fall back to a one-shot commonwealth-sync sync) rather than owning sync logic.

Alternatives considered

  • Lean sync library + CLI invoked by hooks — simpler and fully testable, but only syncs at session boundaries; no continuous background propagation. Rejected in favor of the real-time experience, accepting the added lifecycle complexity.
  • CRDT / custom sync protocol — off-git, conflicts with the ownership thesis (ADR-0003). Rejected.