chant lifecycle
Synopsis
Section titled “Synopsis”chant lifecycle snapshot <env> [lexicon]chant lifecycle show <env>chant lifecycle diff <env> [--live]chant lifecycle log [env]Description
Section titled “Description”chant lifecycle captures point-in-time snapshots of deployed infrastructure by querying the cloud provider API and saving the result to a git orphan branch. Snapshots enable drift detection — comparing what’s currently built against what was last deployed, and (with --live) against what’s actually in the cloud right now.
The environment name (e.g. dev, staging, prod) must be declared in chant.config.ts under environments.
For the conceptual model behind these commands — observational vs. authoritative state, resources vs. artifacts, when drift detection earns its keep — see Drift Detection.
Subcommands
Section titled “Subcommands”lifecycle snapshot <env>
Section titled “lifecycle snapshot <env>”Query the provider API for the current deployed state, then save a snapshot to the chant-state/<env> orphan branch.
chant lifecycle snapshot devchant lifecycle snapshot prod aws # snapshot only the aws lexiconlifecycle show <env>
Section titled “lifecycle show <env>”Print the latest saved snapshot for an environment.
chant lifecycle show devlifecycle diff <env>
Section titled “lifecycle diff <env>”Two modes, depending on whether --live is set.
Default (digest mode). Build the current project, fingerprint the resource declarations, and compare against the digest stored in the last snapshot. Fast, offline, and useful as a fast-feedback check inside CI — but only catches changes you’ve made in source. Ignores the cloud entirely.
chant lifecycle diff devReports added, removed, changed, and unchanged resources at the declaration level.
--live (drift mode). Query the cloud provider API right now via each lexicon’s describeResources() plugin method, then compare the live result against both the previous snapshot and the current build. This is the path that actually catches external mutations (someone scaled a node pool by hand, deleted a bucket, etc.).
chant lifecycle diff prod --liveOutput is grouped into six categories per lexicon:
| Category | Meaning |
|---|---|
| missing | Declared in source, but not present in the cloud right now |
| orphan | Present in the cloud, but not declared in source |
| disappeared | In the previous snapshot, but gone now |
| newly observed | Declared and observed now, but not in any prior snapshot |
| drifted | Observed in both snapshots; status, physical ID, or attributes changed |
| unchanged | Observed in both snapshots; metadata identical |
Drifted entries include attribute-level deltas (status, physicalId, lastUpdated, and each attributes.* key).
lifecycle plan <env>
Section titled “lifecycle plan <env>”Promote the live diff to a typed, read-only change set. Where lifecycle diff --live reports six observation categories, lifecycle plan classifies each resource into one action you can act on:
chant lifecycle plan prodchant lifecycle plan prod --json # emit the ChangeSet as JSON| Action | Meaning |
|---|---|
| create | Declared in source, absent from the cloud |
| update | Declared and live, but the live config drifted |
| delete | A chant-owned resource that is live but no longer declared |
| adopt | Live but undeclared, ownership not established — a candidate to pull back into source, never an auto-delete |
| noop | Declared and live with no drift, or already reconciled |
create and update are precise from declared-vs-live. delete is only ever proposed for an undeclared resource whose live ownership marker (ownership marking) confirms it is chant’s; a foreign orphan is adopt, and an orphan with no marker data is adopt, never delete. Pass --owned to restrict the query to chant-owned resources.
The classification reads ownership from the live marker, never from the snapshot, so the snapshot never becomes load-bearing: the delete decision is identical whether or not a snapshot exists. The moment a mutation trusted the snapshot, the snapshot would have become an authoritative state file under a different name — which chant deliberately avoids.
lifecycle plan is strictly read-only: it builds, queries, and classifies. It never mutates the cloud and never deploys — chant build stays pure.
Resources vs artifacts
Section titled “Resources vs artifacts”A single lexicon may report both resources (entity-keyed, via describeResources()) and artifacts (context-keyed, via listArtifacts()); lifecycle diff --live shows them in separate sections. Artifacts use a four-category two-way diff (no “declared” axis):
| Category | Meaning |
|---|---|
| artifacts added | Observed now, not in last snapshot |
| artifacts removed | In last snapshot, gone now |
| artifacts changed | In both; metadata changed |
| artifacts unchanged | In both; metadata identical |
For the conceptual distinction between resources and artifacts, see Drift Detection — Resources and artifacts.
Coverage today
Section titled “Coverage today”See the Runtime observation coverage matrix on the Lexicons overview page for the canonical version with query-mechanism notes. Summary:
| Lexicon | describeResources() | listArtifacts() |
|---|---|---|
| AWS | ✅ | |
| Temporal | ✅ | |
| K8s | ✅ | |
| GCP (via Config Connector) | ✅ | |
| Azure | ✅ | |
| Helm | ✅ | |
| Docker | ✅ | |
| GitHub / GitLab | N/A — see lexicon READMEs |
Lexicons that implement neither method are warn-skipped — --live doesn’t fail the whole command for them.
The Temporal lexicon resolves its connection via the chant config: lifecycle snapshot <env> (or --live against <env>) looks up temporal.profiles.<env> in your chant.config.ts and falls back to temporal.defaultProfile. The same profile model is used by chant run. With #39’s entity-prop pass-through, namespaces/schedules/search-attributes are mapped back to chant entity names when the declared props.name (etc.) match the server-side identifier.
The K8s lexicon shells out to kubectl get <kind> <name> [-n <namespace>] -o json per declared entity. The cluster context comes from the user’s kubeconfig — there’s no separate profile model. Twenty common resource types (Deployment, Service, ConfigMap, Secret, Namespace, Pod, PVC, ServiceAccount, Job, CronJob, Ingress, NetworkPolicy, RBAC roles + bindings, ReplicaSet, StatefulSet, DaemonSet) are covered out of the box; CRDs and uncommon types are warn-skipped.
The GCP lexicon uses the same kubectl shell-out path against Config Connector CRDs. The entity type’s GVK derivation matches the serializer (GCP::Storage::Bucket → storagebucket.storage.cnrm.cloud.google.com), so any of the ~300 chant-supported GCP resources work without per-type configuration. Ready=True on the resource’s status is mapped to READY; otherwise the condition’s reason is surfaced.
The Azure lexicon shells out to az resource show --resource-group <env> --name <name> --resource-type <type> -o json per declared entity. The <env> argument is treated as the Azure resource group name. properties.provisioningState becomes the status. Top-level resources only — nested ARM types (e.g. Microsoft.Storage/storageAccounts/blobServices) are warn-skipped since az resource show doesn’t accept compound type names directly.
Concurrent snapshots
Section titled “Concurrent snapshots”Snapshots are pushed to the orphan chant/lifecycle branch with git push --force-with-lease. If two operators (or a CI job + a human) take a snapshot for the same remote at the same time, the second push is rejected rather than silently overwriting the first. You’ll see:
error: Another snapshot completed for chant/lifecycle after this run started (env: prod).hint: Pull and retry: `git fetch origin chant/lifecycle:chant/lifecycle` && `chant lifecycle snapshot prod`.Pull the remote ref and re-run — the first snapshot is preserved, the second proceeds against the updated baseline.
lifecycle log [env]
Section titled “lifecycle log [env]”List the history of snapshots. Omit env to show all environments.
chant lifecycle log # all environmentschant lifecycle log dev # just devExit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (invalid environment, API failure, no snapshot found) |
See Also
Section titled “See Also”chant build— build current output for diffing- Configuration — declare
environmentsinchant.config.ts - Watching Lifecycle — wire
lifecycle snapshot+lifecycle diff --liveto aTemporalSchedulevia theWatchOpcomposite - Implementing Observation — for lexicon authors, how to plug into
--liveviadescribeResources()/listArtifacts()