Skip to content

chant carve (emit / bridge / apply)

chant carve emit --from <tf-dir> --select <address> --env <env>
chant carve bridge --from <tf-dir> --select <address> [--apply-rewrites]
chant carve apply --from <tf-dir> --select <address> --env <env> [--write]

The carve commands peel a resource out of a Terraform estate into native chant source — incrementally, never the whole estate. The long tail stays in Terraform; “we can’t map this” becomes “leave it where it is,” not a failure. Start with chant carve advise to see what is cheap to carve.

A carve never destroys or recreates. It reuses the adopt-an-orphan loop: Terraform stops managing the resource, chant adopts the still-live resource, and you sit at the observe position until you turn the dial to apply. Every step before graduation is reversible with terraform import.

The flow is three steps.

Adopts the selected resource into typed chant source and reports the boundary — every dependency edge the carve would cut. There are two adoption sources:

  • --state <tfstate> (recommended) adopts offline, straight from the Terraform state file. This is the correct source for a Terraform-managed resource: it is created through the provider API, not CloudFormation, so it is not in any CFN stack, but its resolved attributes are in the state. No cloud call.
  • --env <env> adopts via the live cloud→code import path (for resources already in a CloudFormation stack). It selects by native type; if the stack has several resources of that type, narrow it with --live-name <logical-id>. This path is exercised end to end against a real AWS endpoint by just carve-emit-e2e (Floci in Docker).
chant carve emit --from ./infra --select aws_s3_bucket.assets --state ./terraform.tfstate

The state path emits a native chant Declarable with CloudFormation-style properties mapped from the Terraform attributes; attributes without a mapping are preserved in a reference comment so nothing is dropped. It covers ~50 common AWS carve targets across S3, IAM, DynamoDB, SNS/SQS, Lambda, KMS, Secrets Manager, SSM, ECR, CloudWatch, Route 53, EFS, EC2 (instances + networking), autoscaling, ELBv2, RDS, ElastiCache, API Gateway, Step Functions, ACM, and ECS; advise and emit cover exactly the same AWS types, so there is no rank-it-but-can’t-emit gap. A type outside that set reports the supported list. Nothing is patched or applied; the resource lands at the observe position.

After emit, chant lint ./out --lexicon aws audits the adopted resource — advisory findings you may choose to fix, and errors that block chant build (e.g. a bucket with no public-access block). Auditing what you inherited is part of the point.

Generates the edits to the Terraform you leave behind so its plan stays valid once the resource is chant-owned.

  • Inbound edges (a survivor reads the carved resource) become a data source plus rewired references. Required immediately, or terraform plan errors on the dangling reference.
  • Outbound edges (the carved resource read a survivor) become deferred deploy-time inputs, wired at apply.
chant carve bridge --from ./infra --select aws_s3_bucket.assets

Safe by default: it writes the proposed data sources, rewritten survivor files, and a runbook to an output directory for review. --apply-rewrites edits the survivor .tf in place. The rewrite is idempotent and never touches the carved resource’s own declaration.

Resolves the ownership marker that makes the resource chant-owned and finalizes the ordered apply runbook.

chant carve apply --from ./infra --select aws_s3_bucket.assets --env prod --stack assets

This is BYOL-honest: it makes no cloud call. It computes the marker and the plan; the apply itself is whatever lifecycle you brought — the native CLI, a CI pipeline, an ApplyOp — and it stamps the ownership marker the emitted source carries. --write saves the graduation doc.

# 1. see what's cheap to carve
chant carve advise --from ./infra
# 2. adopt the bucket into chant source, see its boundary
chant carve emit --from ./infra --select aws_s3_bucket.assets --env prod
# 3. Terraform stops managing it (does NOT destroy it)
terraform state rm aws_s3_bucket.assets
# 4. patch the survivors so their plan stays valid
chant carve bridge --from ./infra --select aws_s3_bucket.assets --apply-rewrites
terraform plan && terraform apply
# 5. graduate: mark it chant-owned, then apply with your lifecycle
chant carve apply --from ./infra --select aws_s3_bucket.assets --env prod --write

At every step before 5, rollback is terraform import aws_s3_bucket.assets <id>.

These are the emit, boundary-bridging, and apply-graduation phases of the strangler-fig design (#197), built on the read-only advisor (#214). Emit targets a Declarable (a single native resource); a whole service with a deploy pipeline is a Component, not a leaf carve. Removing the carved resource’s own block from the .tf is a runbook step, not an automatic edit — the parser has no source spans to excise a block precisely.