What chant is
chant compiles TypeScript into native formats such as CloudFormation and Kubernetes YAML. Per environment, it can also deploy what it built or compare it with what is running.
The core is a compiler: TypeScript in, spec-native artifacts out, validated by semantic lint rules. Per environment you then pick what happens after the build: observe drift, reconcile cloud → code, or apply code → cloud, locally or on a fountain steward. The compiler is what makes the rest auditable and safe.
The core is a compiler
Section titled “The core is a compiler”chant build reads the resource objects your TypeScript exports and emits the target format. The default path does not import your file at all: the source is reduced to values without executing it, which the specification calls folding. A file that does more than declare values is imported and run instead, and both paths produce the same output. No cloud API is called, no state is read or written, nothing is deployed.
Every value in the output traces to a line of source. The build makes no network calls and holds no credentials, and synthesis is fast enough to run in the IDE. That makes it small and side-effect-free to audit, and every later stage starts from output you can trust. See Philosophy and TypeScript as Data for why the core is built this way.
The lifecycle is yours
Section titled “The lifecycle is yours”Most infrastructure tools ship the compiler and the deployment lifecycle as one product, so you take both or neither. chant separates them:
Pluggable lexicons in, pluggable lifecycles out, deterministic synthesis in the middle.
You pick a position per environment on one dial:
- observe —
chant lifecycle diff --live/WatchOp: read live drift, change nothing. - reconcile —
ReconcileOp: opencloud → codePRs that pull live reality back into source. - apply —
ApplyOp: pushcode → cloudbehind a gate, with owned-only deletes.
A dev environment might only observe while production applies behind an approval gate, in the same project. The live system is the source of truth, and a marker on each resource records who owns it. See Lifecycle Models for the full model.
Durable when you need it
Section titled “Durable when you need it”The lifecycle is orchestration, and you declare it as Ops — named, phased workflows in *.op.ts files. An Op runs locally by default, in the chant process. When it needs a machine of its own, a standing record, or a schedule, the same Op runs on a fountain steward with chant run <op> --on fountain.
The component release model is built from Ops: declare a releasable unit in *.component.ts, and one generated orchestrator builds, publishes, signs, applies, verifies, and rolls it back. You write no pipeline per unit.
The whole arc
Section titled “The whole arc”| Stage | What runs | Where it’s covered |
|---|---|---|
| Author | TypeScript resources, composites, presets | Writing Resources |
| Validate | semantic lint + type-check, one local pass | Linting |
| Emit | chant build → spec-native artifacts | Building |
| Deploy | Ops (local or on a steward), or hand off to your pipeline | Ops · Deployment Model |
| Observe | live drift against the deployed system | Drift Detection |
| Reconcile / apply | cloud → code PRs, or gated code → cloud | Lifecycle Models |
Every stage after Emit is optional. Hand a chant-built artifact to any deployment tool and the later stages go unused. The output is the native format, so you can stop using chant and keep it.
Where chant draws the line
Section titled “Where chant draws the line”chant hosts no authoritative state file, and the build path itself never touches your cloud. You bring the apply step, such as kubectl or a CI pipeline, or chant runs it for you through an Op. Keeping it out of the build keeps the core small and the output portable. How chant compares works through the trade-offs against Terraform, CDK, and Pulumi.
The subset has a specification
Section titled “The subset has a specification”A published specification, TypeScript-as-Data, defines which TypeScript folds. chant implements it, the specification is versioned, and chant declares the version it implements as SPEC_VERSION, exported from @intentius/chant:
import { SPEC_VERSION } from "@intentius/chant";// "2.3"A conformance suite runs chant and a second, independent implementation over the same fixtures and compares them, so “chant folds this” is a claim something else checks. TypeScript as Data is chant’s guide to that rule set.
- Philosophy — why the core is a deterministic compiler
- Lifecycle Models — the observe -> reconcile -> apply dial, in depth
- Choosing Your Deployment Model — synthesis hand-off, Ops on the local runtime, Components, or a fountain steward
- Getting Started — install and build your first artifact