A drop-in replacement for terraform plan and terraform apply that replaces Terraform's verbose output with a clean, readable diff.
Summary table — every changed resource at a glance:
Changes to be applied
──────────────────────────────────────────────────────────────────────────
Type Name Action
──────────────────────────────────────────────────────────────────────────
+ aws_s3_bucket my_bucket create
~ aws_instance web update
± aws_db_instance postgres replace
- aws_security_group old destroy
──────────────────────────────────────────────────────────────────────────
2 to add · 1 to change · 1 to replace · 1 to destroy
Per-resource panels — only the attributes that actually changed, with old → new values. Nested objects and arrays are flattened to dot-paths. JSON-encoded strings are decoded and diffed internally:
┌─ update aws_scheduler_schedule.my_job ──────────────────────────────
│ schedule_expression "rate(1 hour)" → "rate(2 hours)"
│ target.0.ecs_parameters.0.task_definition_arn
│ "...task:4" → "...task:5"
│ target.0.input.containerOverrides.0.command
│ [..., "100000000"] → [..., "1000"]
│ (10 unchanged attribute(s) hidden)
└───────────────────────────────────────────────────────────────────────
┌─ replace aws_db_instance.postgres ─────────────────────────────────
│ engine_version "13.4" → "15.2"
│ instance_class "db.t3.micro" → "db.t3.medium"
│ (2 unchanged attribute(s) hidden)
└───────────────────────────────────────────────────────────────────────
terraformbinary available in$PATH
brew install antoniocali/tap/terafromgo install github.com/antoniodavide/terafrom@latestDownload the latest release for your platform from the GitHub Releases page, extract the archive, and place the terafrom binary somewhere on your $PATH.
Show the diff for the current directory — runs terraform init automatically if needed:
terafrom# Specific directory
terafrom --dir ./infra
# Show unchanged attributes too
terafrom --show-all
# Only the summary table, no per-resource panels
terafrom --compact
# Load an existing plan file instead of running terraform plan
terafrom --plan-file ./my.tfplan
# Pass extra arguments through to terraform plan
terafrom -- -var-file=prod.tfvars -target=aws_s3_bucket.dataPlan, show the diff, then apply in one step. Terraform's own stdout is suppressed to avoid duplicate output — only errors and real progress come through:
terafrom applyterafrom apply --dir ./infra
terafrom apply -- -var-file=prod.tfvarsterafrom works transparently with any backend that stores state remotely (S3, GCS, Azure Blob Storage, HTTP, Consul, PostgreSQL, …). Terraform fetches the remote state itself during plan — no extra configuration needed.
If .terraform/ is absent, terafrom runs terraform init automatically before planning. Use --init to force a re-init (e.g. after changing the backend config or provider versions), or --no-init to skip it entirely.
Set the relevant environment variables before running terafrom — they are inherited by the terraform subprocess:
# AWS (S3 backend)
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1
terafrom --dir ./infra
# GCP (GCS backend)
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
terafrom --dir ./infra
# Azure (azurerm backend)
export ARM_CLIENT_ID=... ARM_CLIENT_SECRET=... ARM_TENANT_ID=... ARM_SUBSCRIPTION_ID=...
terafrom --dir ./infraIf your .tf files use a partial backend configuration, pass the missing values via --backend-config — forwarded to terraform init -backend-config=...:
terafrom \
--backend-config bucket=my-tfstate-bucket \
--backend-config region=eu-west-1 \
--backend-config dynamodb_table=tf-locks \
--dir ./infra
# Switch state key per environment without touching .tf files
terafrom --init --backend-config "key=envs/prod/terraform.tfstate" --dir ./infra| Flag | Default | Description |
|---|---|---|
--plan-file |
— | Load an existing .tfplan or JSON plan file |
--dir |
. |
Terraform working directory |
--init |
false |
Force terraform init before planning |
--no-init |
false |
Never run terraform init automatically |
--init-arg |
— | Extra argument forwarded to terraform init (repeatable) |
--backend-config |
— | Backend config key=value forwarded to terraform init (repeatable) |
--show-all |
false |
Show unchanged attributes inside resource panels |
--compact |
false |
Summary table only, no per-resource panels |
--no-color |
false |
Disable ANSI colour output |
--verbose |
false |
Also print the raw terraform plan output before the terafrom diff |
--terraform-args |
— | Extra argument forwarded to terraform plan (repeatable) |
| Flag | Default | Description |
|---|---|---|
--dir |
. |
Terraform working directory |
--init |
false |
Force terraform init before applying |
--no-init |
false |
Never run terraform init automatically |
--init-arg |
— | Extra argument forwarded to terraform init (repeatable) |
--backend-config |
— | Backend config key=value forwarded to terraform init (repeatable) |
--show-all |
false |
Show unchanged attributes in the diff output |
--no-color |
false |
Disable ANSI colour output |
--terraform-args |
— | Extra argument forwarded to terraform plan/apply (repeatable) |
| Symbol | Colour | Meaning |
|---|---|---|
+ |
Green | Resource/attribute added |
- |
Red | Resource/attribute destroyed |
~ |
Yellow | Resource/attribute modified |
± |
Magenta | Resource replaced (destroy + create) |
> |
Cyan | Data source read |
Requirements: Go 1.21+, terraform in $PATH.
git clone https://github.com/antoniodavide/terafrom
cd terafrom| Command | Description |
|---|---|
make build |
Compile the binary to ./terafrom |
make install |
Install to $GOPATH/bin |
make test |
Run all tests |
make test-verbose |
Run tests with verbose output |
make lint |
Run go vet |
make fmt |
Format source with go fmt |
make tidy |
Tidy and verify go.mod / go.sum |
make clean |
Remove build artefacts |
terafrom/
├── main.go # Entry point
├── cmd/terafrom/
│ ├── root.go # terafrom (plan) command and flags
│ └── apply.go # terafrom apply subcommand
└── internal/
├── backend/
│ └── backend.go # Backend type detection (.terraform/terraform.tfstate)
├── plan/
│ ├── types.go # Plan JSON structs + ActionType helpers
│ └── loader.go # File loader, auto-init, terraform runner
├── diff/
│ └── diff.go # Attribute diff engine (flattening, JSON decoding)
├── render/
│ └── render.go # Summary table + per-resource panel renderer
└── version/
└── version.go # Build-time version, commit, and date (set via ldflags)