Natural language → validated, secured, cost-estimated OpenTofu config
Project description
tofu-assist
Writing Terraform is slow. Reading terraform plan output is unreadable. tofu-assist fixes both.
Describe your infrastructure in plain English. Get validated, security-scanned, cost-estimated OpenTofu config — with a single approve step before anything touches your cloud.
$ tofu-assist "I need a k8s cluster with postgres in eu-west-1"
Provider: aws (eu-west-1)
Generating configuration...
✓ main.tf (47 lines)
✓ variables.tf (11 lines)
✓ outputs.tf (8 lines)
Security scan: ✓ no issues found
Running tofu plan...
SUMMARY
9 resources: 9 will be created.
Estimated cost: $187/month
ATTENTION REQUIRED
(none)
WHAT WILL BE BUILT
+ main (VPC)
+ 2x public (subnet)
+ 2x private (subnet)
+ main (EKS cluster)
+ main (EKS node group)
+ main (RDS instance)
...
Apply this? [y/N]
Install
Prerequisites
- OpenTofu (install guide) — the open-source Terraform fork
- Python 3.10+
- An API key for any OpenAI-compatible LLM (DeepSeek, OpenAI, Anthropic, OpenCode, etc.)
Quickstart
pip install tofu-assist
export TOFU_ASSIST_API_KEY=your_api_key
tofu-assist "I need a load balancer with two EC2 instances"
Optional dependencies
| Tool | Purpose | Install |
|---|---|---|
| Infracost | Cost estimation before apply | curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh |
| Checkov | Static security scanning | pip install checkov |
The pipeline degrades gracefully — missing tools are skipped with a note, never an error.
What it does
Three layers. One pipeline.
| Layer | What you get |
|---|---|
| Generate | Plain English → production-quality HCL. Security defaults baked in: encryption at rest, blocked public S3, no wildcard IAM, no 0.0.0.0/0 on sensitive ports. One retry if validation fails. |
| Verify | Static security scan (Checkov) catches bad defaults before plan. Plan explainer turns 500-line JSON into a 3-section summary. Cost estimate (Infracost) tells you the monthly bill before you approve. |
| Approve | Hard-stop on production resource destruction. Tag-only changes are silent. y/N gate with everything visible. |
Subcommands
tofu-assist explain — understand any codebase instantly
Point at any directory with .tf files and get a plain-English summary.
$ tofu-assist explain ./infra
Analyzing /home/user/infra...
──────────────────────────────────────────────────────────
CODEBASE EXPLANATION
──────────────────────────────────────────────────────────
OVERVIEW
A production EKS cluster with RDS Postgres in a custom VPC
across 3 AZs. Public-facing via ALB with WAF.
RESOURCES (12)
• main_vpc (aws_vpc)
VPC with 10.0.0.0/16 CIDR for all resources
• public_subnet_a (aws_subnet)
Public subnet in us-east-1a for load balancer
• ...
ARCHITECTURE
Internet → WAF → ALB → EKS (private subnets) → RDS (private subnets)
SECURITY NOTES
⚠ RDS is publicly accessible — consider restricting
⚠ Security group allows 0.0.0.0/0 on port 5432
COST IMPLICATIONS
💰 EKS cluster: ~$73/month base
💰 RDS db.r5.large (multi-AZ): ~$400/month
SUGGESTIONS
→ Add encryption at rest for RDS
→ Add lifecycle policies for S3 buckets
→ Tag all resources with Environment and Team
Options:
--detailed— deeper security and cost analysis--json— machine-readable JSON output
tofu-assist edit — modify existing config via natural language
Don't rewrite configs. Tell them what to change.
$ tofu-assist edit "add a read replica to the RDS instance"
Editing /home/user/infra...
Instruction: add a read replica to the RDS instance
Changes:
--- a/main.tf
+++ b/main.tf
@@ -45,6 +45,14 @@
skip_final_snapshot = true
}
+resource "aws_db_instance" "read_replica" {
+ replicate_source_db = aws_db_instance.main.identifier
+ instance_class = "db.r5.large"
+}
+
Apply these changes? [y/N] y
✓ Modified 1 file(s): main.tf
Backup saved to: ~/.tofu-assist/backups/
Next steps:
cd /home/user/infra && tofu plan # review the plan
tofu apply # apply changes
Options:
--dir— specify target directory--dry-run— preview changes without applying--yes/-y— skip approval prompt
How it works
You: "I need a k8s cluster with postgres"
│
▼
┌─────────────────┐
│ LLM generation │ System prompt enforces security defaults.
│ (DeepSeek/any) │ JSON envelope, no markdown parsing.
└────────┬────────┘
│ main.tf, variables.tf, outputs.tf
▼
┌─────────────────┐
│ Checkov scan │ Static analysis. CRITICAL findings surfaced.
│ (optional) │ Encryption, public access, wildcard IAM.
└────────┬────────┘
│
▼
┌─────────────────┐
│ tofu plan │ OpenTofu validates and produces plan JSON.
└────────┬────────┘
│
▼
┌─────────────────┐
│ explain layer │ SUMMARY + ATTENTION REQUIRED + WHAT WILL BE BUILT.
│ + Infracost │ Estimated cost injected inline.
└────────┬────────┘
│
▼
┌─────────────────┐
│ Approve? [y/N] │ Hard-stop on production resource destruction.
└─────────────────┘
Edit flow
You: "add a read replica to the RDS"
│
▼
┌─────────────────┐
│ Read existing │ All .tf files from target directory.
│ config files │ Hidden files and plan.json skipped.
└────────┬────────┘
│
▼
┌─────────────────┐
│ LLM edit │ System prompt preserves all unchanged
│ (DeepSeek/any) │ resources. Only modifies what the
└────────┬────────┘ instruction targets.
│
▼
┌─────────────────┐
│ Show diff │ Unified diff of changes across all files.
│ + tofu validate │ Validation with auto-retry on failure.
└────────┬────────┘
│
▼
┌─────────────────┐
│ Approve? [y/N] │ Backs up originals to ~/.tofu-assist/backups/.
│ │ Overwrites on approval. Dry-run available.
└─────────────────┘
Safety features
- Security defaults in the system prompt — encryption at rest, blocked public S3, no wildcard IAM, restricted security groups. The LLM generates secure config by default.
- Checkov static scan — catches bad defaults before
planruns. CRITICAL findings are always surfaced. Noise is swallowed. - Production risk detection — destroying
aws_db_instance.productionis a hard stop. Destroyingaws_subnet.mainis a warning. The classification weighs resource type AND naming patterns. - Alarming plan detection — 15+ deletions or high destroy ratio refuses auto-summary. Single production database destroy triggers hard stop.
- Tag-only filtering — tag changes are silent. The ATTENTION REQUIRED section stays trustworthy.
- Never blocks on tool failures — Infracost not installed? Shows "cost estimate unavailable." Checkov not installed? Skips scan. The pipeline degrades gracefully.
Files
~/.tofu-assist/
├── pending/ ← Generation lands here
│ └── 2024-01-15-143022/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── plan.json
└── applied/ ← Successful applies archived here
└── 2024-01-15-143045/
└── ...
Configuration
| Variable | Default | Purpose |
|---|---|---|
TOFU_ASSIST_API_KEY |
$DEEPSEEK_API_KEY |
LLM API key (required) |
TOFU_ASSIST_API_BASE |
https://api.deepseek.com/v1 |
OpenAI-compatible API endpoint |
TOFU_ASSIST_MODEL |
deepseek-chat |
Model name |
Provider examples
# DeepSeek (default)
export TOFU_ASSIST_API_KEY=sk-...
# OpenAI
export TOFU_ASSIST_API_KEY=sk-...
export TOFU_ASSIST_API_BASE=https://api.openai.com/v1
export TOFU_ASSIST_MODEL=gpt-4o
# Anthropic (via compatible proxy)
export TOFU_ASSIST_API_KEY=sk-ant-...
export TOFU_ASSIST_API_BASE=https://api.anthropic.com/v1
export TOFU_ASSIST_MODEL=claude-sonnet-4-20250514
# OpenCode Go
export TOFU_ASSIST_API_KEY=oc-...
export TOFU_ASSIST_API_BASE=https://api.opencode.ai/zen/go/v1
export TOFU_ASSIST_MODEL=deepseek-v4-flash
File structure
~/.tofu-assist/
├── pending/ ← Generated configs land here before approval
│ ├── 2024-01-15-143022/ ← Fresh generation
│ └── edit-2024-01-15-150000/ ← Edit preview
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ └── plan.json
├── applied/ ← Successfully applied configs archived here
│ └── 2024-01-15-143045/
└── backups/ ← Originals backed up before edit overwrites
└── 2024-01-15-150000/
Why?
Coding agents can generate Terraform. But they can't validate it, scan it for security issues, estimate what it'll cost, or stop you from destroying production. tofu-assist does all of that, plus lets you edit existing configs and explain any codebase — not just generate from scratch.
"Try generating a production EKS cluster with RDS in Claude Code. Now check: is the DB encrypted? Are the security groups locked down? Do you know what it'll cost? What happens if you run apply? Exactly."
Why OpenTofu
OpenTofu is the community fork of Terraform (Apache 2.0), created after HashiCorp's license change to BUSL. tofu-assist bets on OpenTofu — the ecosystem that's growing, not the one that changed the rules.
Contributing
See CONTRIBUTING.md for development setup, testing, and PR guidelines.
git clone https://github.com/tofu-assist/tofu-assist.git
cd tofu-assist
pip install -e ".[dev]"
python -m pytest -v
License
MIT
Project details
Release history Release notifications | RSS feed
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 tofu_assist-0.1.2.tar.gz.
File metadata
- Download URL: tofu_assist-0.1.2.tar.gz
- Upload date:
- Size: 35.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
065011963529de59cd84be1858a3684fc2da0b1f0a9522d24409d0b38aace480
|
|
| MD5 |
eb5ed06ed58fc5a87eca886ad0d783af
|
|
| BLAKE2b-256 |
92df63b82934c84827243cd7c968bd40376f83b78b897c5962622925255d9565
|
Provenance
The following attestation bundles were made for tofu_assist-0.1.2.tar.gz:
Publisher:
release.yml on tofu-assist/tofu-assist
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tofu_assist-0.1.2.tar.gz -
Subject digest:
065011963529de59cd84be1858a3684fc2da0b1f0a9522d24409d0b38aace480 - Sigstore transparency entry: 1625068594
- Sigstore integration time:
-
Permalink:
tofu-assist/tofu-assist@27eed233ce869e1f0b2fb6abfa56069f0b010c8d -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/tofu-assist
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@27eed233ce869e1f0b2fb6abfa56069f0b010c8d -
Trigger Event:
push
-
Statement type:
File details
Details for the file tofu_assist-0.1.2-py3-none-any.whl.
File metadata
- Download URL: tofu_assist-0.1.2-py3-none-any.whl
- Upload date:
- Size: 34.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 |
c67ee4e29d6ab92832445c2ef03ff7e4b53da0b0a5e82bb1eac633bd38d0b87a
|
|
| MD5 |
fc9849182d39ff82cddb521a5112ec54
|
|
| BLAKE2b-256 |
7ed1d9832ca7c51cf03308b33ce686aa46765ece984b797fd1f0fc2fde7903c6
|
Provenance
The following attestation bundles were made for tofu_assist-0.1.2-py3-none-any.whl:
Publisher:
release.yml on tofu-assist/tofu-assist
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tofu_assist-0.1.2-py3-none-any.whl -
Subject digest:
c67ee4e29d6ab92832445c2ef03ff7e4b53da0b0a5e82bb1eac633bd38d0b87a - Sigstore transparency entry: 1625068642
- Sigstore integration time:
-
Permalink:
tofu-assist/tofu-assist@27eed233ce869e1f0b2fb6abfa56069f0b010c8d -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/tofu-assist
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@27eed233ce869e1f0b2fb6abfa56069f0b010c8d -
Trigger Event:
push
-
Statement type: