Terraform or OpenTofu roots
llms.txtlists every page for an agent
Directories of .tf files with their own state.
Works
- init finds every root and writes the pipeline for your forge
- Each root runs its own pinned Terraform or OpenTofu version
- Roots that read each other through terraform_remote_state apply in waves, in order
Differs
Nothing beyond what the other pages describe.
On Terraform, choudoufu, GitLab
On Terraform
- Two overlapping pushes to one root can fail the newer apply with "Saved plan is stale"; run it again and it plans again.
On choudoufu
- terragucci does not read a root's required_version as a choudoufu release.
On GitLab
- Comment commands answer on a schedule, since a merge request note starts no pipeline.
- Roots lock on /terragucci apply or /terragucci lock, not at the first plan.
- The agent comment and drift fixes are GitHub and Forgejo only.
First step
Proof
OpenTofu, on Forgejo
- Plan and reviewPlan and review, OpenTofu42 checks, all proven.
- tf-check fails an unformatted root and names the file
- only the roots a change touches are planned
- one note groups many plans
- Approve and applyApprove and apply, OpenTofu51 checks, all proven.
- each wave goes out only once approved
- a wave whose plans changed after approval applies nothing
- under approval: sealed a wave counts only an approval sealed by a key the signers file lists
- Locks and safetyLocks and safety, OpenTofu28 checks, all proven.
- two pushes to main apply one after the other, and the commit carries one terragucci/apply status
- a new upstream and its dependent merge together and apply in order, so no mock reaches real state
- a second pull request that reaches a root another open pull request has applied is refused with the root and the holder named, and applies once the first is unlocked with /terragucci unlock
- PolicyPolicy, OpenTofu16 checks, all proven.
- an opt-in policy denies a plan, fails the root in tf-plan, and names the violation
- a tf-apply wave whose plan the policy denies applies nothing, and its report keeps the changes of the denied root with the denial and the warnings
- a tf-apply wave gives the policy the risk the review workflow of the default branch kept as its artifact for the head of the merged pull request as input.review; the edited review job of the pull request itself keeping risk low and a forged low-risk note posted with the pipeline token change nothing, and a policy that denies risk high stops the wave
- DriftDrift, OpenTofu10 checks, all proven.
- drift is reported by root
- drift is reported by unit in a Terragrunt repo, with the same tracking issue
- drift on a literal becomes a pull request with the live value, and import blocks for what is unmanaged
- Chat and notifyChat and notify, OpenTofu6 checks, all proven.
- with notify naming a Slack and a Teams webhook secret and approval: pr-review, a wave of a merged pull request that waits posts the wave, its root, the digest, the approve command, the run and a link to review the pull request to each, and once that review lands the next run applies it
- with notify naming a generic webhook and its key, a wave that waits posts a terragucci.notify/v1 event signed with HMAC-SHA256 over its body, carrying the outcome, digest and approve command
- a click on the Approve button of the Slack message of a waiting wave, signed with the signing secret of the app, reaches the relay, which maps the Slack user to their principal in the signers file, records the approval of that digest as them and says so in the thread; the resume workflow then applies the wave
- Reports and visibilityReports and visibility, OpenTofu41 checks, all proven.
- the report is JSON and HTML, and links every root to its full plan
- each plan run is one trace, with a span per root and the binary spans inside it
- the metrics of a plan run reach Prometheus with the counts in its report
- ModulesModules, OpenTofu13 checks, all proven.
- a module version rolls out one pull request per wave
- changed modules are published at a new version
- with modules.attest each release is signed, attested and recorded in the release ledger with its tag
- State and migrationState and migration, OpenTofu20 checks, all proven.
- each Atmos instance plans and applies in the Terraform workspace Atmos names for it, never default: the instances of one component in two stacks keep their own states, and plan no change after the apply
- a root whose state is in a versioned S3 bucket applies twice, and the estate page lists both state version ids newest first, each one the bucket holds, and no state content
- terragucci state export records a request, waits for an approval by someone else, then writes the state version on the machine of the person who asked, recorded on chant/lifecycle and in the audit trail, with no state in the bucket
- Agents and pull request environmentsAgents and pull request environments, OpenTofu10 checks, all proven.
- a /terragucci agent comment pushes the commit of the stand-in agent to the branch of the pull request, which re-plans it and is linked in the reply, and a forbidden path, a non-writer and a fork push nothing
- with review.agent on, the review workflow of the default branch runs on pull_request_target after the plan, and its review job runs a stand-in reviewer on the pull request, its plan and the instructions of the default branch, with the key of the model and no forge token, and the note it posts flags a destroy the description does not mention and approves nothing
- with respond.description: check the plan job flags a destroy the pull request description leaves out, at the top of the note and in the report, and writes intent.json
- Setup and runtimeSetup and runtime, OpenTofu39 checks, all proven.
- the example boots and deploys locally
- with no more than a drift schedule and the canary wave in terragucci.yml, init writes the same pipeline
- a control repo opens one pull request per project that changes, and the merged pipeline applies
- proven passes, and fails with the feature cut out
Every check runs on OpenTofu on Forgejo. Runs on Terraform, choudoufu and github.com are expensive, so they re-run only the checks where the binary or forge changes what happens.
Open a cell for the checks behind it. Recorded: example checks, last full run Oct 8, 2026; per-forge checks Oct 7 to Oct 9, 2026; github.com Oct 10, 2026.
You can count on
- A plan note on every pull request
- Gated applies of the plans you approved
- No overlapping or stale applies
- Re-plan from a comment
- Scheduled drift checks
- OIDC roles, one to plan, one to apply
- Policy on every plan
- An audit trail in your bucket
- Secrets kept out of notes and logs
- Your state backend, as is
- Your own runners
- Your forge's sign-in and permissions
Then read
These docs count page views and clicks with PostHog. They set no cookies, store nothing in your browser, and send nothing when your browser asks not to be tracked.