Skip to content

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.

Desired state and observed runtime state compared by a comparator to produce a drift report.

  • 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 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 a confirmed lifecycle plan.

Imperative commands describe how; a manifest describes what. A declarative model provides properties that imperative commands do not:

  • Idempotency: a lifecycle command 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 reports when observed state diverges from desired state.
  • 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.

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: 2
project: api-local
services:
api:
image: ghcr.io/example/api:latest
ports:
- "8080:8080"

Hostwright does not run an aggressive convergence loop. The foreground daemon observes, plans, and records events; it never calls a lifecycle command itself. Mutation stays reserved for an operator (or an operator-triggered script) running up, down, run, start, stop, restart, rm, or update with an explicit --confirm-plan. A confirmed plan can converge every affected service in one invocation, in dependency order, but only the services and actions named in that exact plan; see Limitations for what recovery can and cannot do when a plan is interrupted partway through.