Compatibility · Terraform 1.14 · OpenTofu 1.11
Turf is built on the OpenTofu framework — the whole expression language, the function library, and the provider ecosystem. It runs ahead of OpenTofu on actions and deferred changes, and it publishes every gap. Where a construct isn’t supported yet, Turf refuses loudly — it never silently mis-plans.
| Construct | Terraform 1.14 | OpenTofu 1.11 | Turf | Notes |
|---|---|---|---|---|
resource | ✅ | ✅ | ✅ | Full resource support; also on the plot authoring whitelist. |
data | ✅ | ✅ | ✅ | Data sources, read directly. |
module | ✅ | ✅ | ✅ | Recursive registry / local / git module install and expansion. |
variable | ✅ | ✅ | ✅ | Fully honored. The declared surface (type / default / sensitive) is modeled and values are supplied at plan time. -var is the value mechanism today; .tfvars / var-file inputs are coming soon. |
output | ✅ | ✅ | ✅ | Outputs, including sensitive ones — a sensitive-valued output must be declared sensitive (a loud error, never silent auto-inference). |
locals | ✅ | ✅ | ✅ | Fully honored in the codified walk. Authoring an ad-hoc plot local isn’t wired yet — an additive convenience, not a language gap (author in codified form or promote). |
provider | ✅ | ✅ | ✅ | The non-secret provider block is written to config; credentials are supplied out-of-band, session-side. |
terraform {} settings | ✅ | ✅ | ✅ | Hand-authored and read by the walk. In a plot, backend / required_providers / provider_meta are folded from per-unit metadata. |
terraform.required_version | ✅ | ✅ | ⚠️➖ | Parsed but not yet enforced — version constraints aren’t checked today. Coming soon. |
backend | ✅ | ✅ | ✅ | State backends. OpenTofu adds state / plan encryption; Turf supports it through the backend (end-to-end verification coming). |
provisioner / connection | ✅ | ✅ | ⛔/⚠️ | Refused as config keys — there is no provisioner runtime, so they never run silently. Use a provider or an action instead. |
moved | ✅ | ✅ | ⛔ | Refused at plan today — Turf keeps addresses stable, so a rename plans no change. Honored moved state moves are coming soon; until then it refuses loudly rather than destroy-and-recreate. |
import block | ✅ | ✅ | ⚠️ | The import block is parsed but not yet honored by the walk; the imperative resource-import tool is the supported path today. Coming soon. |
removed | ✅ | ✅ | ✅ | Aggregated and folded into orphan / forget planning; lifecycle { destroy = false } becomes a state-only forget. |
check | ✅ | ✅ | ⚠️➖ | Parsed but not yet evaluated — check assertions don’t run today. Coming soon. |
action + action_trigger | ✅ | ➖ | ✅ | The Terraform 1.14 action model, carried by Turf — OpenTofu has no action blocks yet. ahead of OpenTofu |
ephemeral resource | ✅ | ✅ | ➖ | Ephemeral resources aren’t supported yet — coming soon (parity with Terraform and OpenTofu). |
| write-only arguments | ✅ | ✅ | ➖ | Write-only attributes aren’t handled yet — coming soon (parity with Terraform and OpenTofu). |
List resources / list block / query | ✅ | ➖ | ➖ | The Terraform 1.14 query paradigm (list blocks, .tfquery.hcl, terraform query) for bulk discovery and import. Coming soon; OpenTofu doesn’t have it yet either. |
| resource identity (provider-declared) | ✅ | ➖ | ⚠️ | Provider-declared resource identity (Terraform 1.12+) is not yet read or persisted, so a state carrying an identity object loses it on the next write. A round-trip fix is coming soon. |
| identity-based import | ✅ | ➖ | ➖ | Import today adopts by string ID only; identity-object import is coming soon (it depends on the identity round-trip above). |
| Meta-argument | Terraform 1.14 | OpenTofu 1.11 | Turf | Notes |
|---|---|---|---|---|
count | ✅ | ✅ | ✅ | Fully supported on codified resources and on modules. A plot’s single-resource declare doesn’t model it — author via a module or the codified form (ergonomics, not a gap). |
for_each | ✅ | ✅ | ✅ | Same as count — codified resources and modules. |
enabled (module) | ➖ | ✅ | ✅ | Turf’s module-level enabled for conditional instantiation; mutually exclusive with count / for_each. Convergent with OpenTofu 1.11; absent from Terraform. |
depends_on | ✅ | ✅ | ✅ | Modules and codified resources. |
lifecycle.create_before_destroy | ✅ | ✅ | ✅ | Supported; forced create-before-destroy is propagated through the plan at approval. |
lifecycle.prevent_destroy | ✅ | ✅ | ✅ | Errors if the plan would destroy the resource. |
lifecycle.ignore_changes (incl. ["all"]) | ✅ | ✅ | ◑ | Honored at preview today, but not yet consistent across every path (indexed paths and the apply path need work). Improving. |
lifecycle.replace_triggered_by | ✅ | ✅ | ➖ | Not supported yet — coming soon. |
lifecycle.precondition / postcondition | ✅ | ✅ | ➖ | Custom condition checks aren’t modeled or evaluated yet — coming soon. |
lifecycle.action_trigger | ✅ | ➖ | ✅ | The 1.14 action trigger. on_failure = taint is parsed but currently behaves as halt, and condition isn’t evaluated yet — both coming soon. ahead of OpenTofu |
provider / providers = {} | ✅ | ✅ | ✅ | Resource provider = and module providers = {}, validated against configuration_aliases. |
timeouts {} | ✅ | ✅ | ➖ | Not yet parsed or forwarded to the provider; providers run with their SDK defaults. Coming soon. |
| Feature | Terraform 1.14 | OpenTofu 1.11 | Turf | Notes |
|---|---|---|---|---|
for-expressions, conditionals, splat, dynamic blocks, string templates, full builtin function library | ✅ | ✅ | ✅ | The whole expression language and builtin function library — Turf imposes no function allow / deny list. Composite expressions and dynamic blocks survive the declare → unit → walk round-trip. |
provider-defined functions (provider::…) | ✅ | ✅ | ✅ | Supported — verify against a provider that exports functions. |
| Feature | Terraform 1.14 | OpenTofu 1.11 | Turf | Notes |
|---|---|---|---|---|
-target | ✅ | ✅ | ⛔ | Accepted by the schema but refused at runtime today — Turf plans the whole configuration rather than a silent partial apply. Coming soon. |
-exclude | ➖ | ✅ | ⛔ | Refused at runtime today; coming soon. (An OpenTofu-only flag — Terraform has no -exclude.) |
-refresh-only | ✅ | ✅ | ⛔ | Refused at runtime today — coming soon. |
-var-file | ✅ | ✅ | ⛔ | Refused today; use -var. File-based var inputs are coming soon. |
-replace | ✅ | ✅ | ✅ | Honored — force replacement of a target resource. |
| destroy | ✅ | ✅ | ✅ | Destroy plans the configuration plus every state orphan, reverse-dependency ordered; config files are left untouched. |
-var | ✅ | ✅ | ✅ | The single variables mechanism; in-memory only. |
| saved planfile round-trip | ✅ | ✅ | ➖ | The copy-on-approve seal directory is the plan snapshot; .tfplan file emission and ingestion are coming soon. |
provider for_each (multi-instance providers) | ➖ | ✅ | ⛔ | Turf’s provider model is strictly per-(name, alias) today, so a for_each provider can’t be routed — it refuses rather than mis-route. Coming soon. (OpenTofu-only; Terraform has no provider for_each.) |
| state / plan encryption | ➖ | ✅ | ◑ | Supported through the backend; not yet verified end-to-end. (An OpenTofu-only feature.) |
| early variable evaluation | ◑ | ✅ | ✅ | Supported. |
.tftest.hcl / .tofutest.hcl test runner | ✅ | ✅ | ➖ | The native HCL test files aren’t executed yet — a turf test command to run them (with plots support) is coming soon. |
| deferred changes / deferral (“try again later”) | ✅ | ◑ | ✅ | A real Terraform capability — the mechanism behind unknown count / for_each / provider config, and the substrate for Stacks. Turf’s distinctive form is a first-class, agent-driven, replan-based multi-phase convergence for any config — no experimental flag. ahead of OpenTofu |
| Construct / capability | Terraform 1.14 | OpenTofu 1.11 | Turf | Notes |
|---|---|---|---|---|
Component config — .tfcomponent.hcl: component (wraps a module) plus stack-level variable / output / provider / removed | ✅ | ➖ | ➖ | Not parsed — Turf has no component block. Stacks is Terraform-only; OpenTofu has none of it either. Turf’s multi-environment story is workspace fan-out (below). |
Deployment config — .tfdeploy.hcl: deployment, orchestrate, identity_token, publish_output / upstream_input, store | ✅ | ➖ | ➖ | Not parsed — no deployment / orchestrate blocks. Terraform-only. |
| Capability: multi-environment, multi-round deployment | ✅ | ➖ | ◑ | A different model, not the Stacks language: one registered configuration bound by N workspaces, each with its own backend and state — the staging / prod idiom — driven across rounds by phases and deferral. Honest caveat: this is workspace fan-out, not a single object that rolls out across deployments as a unit, and there’s no orchestrate / identity_token / cross-stack output wiring yet. |
Turf is built on the OpenTofu framework — then adds an agent-oriented execution model on top. A handful of capabilities have no Terraform or OpenTofu equivalent.
turf_confirm (agent elicitation) and turf_action (sampling), served by Turf’s built-in provider identity and validated natively at plan time.
Take it slow! You're in control as infrastructure changes are applied, so the agent - and you - can intervene at any step.
Shift-left: Ad-hoc configurations graduate to idiomatic .tf via a converter.
Deferral provides a first-class, agent-driven convergence loop: a “try again later” records what to resolve, the agent resolves it, and replan re-walks until nothing remains — and no Stacks required.