D 2026-10-13T02:27:53.200 L Leaf\sAgent N text/x-markdown U dmestas W 2071 # Leaf Agent A Go daemon that sits next to a Fossil repo and keeps it synced over NATS. ## Data Flow ``` pikchr right R: cylinder "repo.fossil" color white fill 0x3a3a3a width 1.2 height 0.5 rad 3px move 0.2 arrow color white thick <-> move 0.1 A: box "Leaf Agent" color white fill 0x2a6b3a width 1.5 height 0.5 rad 5px move 0.2 arrow color white thick "sync request" above move 0.1 N: cylinder "NATS" color white fill 0x2a4a6b width 1.0 height 0.5 rad 5px move 0.2 arrow color white thick move 0.1 B: box "Bridge" color white fill 0x6b5a2a width 1.2 height 0.5 rad 5px move 0.2 arrow color white thick "HTTP" above move 0.1 F: box "Fossil" color white fill 0x6b2a2a width 1.2 height 0.5 rad 5px ``` ## How It Works 1. Opens a `.fossil` repo — reads project/server codes from SQLite 2. Connects to NATS 3. Polls every 5s (configurable): - Checks `unsent`/`unclustered` tables - If new artifacts found, calls `sync.Sync()` via NATS transport 4. `SIGUSR1` triggers immediate sync 5. `SIGINT`/`SIGTERM` graceful shutdown ## Usage ``` leaf-agent --repo /path/to/repo.fossil \ --nats nats://localhost:4222 \ --poll 5s \ --push --pull ``` | Flag | Env Var | Default | Description | |------|---------|---------|-------------| | `--repo` | `LEAF_REPO` | (required) | Path to `.fossil` file | | `--nats` | `LEAF_NATS_URL` | `nats://localhost:4222` | NATS server URL | | `--poll` | — | `5s` | Poll interval | | `--user` | `LEAF_USER` | `anonymous` | Sync user | | `--password` | `LEAF_PASSWORD` | — | Sync password | | `--push` | — | `true` | Push local artifacts | | `--pull` | — | `true` | Pull remote artifacts | | `--prefix` | — | `fossil` | NATS subject prefix | ## Concurrency The poll goroutine is the sole executor of sync. `SyncNow()` sends on a buffered channel — it never calls sync directly. This avoids concurrent SQLite access. ## See Also - [Bridge](wiki:Bridge) — the other half - [Home](wiki:index) — architecture overview Z 566e7eccd75703e3315e7e8bdb9d4a98