Generating Terraform Documentation With AI and terraform-docs
terraform-docs gives you the tables; AI writes the prose nobody wants to. Pair them to ship module docs that explain the why, not just the variable names.
- #terraform
- #ai
- #documentation
- #modules
- #terraform-docs
I have written a lot of Terraform modules, and I have written almost no documentation for them. Not because I’m lazy — okay, partly because I’m lazy — but because the documentation that matters is the part terraform-docs can’t generate: why this module exists, when you’d reach for it, and the three landmines you’ll step on if you don’t read carefully. The variable tables practically write themselves. The reasoning doesn’t.
That gap is exactly where an AI assistant earns its keep. Think of it as a fast junior engineer who’ll happily draft the README you keep deferring. It reads your HCL, drafts the prose, and you edit. What it never does is touch your state or your cloud credentials — it’s a writer, not an operator.
Start with the part that’s already solved
terraform-docs is deterministic and excellent. Don’t ask an AI to reproduce it. Generate the canonical tables first:
terraform-docs markdown table --output-file README.md \
--output-mode inject ./modules/network
With injection mode, it edits between <!-- BEGIN_TF_DOCS --> and <!-- END_TF_DOCS --> markers and leaves the rest of your README alone. That boundary is the contract: the tool owns the tables, you (and your AI helper) own everything above them.
A minimal config keeps output stable across runs:
# .terraform-docs.yml
formatter: "markdown table"
sort:
enabled: true
by: required
output:
file: README.md
mode: inject
Hand the AI the inputs, not a blank page
The model writes better prose when it sees the same thing a human reviewer would. Give it three things: the variable definitions, the outputs, and the resource graph. You can dump them cheaply:
terraform-docs json ./modules/network > /tmp/iface.json
terraform graph | grep -v '\[label' > /tmp/graph.txt
Then prompt it along these lines: “Here is the public interface and resource graph for a Terraform module. Write a README introduction (3-4 paragraphs) covering what it provisions, who should use it, and the top operational gotchas. Do not reproduce the variable table — that’s generated. Flag anything you’re unsure about as a TODO rather than inventing it.”
That last sentence matters. Without it, models confidently describe behavior the code doesn’t have.
Make it explain the gotchas, not just the inputs
The highest-value paragraph in any module README is the warnings section. Ask explicitly:
“Based on this HCL, list the operational footguns: anything that forces resource replacement, anything with a hardcoded region or account assumption, any
prevent_destroylifecycle rule, and any input that silently changes cost.”
Feed it the actual resource blocks for this. A model reading a real aws_db_instance will reliably notice that changing engine_version across a major version triggers replacement, or that allocated_storage only grows. Those are the lines that turn a README from decoration into a safety device.
Pro Tip: Ask the model to cite the exact line or block behind each gotcha it lists. If it can’t point to the HCL, the warning is a hallucination and you delete it.
Generate usage examples that actually parse
Models are good at writing example module blocks, and bad at knowing which arguments are required. Close that loop with the toolchain instead of trusting the draft:
# After the AI drafts examples/basic/main.tf
terraform -chdir=examples/basic init -backend=false
terraform -chdir=examples/basic validate
-backend=false keeps this hermetic — no remote state, no credentials, just a syntax-and-schema check. If validate passes, the example is structurally sound. If it fails, paste the error back to the model and let it fix the block. This is the whole workflow in miniature: the AI proposes, the deterministic tooling verifies, and a human decides what merges.
Keep docs honest with a CI gate
The fastest way for docs to rot is to let code drift past them. Wire terraform-docs into CI so a stale table fails the build:
# .github/workflows/docs.yml (excerpt)
- name: Check docs are current
run: |
terraform-docs markdown table --output-mode inject \
--output-file README.md ./modules/network
git diff --exit-code README.md
This only polices the generated tables — the AI-written prose is reviewed by humans in the PR, where it belongs. The split is deliberate: machines enforce the mechanical part, people own the judgment part.
Where to point the model, and where not to
Some practical guardrails I’ve settled on:
- Run the drafting in a chat workspace, not against your apply pipeline. The prompt workspace keeps your module-doc prompts reusable across modules.
- The AI gets read access to HCL and
terraform-docsoutput. It never gets state files,terraform.tfstate, or cloud credentials. Documentation generation has zero reason to authenticate to anything. - A human reviews every generated paragraph the same way they’d review a plan. Plausible-sounding prose about resources you don’t have is its own kind of drift.
If you want consistent prompts for this, I keep mine in a reusable set; you can browse the prompt library or grab the Terraform prompt pack which has module-documentation prompts tuned for exactly this split between generated tables and written reasoning.
Document the examples directory too, not just the root
Most module READMEs stop at the root, but the examples/ directory is where new users actually start — they copy the simplest example and adapt it. Those examples deserve their own short explanations, and they’re another place the AI’s drafting plus toolchain verification pays off. For each example, ask the model to write a one-paragraph “what this shows and when to use it” intro, grounded in the example’s main.tf:
“Here is
examples/multi-az/main.tf. Write a two-sentence description for a docs index: what scenario it demonstrates and what makes it different from the basic example. Don’t restate every argument.”
Then keep the examples honest the same way you keep the root honest — validate each one with no backend so a copy-paste user never lands on a broken starting point:
for d in examples/*/; do
terraform -chdir="$d" init -backend=false -input=false
terraform -chdir="$d" validate || echo "BROKEN: $d"
done
A loop like that in CI means every example always parses against the current module interface. The AI writes the human-facing description; the loop guarantees the code under it actually works. That’s the same machine-verifies-the-mechanical, human-owns-the-judgment split applied one level down — and it’s the difference between an examples directory that onboards people and one that frustrates them.
A note on keeping prose and code in sync
The subtle failure with AI-written prose is that it ages out of sync with the code while the generated tables stay current. A variable gets renamed, terraform-docs updates the table in CI, but the introduction still describes the old behavior. Guard against it by keeping the prose short and structural — describe purpose and gotchas, which change slowly, rather than enumerating arguments, which change every PR. When the prose only talks about things that rarely move, it rots far more slowly, and the human reviewer catches the rare case where it does.
Conclusion
The trick to documenting Terraform isn’t finding a tool that writes it all for you — it’s splitting the job. terraform-docs owns the mechanical tables and CI keeps them honest. The AI drafts the prose a human would otherwise never get around to, grounded in your actual HCL and verified by validate. You stay the editor and the only one with the keys. Do that, and your modules finally get the READMEs they deserved all along. More patterns live over in the Terraform guides.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.