Open-source CLI for explaining Terraform code and plans in human-readable form by BuildNAutomate.
Project description
tfexplain
tfexplain is an open-source CLI for explaining Terraform code, saved Terraform plans, Terraform JSON plans, and piped Terraform plan text.
Author: Vijay Daswani
Company: Build & Automate
Website: buildnautomate.com
Package: bna-tools/tfexplain
Community: Join the Build & Automate Slack
By default, tfexplain is deterministic and dependency-free. It does not call AI services, does not run terraform apply, and does not send code or plan contents anywhere. AI-assisted output is available only when you explicitly pass --ai.
Demo
Why tfexplain?
Terraform plans are powerful but noisy. tfexplain turns Terraform code and plan output into readable summaries for engineers, reviewers, and CI/CD pipelines.
Safety & Privacy
- No AI calls unless
--aiis passed. - No
terraform apply. - No cloud changes.
- Plan/code analysis runs locally.
- Secrets are redacted before AI requests.
Install for Development
Install from PyPI:
pip install bna-tfexplain
Then run:
tfexplain --help
The PyPI package name is bna-tfexplain; the CLI command remains tfexplain.
Standalone binary bundles for Linux, macOS, and Windows are attached to GitHub releases.
For local development:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e .
You can also run it without installing:
PYTHONPATH=src python3 -m tfexplain --help
Explain a Terraform Plan
Pipe-friendly local workflow:
terraform plan -no-color | tfexplain
Raw plan text gives an action/resource summary. For richer field-level details, use a saved plan or Terraform JSON.
Terragrunt works the same way for a single module:
terragrunt plan -no-color | tfexplain
For richer details with Terragrunt:
terragrunt plan -out=tfplan
terragrunt show -json tfplan | tfexplain plan -
terraform plan -out=tfplan
tfexplain plan tfplan
You can also pass Terraform JSON if you prefer to generate it yourself:
terraform show -json tfplan > plan.json
tfexplain plan plan.json
Or stream Terraform JSON through stdin:
terraform show -json tfplan | tfexplain plan -
Passing a saved binary plan file requires the terraform executable to be installed because tfexplain converts it locally with terraform show -json.
This also works:
terraform plan -out=tfplan
terraform show -json tfplan | tfexplain plan -
Useful options:
tfexplain plan plan.json --format markdown --output summary.md
tfexplain plan tfplan --group-by risk --show-fields
tfexplain plan tfplan --fail-on delete,replace,high
Explain Terraform Code
tfexplain code .
tfexplain code ./modules/network --format json
The code scanner reports providers, modules, resources, variables, outputs, backend settings, README/examples presence, variable descriptions, validation blocks, and high-attention resource types.
Explain Code and Plan Together
tfexplain explain --code . --plan plan.json --format markdown
Review, Docs, Graph, and Init
Generate a PR-oriented review summary:
tfexplain review --code . --plan tfplan --format markdown
tfexplain review --code . --plan tfplan --format github
tfexplain review --plan plan.json --fail-on delete,replace,high
Generate module documentation:
tfexplain docs . --output TERRAFORM.md
tfexplain docs . --format json
Generate a lightweight graph:
tfexplain graph . --format text
tfexplain graph . --format ascii
tfexplain graph . --format mermaid
tfexplain graph . --format dot
Create a local config file:
tfexplain init
tfexplain init --force
Samples
Sample Terraform code and plan fixtures live in samples/.
tfexplain code samples/terraform-code/aws-webapp
tfexplain code samples/terraform-code/local-pipe-plan
tfexplain plan samples/plans/02-aws-rds-replace.json --show-fields
tfexplain explain --code samples/terraform-code/azurerm-aks --plan samples/plans/03-azurerm-aks-update.json --format markdown
To test the exact pipe workflow with no cloud or Kubernetes provider:
cd samples/terraform-code/local-pipe-plan
terraform init -backend=false
terraform plan -no-color | PYTHONPATH=../../../src python3 -m tfexplain
The plan fixtures cover AWS, AzureRM, Google, Kubernetes, Helm, Cloudflare, Datadog, Random, TLS, and Local providers across create, update, delete, replace, no-op, and module-addressed changes.
To generate real local .tfplan samples:
./samples/tfplans/generate.sh
tfexplain plan samples/tfplans/generated/terraform-data/create.tfplan
tfexplain plan samples/tfplans/generated/terraform-data/update-replace.tfplan --show-fields
GitHub Action Example
name: tfexplain
on:
pull_request:
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Install tfexplain
run: |
python -m pip install -e .
- name: Terraform plan
run: |
terraform init
terraform plan -out=tfplan
- name: Generate tfexplain PR comment
run: |
tfexplain review --code . --plan tfplan --format github > tfexplain-review.md
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('tfexplain-review.md', 'utf8');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
Commands
tfexplain plan <plan.json|tfplan|->
terraform plan -no-color | tfexplain
tfexplain code <directory>
tfexplain explain --code <directory> --plan <plan.json|tfplan|->
tfexplain review --code <directory> --plan <plan.json|tfplan|->
tfexplain docs <directory>
tfexplain graph <directory>
tfexplain init [directory]
tfexplain risk <plan.json|tfplan|->
tfexplain version
AI Mode
AI output appends a generated explanation to the deterministic local analysis.
OpenAI:
export OPENAI_API_KEY=...
tfexplain plan tfplan --ai --provider openai
tfexplain code . --ai --provider openai --model gpt-4o-mini
Claude:
export ANTHROPIC_API_KEY=...
tfexplain review --code . --plan tfplan --ai --provider claude
Azure OpenAI:
export AZURE_OPENAI_API_KEY=...
export AZURE_OPENAI_ENDPOINT=https://example.openai.azure.com
tfexplain plan tfplan --ai --provider azure-openai --model <deployment-name>
Ollama:
ollama serve
tfexplain code . --ai --provider ollama --model llama3.1
Supported providers are openai, claude, azure-openai, and ollama. For JSON output, AI content is added under an ai object.
Roadmap
- GitHub PR comment mode
- Azure DevOps summary output
- More provider-aware risk rules
- HTML report
- SARIF output
- Homebrew install
Test
python3 -m unittest discover -s tests
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bna_tfexplain-0.1.2.tar.gz.
File metadata
- Download URL: bna_tfexplain-0.1.2.tar.gz
- Upload date:
- Size: 32.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2779c200386e174351d196e78f40f4b32eca8a65540353fedbab6640546c60a
|
|
| MD5 |
c7d5229a7198cd1670b6260b5dce32c3
|
|
| BLAKE2b-256 |
d70d8b460aab0101486b8822b21316ce1744fda48e5916e5e83354976c1e2bf0
|
Provenance
The following attestation bundles were made for bna_tfexplain-0.1.2.tar.gz:
Publisher:
release.yml on Vijaydaswani/tfexplain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bna_tfexplain-0.1.2.tar.gz -
Subject digest:
c2779c200386e174351d196e78f40f4b32eca8a65540353fedbab6640546c60a - Sigstore transparency entry: 2083062974
- Sigstore integration time:
-
Permalink:
Vijaydaswani/tfexplain@cc0d4b600904fe3b43e128676b1bf6e692055d8b -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/Vijaydaswani
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cc0d4b600904fe3b43e128676b1bf6e692055d8b -
Trigger Event:
push
-
Statement type:
File details
Details for the file bna_tfexplain-0.1.2-py3-none-any.whl.
File metadata
- Download URL: bna_tfexplain-0.1.2-py3-none-any.whl
- Upload date:
- Size: 30.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2fc8a539127eb1b4bb7cd44ec27c337c77d2029a02724fc9106c5d00ead8666
|
|
| MD5 |
20772826c1c71d3b6ea2c75d56eb2844
|
|
| BLAKE2b-256 |
9223c7d502d04ff04b079ebab3e18c75fdc8fa6360d392706716e99a07dc4249
|
Provenance
The following attestation bundles were made for bna_tfexplain-0.1.2-py3-none-any.whl:
Publisher:
release.yml on Vijaydaswani/tfexplain
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bna_tfexplain-0.1.2-py3-none-any.whl -
Subject digest:
e2fc8a539127eb1b4bb7cd44ec27c337c77d2029a02724fc9106c5d00ead8666 - Sigstore transparency entry: 2083062978
- Sigstore integration time:
-
Permalink:
Vijaydaswani/tfexplain@cc0d4b600904fe3b43e128676b1bf6e692055d8b -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/Vijaydaswani
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cc0d4b600904fe3b43e128676b1bf6e692055d8b -
Trigger Event:
push
-
Statement type: