diff --git a/README.md b/README.md index 699e291..943aab9 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,33 @@ no account, central server, or web app. See [the architecture reference](docs/architecture.md) for Appa's folder, device, member, peer, node, and capability terminology. +## Run Appa as a service + +After installation, Appa normally runs as one long-lived local daemon. It owns +the Iroh node, SQLite state, file watchers, and background synchronization. +The CLI and COSMIC app are clients of that daemon, rather than starting another +sync process for each command. + +Install the per-user service once: + +```sh +appa service install +``` + +It starts immediately and starts again at login. The service uses systemd on +Linux and launchd on macOS. Check it with `appa service status`; `logs`, +`restart`, and `uninstall` are available through `appa service` too. + +For development, debugging, or another process manager, run the daemon in the +foreground instead: + +```sh +appa daemon serve +``` + +`appa run` remains a foreground alias for the daemon. Stop either foreground +form with Ctrl-C. + ## Install Appa requires Rust 1.97.1 or newer. From the repository root: @@ -36,7 +63,6 @@ On the first device: ```sh appa init ~/notes appa invite ~/notes --copy -appa run ``` Send the invitation to your other device. It is reusable for 24 hours, so @@ -46,11 +72,10 @@ On the other device: ```sh appa join ~/notes --stdin -appa run ``` -Confirm the join, paste the invitation, then press Ctrl-D. Appa now watches the -folder and syncs changes whenever both devices are reachable. +Confirm the join, paste the invitation, then press Ctrl-D. The local daemon +now watches the folder and syncs changes whenever both devices are reachable. Check the connection from either device: @@ -70,8 +95,7 @@ only that folder. | Add a folder | `appa init ` | | Invite a device | `appa invite --copy` | | Join a folder | `appa join --stdin` | -| Sync all folders | `appa run` | -| Sync one folder | `appa run ` | +| Run the daemon in foreground | `appa daemon serve` | | Check sync health | `appa status [folder]` | | List devices | `appa members ` | | List peer routes | `appa peers ` | @@ -100,10 +124,10 @@ lossily renamed during synchronization. ## Change folders while Appa runs -`appa run` refreshes its folder list and settings every second. You can run +The daemon refreshes its folder list and settings every second. You can run `appa init`, `appa join`, `appa leave`, or apply configuration from another -terminal; Appa starts watching added folders, stops watching removed folders, -and reloads changed folder settings without a daemon restart. +terminal; it starts watching added folders, stops watching removed folders, and +reloads changed folder settings without a daemon restart. ## Handle conflicts @@ -162,26 +186,12 @@ To stop syncing locally without deleting any files: appa leave ~/notes ``` -## Run in the background on Linux - -On Linux with systemd: - -```sh -appa service install -``` - -This installs and starts a user service. It restarts after failures and starts -on future logins. - -```sh -appa service status -appa service restart -appa service logs -appa service uninstall -``` +## Finding peers -On macOS and other platforms, run `appa run` with your preferred process -manager. +Appa uses Iroh for encrypted direct connections when possible and relay routes +when necessary. On a shared LAN, it also uses mDNS to discover a peer's direct +address. mDNS is only route discovery: it does not make a folder public or +replace invitation, roster, or encryption checks. ## COSMIC desktop companion diff --git a/docs/architecture.md b/docs/architecture.md index bc1dc14..e4ae3da 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,8 +1,10 @@ # Appa architecture -Appa is a single-binary, local-first folder synchronizer. Each running Appa -process is both a client and a server: it watches its registered folders, -serves manifests and blobs to authorized peers, and applies remote changes. +Appa is a single-binary, local-first folder synchronizer. A long-lived local +daemon owns synchronization: it watches registered folders, serves manifests +and blobs to authorized peers, and applies remote changes. The CLI and COSMIC +app are short-lived local clients that send requests to that daemon over its +user-owned local socket. ## Terms @@ -14,8 +16,9 @@ serves manifests and blobs to authorized peers, and applies remote changes. read/write, or read-only rights. - **Peer**: a reachable route for a member device. A peer may be reached over a direct LAN/WAN address or through an Iroh relay. -- **Node**: the in-process Iroh endpoint that hosts folders and transfers - blobs. `appa run` creates one node for all configured folders. +- **Node**: the daemon's in-process Iroh endpoint that hosts folders and + transfers blobs. `appa daemon serve` creates one node for all configured + folders. - **Capability**: the secret required to request a folder's control data. An invitation carries a capability and a signed roster; treat it like a password. @@ -34,8 +37,9 @@ serves manifests and blobs to authorized peers, and applies remote changes. recovered on the next sync. All control streams and blob transfers are authenticated and encrypted by -Iroh. LAN discovery only provides direct route information; it does not change -the encryption or membership checks. +Iroh. The daemon uses mDNS on a LAN to discover direct routes, while Iroh can +use relay routes when a direct route is unavailable. Discovery only provides +route information; it does not change encryption or membership checks. ## Local state and configuration