TF vendor power - without the SaaS
Terraform vendors sell plan and apply on pull requests, approvals, policy, drift checks and an audit trail, run on their servers with your cloud credentials. terragucci is those pipelines, ready to run in your own CI on GitHub, GitLab or Forgejo, with state and reports in your own bucket. There’s no account to create and no platform to log into, and it’s Apache-2.0.
choudoufu is optional. It’s OpenTofu that tags each resource with its owner, so the state file becomes a cache and locking goes per resource. It runs on AWS and Kubernetes under MPL-2.0, and since the cache is a stock state file, going back to stock is a copy.
What you’d pay a SaaS for

State and locking

Sources at the end links every cell to its doc.
Kill an apply
kill -9 an apply right after it creates a VPC, then run it again. choudoufu tags the VPC in the create request, so the next plan finds it by that tag and the re-run binds it instead of building a second one. Stock Terraform and OpenTofu record the VPC only after the create call returns, so a kill in that window leaves one the re-run doesn’t know about. The ten types that take no tags at create keep that window under choudoufu too.
A plan that costs its change
plan -cone plans only the changed resources, what they depend on and what depends on them. It’s opt-in for pull requests and approved with the plan. A change that touches providers, the lock file or more than 30% of the estate gets a full plan instead.
A plan across state files
A root that reads another root’s state plans on that root’s planned outputs, so it’s checked against what the merge will build. This covers terraform_remote_state and Terragrunt dependency blocks. Between choudoufu estates it works the same way.
A value only known after the upstream applies, like a new network’s ID, can’t be planned. terragucci plans the reader again once its upstream has applied. choudoufu refuses to plan on it. A failed wave leaves the earlier waves applied and plans again on what’s there.
The detail

Most rows are backed by a smoke claim named on the locking page. The glossary defines wave, root and forge.
Prove it to yourself with your own agent
Read https://lex00.github.io/posts/tf-vendor-power-without-the-saas/
For each row of "What you'd pay a SaaS for", open the page listed for it under Sources and say whether it does what the row says.
For each row of "The detail", give three verdicts, each with a source link:
- terragucci: does the doc listed for it under Sources support the cell as written? Find the smoke claim behind it in https://github.com/INTENTIUS/terragucci (stack/smoke.sh, docs-site/src/data/smoke.json) and say whether its latest result passes.
- choudoufu: the same, in https://github.com/INTENTIUS/choudoufu (live/smoke/claims/).
- The industry, as of today: which Terraform state backends, TACOs and hosted Terraform platforms document the same capability? Quote their current docs and give the date you read them.
Mark a cell unverified when you can't find a source, rather than inferring one.
Then run the post's "Kill an apply" test if you have Docker: against a local AWS emulator, once with stock OpenTofu and once with choudoufu, and report how many VPCs exist after each re-run. Never run it against a real cloud account.Read more
- terragucci: locking and staleness
- choudoufu: concurrency
- Tofu tastes better with live markers
- choudoufu cuts terralith optimization time in half
Sources
What you’d pay a SaaS for:
- Plans on pull requests, applies after approval: One grouped plan note, then applies in waves
- Policy: Rego checks in the plan note, and recorded overrides
- Drift detection: Every root planned on a schedule, one grouped report
- Cost estimates: Infracost in the plan note, on your own key
- An audit trail: Every approval, apply and override as JSON lines in your bucket
- One view of every project: A page in your bucket with every project’s latest plan and drift
- Approvals in Slack or Teams: Through a relay you run in your own cloud
- Holding your credentials: Nobody else does: separate plan and apply roles over OIDC, in your CI
- Scale: 1,361 roots and 10,069 resources across 12 repos
- Moving off it: HCP Terraform, Scalr and OTF, Spacelift and env zero, Atlantis and OpenTaco
State and locking, and the detail:
- Resource-level locking: applies kept apart per root, a wave holds each resource its plan changes
- Disjoint changes apply in parallel: Different roots side by side, Inside one estate too
- Plans take no lock: Pull request plans and drift runs, Every plan
- A conflicting apply is refused, naming the other: A held root is refused with the holder named, a stale plan is refused, only when one of its own changes moved
- One saved plan to review: One grouped note for N plans, the approval bound to their digest
- Multi-state transaction: each wave plans after the one before it applied, a wave whose approved plans moved applies nothing, a failed wave plans again when it next runs, a reading estate’s apply is refused
- A killed apply: The state lock stays held until
terragucci unlock-statefrees it after an approval, a resource created after the last state write gets created twice, Nothing to release, the wave resumes under the same approval - Applies from outside the pipeline: The state lock still serializes them, Different resources both land; on one record, one lands and the other fails naming it
- Scoped permissions: Per state file and role, A role scoped by the estate tag
- Query your infrastructure: SQL over every run’s reports, a read-only MCP server, any cloud tool can list an estate by its tag
- Nothing mocked: a plan that reads
mock_outputsfails its wave, pull requests plan on the upstream’s planned outputs, a downstream estate plans on its upstream’s planned outputs - A plan walks only what the change touches: only the roots a change reaches are planned