Compatibility · Terraform 1.14 · OpenTofu 1.11

Radically honest compatibility.

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.

Supported Partial — improving ⚠️ Parsed, but diverges Refuses loudly (never mis-plans) Coming soon
Top-level blocks
ConstructTerraform 1.14OpenTofu 1.11TurfNotes
resourceFull resource support; also on the plot authoring whitelist.
dataData sources, read directly.
moduleRecursive registry / local / git module install and expansion.
variableFully 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.
outputOutputs, including sensitive ones — a sensitive-valued output must be declared sensitive (a loud error, never silent auto-inference).
localsFully 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).
providerThe non-secret provider block is written to config; credentials are supplied out-of-band, session-side.
terraform {} settingsHand-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.
backendState 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.
movedRefused 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.
removedAggregated 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_triggerThe Terraform 1.14 action model, carried by Turf — OpenTofu has no action blocks yet. ahead of OpenTofu
ephemeral resourceEphemeral resources aren’t supported yet — coming soon (parity with Terraform and OpenTofu).
write-only argumentsWrite-only attributes aren’t handled yet — coming soon (parity with Terraform and OpenTofu).
List resources / list block / queryThe 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 importImport today adopts by string ID only; identity-object import is coming soon (it depends on the identity round-trip above).
Meta-arguments
Meta-argumentTerraform 1.14OpenTofu 1.11TurfNotes
countFully 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_eachSame 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_onModules and codified resources.
lifecycle.create_before_destroySupported; forced create-before-destroy is propagated through the plan at approval.
lifecycle.prevent_destroyErrors 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_byNot supported yet — coming soon.
lifecycle.precondition / postconditionCustom condition checks aren’t modeled or evaluated yet — coming soon.
lifecycle.action_triggerThe 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.
Expressions & functions
FeatureTerraform 1.14OpenTofu 1.11TurfNotes
for-expressions, conditionals, splat, dynamic blocks, string templates, full builtin function libraryThe 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.
Plan / apply options & workflow
FeatureTerraform 1.14OpenTofu 1.11TurfNotes
-targetAccepted by the schema but refused at runtime today — Turf plans the whole configuration rather than a silent partial apply. Coming soon.
-excludeRefused at runtime today; coming soon. (An OpenTofu-only flag — Terraform has no -exclude.)
-refresh-onlyRefused at runtime today — coming soon.
-var-fileRefused today; use -var. File-based var inputs are coming soon.
-replaceHonored — force replacement of a target resource.
destroyDestroy plans the configuration plus every state orphan, reverse-dependency ordered; config files are left untouched.
-varThe single variables mechanism; in-memory only.
saved planfile round-tripThe 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 encryptionSupported through the backend; not yet verified end-to-end. (An OpenTofu-only feature.)
early variable evaluationSupported.
.tftest.hcl / .tofutest.hcl test runnerThe 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
HCL Stacks (components & deployments)
Construct / capabilityTerraform 1.14OpenTofu 1.11TurfNotes
Component config — .tfcomponent.hcl: component (wraps a module) plus stack-level variable / output / provider / removedNot 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, storeNot parsed — no deployment / orchestrate blocks. Terraform-only.
Capability: multi-environment, multi-round deploymentA 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.

Beyond Terraform & OpenTofu

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.

Agentic Terraform actions

turf_confirm (agent elicitation) and turf_action (sampling), served by Turf’s built-in provider identity and validated natively at plan time.

Agent-in-the-loop apply

Take it slow! You're in control as infrastructure changes are applied, so the agent - and you - can intervene at any step.

Turf Plots - No-Code Infrastructure

Shift-left: Ad-hoc configurations graduate to idiomatic .tf via a converter.

Agentic multi-phase deferral

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.