AI-powered Terraform plan reviewer — verify your plan matches your intent before apply
Project description
tfrev — AI-Powered Terraform Plan Reviewer
Verify your Terraform plan matches your code intent before apply.
tfrev uses Claude AI to review your terraform plan output against your code changes, catching mismatches, security risks, and unexpected side effects before they hit production. Works with any Terraform provider — AWS, Azure, GCP, Kubernetes, and more.
Quick Start
# Install
pip install tfrev
# Set your API key
export ANTHROPIC_API_KEY=sk-ant-...
# Review a plan
terraform plan -out=tfplan
terraform show -json tfplan > plan.json
tfrev review --plan plan.json
Or use auto-detection:
terraform plan -out=tfplan
tfrev review --auto
To diff against a specific ref (e.g. last deployed SHA):
tfrev review --plan plan.json --base-ref abc1234
What It Catches
- Intent mismatches — plan does something the code change didn't intend
- Unexpected replacements — a tag change triggering a full resource destroy+create
- Security regressions — widened security groups, broadened IAM policies
- Blast radius — too many resources changing at once
- Drift — plan changes with no corresponding code change
- Policy violations — custom team rules defined in
.tfrev.yaml
CI/CD Integration
GitHub Actions
- name: AI Plan Review
uses: bishalOps/tfrev@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
post_comment: "true"
fail_on: high
GitLab CI
include:
- remote: 'https://raw.githubusercontent.com/bishalOps/tfrev/main/ci/gitlab/.gitlab-ci-template.yml'
Jenkins
Copy ci/jenkins/Jenkinsfile into your repo and add ANTHROPIC_API_KEY as a credential.
Any CI/CD
pip install tfrev
export ANTHROPIC_API_KEY=$YOUR_SECRET
tfrev review --auto --output markdown --fail-on high
Configuration
Create a .tfrev.yaml in your project root:
model: claude-sonnet-4-6
fail_on: high
policies:
- name: no-public-ingress
description: "Flag security group rules allowing 0.0.0.0/0"
severity: critical
sensitive_resources:
- aws_iam_* # AWS
- google_project_iam_* # GCP
- azurerm_key_vault* # Azure
See .tfrev.yaml.example for all options.
Sample Output
────────────────────────────────────────────────────────────────────────
❌ Verdict: FAIL Confidence: 95%
────────────────────────────────────────────────────────────────────────
This plan contains three significant security regressions introduced by the code diff:
SSH access widened from a private CIDR to 0.0.0.0/0, an RDS database marked
publicly_accessible=true, and an S3 bucket ACL changed from private to public-read. All
four resource creations are explained by code changes, but the security posture of the
planned infrastructure is critically degraded and should not be applied without
deliberate review and approval.
Resources: 4 reviewed | +4 create | ~0 update | -0 delete | -/+0 replace
ID Severity Category Resource Title
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
F001 CRITICAL security null_resource.web_sg SSH ingress opened to the entire internet (0.0.0.0/0)
F002 CRITICAL security null_resource.app_db RDS database instance set to publicly_accessible=true
F003 HIGH security null_resource.app_assets_bucket S3 bucket ACL changed from private to public-read
F004 MEDIUM best_practice null_resource.app_db deletion_protection is false on the database resource
F005 MEDIUM best_practice null_resource.app_db db_instance_class upsized from db.t3.small to db.t3.medium via variable default change
F006 LOW best_practice general All four resources lack lifecycle prevent_destroy protections
────────────────────────────────────────────────────────────────────────
[F001] ❗ CRITICAL — SSH ingress opened to the entire internet (0.0.0.0/0)
The code diff explicitly changes ingress_ssh_cidr from 10.0.0.0/8 (a private RFC-1918
range) to 0.0.0.0/0, exposing SSH (port 22) to all public IPs.
Code: main.tf (lines 18-19)
Plan: null_resource.web_sg (create)
Recommendation:
Revert ingress_ssh_cidr to a specific, restricted CIDR. Consider using AWS Systems
Manager Session Manager to eliminate SSH exposure entirely.
────────────────────────────────────────────────────────────────────────
[F002] ❗ CRITICAL — RDS database instance set to publicly_accessible=true
...
Output Formats
tfrev review --plan plan.json --output table # Terminal (default)
tfrev review --plan plan.json --output markdown # PR comments
tfrev review --plan plan.json --output json # Machine consumption
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Review passed |
| 1 | Review failed (findings at or above --fail-on severity) |
| 2 | Error (API failure, invalid input) |
Cost
Each review is a single Claude API call. Cost scales with the size of your plan and diff.
License
MIT
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 tfrev-1.0.1.tar.gz.
File metadata
- Download URL: tfrev-1.0.1.tar.gz
- Upload date:
- Size: 35.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30e593d7b6ebfc406ec01e34d11a73a7d4761abdfbed3ba1bf16d76feca50b41
|
|
| MD5 |
c8c4956cf420f1c6323ff7d1c193a56c
|
|
| BLAKE2b-256 |
29bc75fa8ae06c56c4ad8caf31265aafb17839ad07a21f899e8f9fdea1279851
|
Provenance
The following attestation bundles were made for tfrev-1.0.1.tar.gz:
Publisher:
publish.yml on bishalOps/tfrev
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tfrev-1.0.1.tar.gz -
Subject digest:
30e593d7b6ebfc406ec01e34d11a73a7d4761abdfbed3ba1bf16d76feca50b41 - Sigstore transparency entry: 1238140236
- Sigstore integration time:
-
Permalink:
bishalOps/tfrev@9ea77e8ecfecda083e0740d976641bd72df50855 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/bishalOps
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9ea77e8ecfecda083e0740d976641bd72df50855 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tfrev-1.0.1-py3-none-any.whl.
File metadata
- Download URL: tfrev-1.0.1-py3-none-any.whl
- Upload date:
- Size: 28.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb2874db0c3e6b6bdb8a48a6330ee71b583ad6b2e470c064ac7ef779e138f309
|
|
| MD5 |
8be644bca1267ee45d8e67a574af5319
|
|
| BLAKE2b-256 |
52675078020050ba73cfbed401b2350dadf7c5c1344860a97b35b0a7dfce526f
|
Provenance
The following attestation bundles were made for tfrev-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on bishalOps/tfrev
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tfrev-1.0.1-py3-none-any.whl -
Subject digest:
eb2874db0c3e6b6bdb8a48a6330ee71b583ad6b2e470c064ac7ef779e138f309 - Sigstore transparency entry: 1238140306
- Sigstore integration time:
-
Permalink:
bishalOps/tfrev@9ea77e8ecfecda083e0740d976641bd72df50855 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/bishalOps
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9ea77e8ecfecda083e0740d976641bd72df50855 -
Trigger Event:
push
-
Statement type: