Skip to content

terragucci

llms.txtlists every page for an agent

TERRAGUCCI

Sophisticated automation for Terraform

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

Proven by recorded checks: 224 for plain roots, 274 on OpenTofu and 13 on GitHub. Each count covers one choice. Validation

First step

Get your first plan note

Then read terragucci for Terraform or OpenTofu roots: what you can count on, and the proof.

With the 0.4.7 release, every approval is one command, terragucci approve. 0.4.5 added SQL over the reports bucket, resuming a killed choudoufu wave from its records, and imports from HCP Terraform, Scalr, Spacelift and env zero. Watch the launch party from the Rome launch.

terragucci reads your roots and runs your binary. Code, state backend and provider pins stay as you have them.

Where it runs What you set Page
GitHub, GitLab or Forgejo CI nothing: init reads the forge from the origin remote and writes its pipeline format Per forge
S3, GCS or Azure Blob, for your state and the reports oidc for keyless cloud identities, reports.bucket for the reports Credentials, Keep reports in a bucket

Every plan, apply and drift run sends one OpenTelemetry trace and the pipeline’s metrics over OTLP to your collector.

One tf-plan run's trace in Grafana's Explore, read from Tempo: the terragucci tf-plan stage span, wave 2, the root span for envs/dev/orders, the tofu init and plan spans under it, and OpenTofu's own spans inside themOne tf-plan run's trace in Grafana's Explore, read from Tempo: the terragucci tf-plan stage span, wave 2, the root span for envs/dev/orders, the tofu init and plan spans under it, and OpenTofu's own spans inside them
The trace shows Page
The stage, then a span per wave and per root, with digests, change counts and status Send traces and metrics
The binary’s own spans inside each root: OpenTofu’s resources, and with choudoufu its provider calls and state lock waits Traces and metrics
Metrics and the Grafana dashboards init writes with dashboards: true The metrics

init writes the pipeline for these stages in your forge’s own format. Architecture.

  1. tf-checkevery push

    Format and validate, before anything plans.

  2. tf-planevery pull request

    Only the roots the change touches, summarised in one note.

  3. tf-applyon merge, or before it

    Wave by wave; by default a wave that destroys or replaces waits for its approval.

  4. tf-drifton a schedule

    Every root planned against live state, drift reported grouped.

  5. tf-publishon merge, with modules set

    Each changed module published under its next version, as an OCI artifact or a git tag.

  6. tf-rollouteach time you run it

    One pull request per wave, moving the pins to the new version.

A change goes out a few roots at a time, starting with the canary roots. By default a wave that destroys or replaces something waits for an approval, which covers exactly the plans it was shown.

  1. wave 13 rootsset:4f1a…c09eappliedthe canary roots, approved by alex
  2. wave 297 rootsset:b77d…12a4waitingnpx terragucci approve wave-2

refusedA plan in wave 2 changed after the approval, so wave 2 applied nothing and named both digests.

The report lists each wave with the digest of its plans and links the approval record that let it go out. Waves and approvals.

terraguccicommented on #482 · bump modules/iam to 1.4.0

200 roots planned. 3 groups, 1 destroy.

180identical change ~ aws_iam_role.app tags
15the same, plus -/+ aws_lambda_function.worker
5different changes, listed one by one below
  # aws_iam_role.app will be updated in-place
~   resource "aws_iam_role" "app" {
~       tags = {
-           "team" = "payments"
+           "team" = "platform"
        }
        # (12 unchanged attributes hidden)
    }
prod-eu/db: Plan: 0 to add, 1 to change, 1 to destroy.

The root's whole plan, as the binary printed it.

destroyprod-eu/db · aws_db_instance.main

WaveRootsApproval
13not-requested
297not-requested
3100not-requested

Roots taking the same change share one diff that shows each value before and after. Every destroy is named. Each root’s whole plan sits collapsed below, and the full report links each root’s plan.

The largest run of the scale bench planned and applied 10,069 resources in 1,361 roots across 12 repos, governed by one control repo: the control repo's pipeline pull requests opened, every root created, then a change to all of them planned and applied, in 120 minutes on a build of terragucci just after 0.4.1.

You get Turn it on Page
Each changed module released after the apply, as a git tag or an OCI artifact, and with attest signed with cosign modules.publish, modules.attest Publish your modules
A new version rolled out to every repo that pins the module, one pull request per wave terragucci rollout, or rollouts: for a scheduled job Roll out a new module version

choudoufu is the OpenTofu fork from the team behind terragucci. Set binary: choudoufu (set it up) and the pipeline also gets:

You get Page
A live check in tf-check on every push, before the apply waves, with no cloud credentials Check
One record per resource in an S3 backend you own, each write conditional, with no lock table or database to run; the state file is a cache Record writes
How long a wave waited for a state lock, and how many tries it took State lock waits
Which provider calls were slow, and the resource each was for What the report lists
Timings summed by resource type, so a large estate’s report stays readable What the report lists
Changes to different resources of one estate apply at the same time; an overlapping change waits, or is refused, before it reaches the cloud; a killed apply leaves nothing to release Locking with choudoufu
A role scoped to one estate by an IAM condition on the tofu-estate tag, refused on another estate’s resources Live resource markers

These are plain CI jobs in your pipeline.

On a pull request How you start it Forges Page
One grouped plan note and a terragucci/plan status open or push to the pull request all three Get your first plan note
Tips and policy results on the plan on by default with the plan; tips: false turns tips off, policy adds checks all three Tips, Policy
A re-plan comment /terragucci plan [root] all three; GitLab through the comments schedule Re-plan from a comment
Root locks by comment comment /terragucci lock or /terragucci unlock GitHub and Forgejo; GitLab with apply.when: pull-request and comments: set Locks
Root locks from the first plan locks: plan GitHub and Forgejo Locks
Apply before merge, then merge after the last wave apply.when: pull-request, then comment /terragucci apply [wave-<n>] GitHub, Forgejo, and GitLab with comments: set Apply before merge
An approval for a waiting wave approval: ledger, pr-review or sealed; run terragucci approve all three Approve a waiting wave
A recorded policy override a listed person runs terragucci override all three Override a policy denial
Comment commands on GitLab comments: sets the schedule that answers merge request notes GitLab Re-plan from a comment

Only these four features run a model. Each is off until you set it up and needs a model API key in your forge’s secrets.

Feature Turn it on Forges Page
Comment /terragucci agent <ask> and an agent commits the change to the pull request agent.comment in terragucci.yml GitHub and Forgejo Have an agent change a pull request
When drift opens the drift issue, an agent changes the code to match what is live, in a pull request agent.drift in terragucci.yml GitHub and Forgejo Have an agent fix drift
A note on each pull request comparing its description with its plan: risk, mismatches, questions review.agent in terragucci.yml all three; GitLab through the comments schedule Have a model review a pull request
A summary of what moved in a refused wave add the explain-refusal job under own_jobs all three Have an agent summarize a refused wave

A coding agent at your desk reads the estate (down to a root’s last apply), the audit trail and the DORA figures through terragucci mcp, a read-only MCP server that runs no model (Read the estate over MCP).

Guard What it means
Plan and apply use separate roles oidc takes one identity for plan and one for apply, and terragucci rejects the same role for both
The plan job cannot apply it runs the pull request’s code with the read-only plan role and never gets the apply role; under approval: sealed an approval also needs a signer’s key, which no job holds
A changed plan is refused a gated wave whose plans moved after the approval applies nothing and names both digests

The threat model lists what each job can reach on each forge.

What terragucci leaves to your forge and your cloud, and what it does not support.

Not hereWhy, and what you use instead
Bitbucket and Azure DevOpsinit writes pipelines for GitHub, GitLab and Forgejo only. (more)
Accounts, sign-in and roles of its ownYour forge decides who signs in and approves, and your cloud IAM decides what each job reaches. (more)
A hosted web UIRuns show on your forge's run pages and on the estate page in your bucket. (more)
A server or database to runEvery job runs in your CI and writes to your git and your bucket. (more)

Recorded checks show what is proven on each tool and forge (validation). Apache-2.0.

Add terragucci to a repo has the same steps by hand. Or paste this into Claude Code, Codex or Cursor in your repository. The agent page says what the agent does. It never applies and never approves.

Hand the setup to your coding agentOr set up by hand: install terragucci and run init, as the getting started page shows.
Show the whole prompt
Set up terragucci in this repository.
Read https://intentius.io/terragucci/llms.txt first, then
https://intentius.io/terragucci/getting-started/agents/ and follow it.
Open a pull request with the result.
Never apply, approve (a pull request review or `terragucci approve`), override a policy denial (`terragucci override`), use `--mode apply`, or merge; never touch `.chant/allowed_signers` or `chant/lifecycle`.

Then the guides cover tasks and the reference the details; the concepts and the glossary explain the reasons and the terms. terragucci is built on chant, and SQL Yodeler brings ClickHouse and Postgres schemas through the same approvals.

terragucci

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.