Desired state
Hostwright is a desired-state system. You declare what should run; Hostwright observes what is running, computes the difference, and reports it as drift with a deterministic plan.
Two kinds of state
Section titled “Two kinds of state”- Desired state — what you declared in
hostwright.yaml. Persisted as a snapshot to the explicit SQLite database you pass with--state-db. - Observed state — what is actually running, read back from the runtime
through the RuntimeAdapter at a point in time.
hostwright status --state-db <path>records it as an observed snapshot.
The reconciler compares the two, emits typed drift records and issues, and produces a plan with a deterministic hash. Convergence is never automatic: mutation happens only through the confirmed apply gate, one action at a time.
Why declare instead of command
Section titled “Why declare instead of command”Imperative commands describe how; a manifest describes what. A declarative model gives you properties that are hard to get from a pile of shell commands:
- Idempotency — apply recomputes the plan and refuses to run when the confirmed hash no longer matches reality, so a stale intent cannot re-execute.
- Drift detection — with desired and observed snapshots both recorded, Hostwright notices when reality diverges instead of you discovering it by surprise.
- Reviewable change — the difference is shown as a plan, with a hash, before anything mutates.
- Recovery — operation intent, checkpoints, and recovery records are
persisted before mutation, so an interrupted operation is diagnosable with
hostwright recovery.
The unit of declaration
Section titled “The unit of declaration”A manifest declares a project that contains one or more services. A service references an image and the runtime details needed to run it — ports, environment, secret references, health checks, and restart policy.
version: 2project: api-local
services: api: image: ghcr.io/example/api:latest ports: - "8080:8080"What convergence is not
Section titled “What convergence is not”Hostwright does not run an aggressive convergence loop. The foreground
daemon observes, plans, and records events — it never
mutates. apply executes exactly one confirmed action per invocation. Automatic
rollback and multi-action apply are not implemented; see
Limitations.
