Releases: patrickchugh/terravision
Release list
v0.42.0 — OpenTofu Support, Customisable Rendering & Resource Grouping
Highlights
OpenTofu Support (#199)
TerraVision now works with OpenTofu as a drop-in alternative to Terraform. Use the new --engine flag to select the infrastructure binary:
# Autodetect (default): prefers terraform, falls back to tofu
terravision draw --source ./infra
# Force OpenTofu
terravision draw --source ./infra --engine tofu
# Or set via environment variable
export TERRAVISION_ENGINE=tofuAvailable on draw, visualise, and graphdata commands. Both engines must be v1.x.
Customisable Font & Icon Sizes (#192, #198)
New CLI options give you control over diagram rendering:
--fontsize <pt>— set label font size (default 12)--iconsize <px>— set icon size in pixels (default 128)--use-resource-names— display Terraform resource names instead of service labels
Auto-Grouping of Duplicate Resources
When multiple resources of the same type appear in a diagram (e.g. several S3 buckets or Lambda functions), they are now automatically grouped into visual clusters for a cleaner layout.
Bug Fixes
- Cyclic variable detection (#196):
handle_metadata_varsnow detects and breaks cyclic variable references instead of entering infinite recursion - Private registry support (#193, #197): Fixed private module registry downloads using Terraform's service discovery protocol
- Module output maps (#195): Fixed
TypeErrorwhen a module output value is a dict/map rather than a string - Terragrunt version — handle Terragrunt reporting its version as
"latest" - IAM Role attachments — improved handling of IAM role attachment relationships
Other Improvements
- Draw.io export: refined icon sizing and cluster whitespace for cleaner output
- Nix: added missing runtime dependency to
flake.nix(#194) - Engine-aware messages: all CLI status and error messages now reflect the active engine name (terraform/tofu)
- Python 3.14 compatibility fixes for test suite
Full changelog: v0.39.0...v0.42.0
0.39.0 — AI backend rework + WSL --show fix
Release Notes — 0.39.0
This release is a major rework of the --ai-annotate backend system and adds first-class WSL support for the --show flag.
Highlights
--ai-annotate bedrocknow usesboto3directly. No more API Gateway proxy stack to deploy. Authentication uses the standard AWS credential chain (env vars,~/.aws/credentials, IAM role, SSO).- New
--ai-annotate restapibackend. Point TerraVision at any OpenAI-compatible/v1/chat/completionsendpoint — OpenAI, Anthropic via LiteLLM, vLLM, LM Studio, OpenRouter, custom proxies, etc. - WSL users no longer need a system-wide
xdg-openshim to use--show. TerraVision auto-detects WSL and routes throughwslviewfrom thewslupackage.
⚠️ Breaking changes
--ai-annotate bedrock requires AWS credentials, not an API Gateway URL
The previous bedrock backend POSTed to a hardcoded API Gateway URL (yirz70b5mc.execute-api.us-east-1.amazonaws.com) backed by a Lambda + Bedrock proxy that users were expected to deploy from ai-backend-terraform/. That entire indirection has been removed.
What changed
BEDROCK_API_ENDPOINTconstant removed frommodules/config/cloud_config_aws.py,cloud_config_azure.py, andcloud_config_gcp.py._stream_bedrock_text()now callsbedrock-runtime.converse_streamviaboto3directly. Streaming uses the AWS EventStream protocol (parsed by botocore) and emitscontentBlockDeltaevents for incremental output.check_bedrock_endpoint(url)preflight replaced withcheck_bedrock_credentials(), which callssts:GetCallerIdentityso preflight needs no Bedrock IAM permissions.
What you need to do
- Make sure your AWS credentials are configured (env vars,
~/.aws/credentials, IAM role, or SSO — anything that works foraws sts get-caller-identityworks here). - Optional: override defaults via env vars.
TV_BEDROCK_REGION— defaults tous-east-1TV_BEDROCK_MODEL_ID— defaults tous.anthropic.claude-haiku-4-5-20251001-v1:0. Any Converse-compatible model id works (Claude family, Nova, Llama, Mistral); cross-region inference profile ids are accepted as-is.
- You can delete any
ai-backend-terraform/Lambda + API Gateway stack you previously deployed — it is no longer needed.
# Before (no longer works)
# (relied on a hardcoded API Gateway URL)
# After
export TV_BEDROCK_REGION=eu-west-1 # optional
export TV_BEDROCK_MODEL_ID=us.anthropic.claude-sonnet-4-5-20250929-v1:0 # optional
terravision draw --source ./infra --ai-annotate bedrock✨ New features
--ai-annotate restapi — generic OpenAI-compatible endpoint
A third backend choice that POSTs an OpenAI-style chat-completions request and parses the streamed SSE response. Works with anything that speaks the OpenAI schema.
Configuration (all three required; preflight fails fast if missing):
| Variable | Description |
|---|---|
TV_RESTAPI_URL |
Full URL including the /v1/chat/completions path |
TV_RESTAPI_KEY |
Bearer token sent as Authorization: Bearer <key> |
TV_RESTAPI_MODEL |
Model id passed through verbatim in the request payload |
Examples
# OpenAI direct
export TV_RESTAPI_URL=https://api.openai.com/v1/chat/completions
export TV_RESTAPI_KEY=sk-...
export TV_RESTAPI_MODEL=gpt-4o-mini
terravision draw --source ./infra --ai-annotate restapi
# Anthropic via LiteLLM proxy
export TV_RESTAPI_URL=https://your-litellm-proxy.example/v1/chat/completions
export TV_RESTAPI_KEY=sk-litellm-...
export TV_RESTAPI_MODEL=claude-haiku-4-5
terravision draw --source ./infra --ai-annotate restapi
# Local vLLM / LM Studio
export TV_RESTAPI_URL=http://localhost:8000/v1/chat/completions
export TV_RESTAPI_KEY=not-needed
export TV_RESTAPI_MODEL=meta-llama/Llama-3.1-8B-Instruct
terravision draw --source ./infra --ai-annotate restapiConfigurable Ollama model (OLLAMA_MODEL)
The --ai-annotate ollama model is no longer hardcoded to llama3. It is now read from a new OLLAMA_MODEL constant in each modules/config/cloud_config_<provider>.py (default: llama3), matching the existing OLLAMA_HOST pattern. Any model already pulled to your Ollama server is valid — llama3.1, mistral, qwen2.5, gemma2, etc.
# modules/config/cloud_config_aws.py (and azure / gcp)
OLLAMA_HOST = "http://localhost:11434"
OLLAMA_MODEL = "llama3" # change to any tag pulled on the serverThe selected model is recorded in the generated_by block of terravision.ai.yml so provenance reflects what actually ran.
WSL detection for --show
TerraVision now auto-detects WSL at runtime and routes diagram opens through wslview (from the wslu package) instead of the broken xdg-open lookup chain that ships in WSL images by default. This affects all three opener call sites equally:
- Graphviz/Canvas (PNG, SVG, PDF, etc.) —
view=Falseis forced on WSL andwsl_open()is invoked after render --format drawio—click.launch()swapped forwsl_open()on WSLterravision visualise(HTML output) —webbrowser.open()swapped forwsl_open()on WSL
On non-WSL platforms the existing opener for each path is preserved verbatim — no behavior change on macOS, Linux, or Windows.
Setup for WSL users
sudo apt install wsluIf wslu is missing, TerraVision prints a one-line install hint and continues — the diagram is always generated correctly regardless. --show only controls auto-opening.
📦 Dependencies
- Added:
boto3>=1.35.0(and transitives:botocore,jmespath,urllib3,s3transfer). Lazy-imported inside the bedrock backend so users onollama/restapidon't pay the import cost at startup. - WSL-only:
wslu(apt package) is recommended for--show. Optional — diagrams generate without it.
📚 Documentation
Comprehensive doc updates to reflect the new backend model:
- README.md — three-backend example block + CLI table updated.
- docs/usage-guide.md — new "Choosing a backend" comparison table; new "Configuration" subsection covering all five env vars with worked examples for OpenAI / LiteLLM / vLLM.
- docs/faq.md — "Where does the data go?" paragraph added; backend list extended.
- docs/installation.md —
wslulisted under System Requirements; new "WSL (Windows Subsystem for Linux)" subsection under Step 1. - docs/troubleshooting.md — new entry: "
--showdoesn't open the diagram on WSL". - docs/cicd-integration.md — CI examples for all three backends, including a GitHub Actions OpenAI/restapi sample.
- docs/CONTRIBUTING.md — testing setup updated for all three backends.
- docs/CLAUDE.md — AI Annotation Pipeline section rewritten; old API Gateway /
ai-backend-terraform/description replaced with the boto3 + Converse story.
🧪 Tests
- tests/test_ai_annotations.py — bedrock unreachable test rewritten to raise
botocore.exceptions.ClientError(the realistic exception type for the new boto3 path). Three new tests: restapi happy path, restapi with missing env vars, and unknown-backend rejection.
🔧 Internal / refactoring
- New module constants and helpers in modules/llm.py:
_bedrock_region(),_bedrock_model_id(),_restapi_settings(). - Three preflight checks:
check_ollama_server(),check_bedrock_credentials(),check_restapi_endpoint(). - Three streamers:
_stream_ollama_text(),_stream_bedrock_text()(boto3 Converse),_stream_restapi_text()(OpenAI SSE). - New WSL helpers in modules/helpers.py:
is_wsl()(cached after first probe) andwsl_open()(WSL-only, callers must gate withis_wsl()). - resource_classes/init.py
Canvas.render()— adds WSL fork that forcesview=Falseto graphviz and routes throughwsl_open()instead.
v0.38.0 — Native draw.io Emitter
Highlights
TerraVision now generates .drawio files natively using Python's built-in xml.etree.ElementTree — no more pygraphviz C-extension compilation, no platform-specific workarounds, no [drawio] optional dependency. draw.io export works out of the box on all platforms.
What's New
Native draw.io emitter (issue #188)
- Replaced the
graphviz2drawiolibrary with a pure-Python mxGraph XML emitter - Uses draw.io's built-in AWS4 stencil shapes with correct fill colors per service category
- Uses draw.io's built-in Azure SVG image paths (
img/lib/azure2/) - GCP icons embedded as base64 PNGs from TerraVision's local icon library
Improved edge routing
- Edges now use draw.io's native
orthogonalEdgeStylerouting instead of Graphviz spline waypoints - Eliminates edges crossing through containers
Auto-generated shape mappings
_CLASS_TO_ALIASmap auto-generated at runtime fromresource_classes/(~850 entries)- Shape map generator updated to fetch
Sidebar-AWS4.js(authoritative source) for AWS shapes - Azure shape maps use
img/lib/azure2/SVG paths instead of legacy stencil XML
Breaking Changes
- Removed
graphviz2drawiodependency — no longer needed - Removed
[drawio]optional install group frompyproject.toml - Removed
drawio_shape_map_gcp.py— GCP uses embedded PNGs, not draw.io stencils
Installation
draw.io export now requires zero extra setup:
pip install terravision
terravision draw --source ./terraform --format drawio --outfile my-diagramThe previous platform-specific workarounds (Apple Silicon compiler flags, Windows Graphviz paths) are no longer needed.
v0.36.0 — AI-Powered Annotations
What's New
TerraVision now generates architecture annotations with AI. Pass --ai-annotate <backend> to draw and TerraVision asks an LLM to suggest diagram titles, edge labels, external actors, and numbered flow sequences — written to a dedicated terravision.ai.yml file and merged into your diagram at render time.
poetry run terravision draw --source ./terraform --ai-annotate ollama
poetry run terravision draw --source ./terraform --ai-annotate bedrockHighlights
-
Two backends out of the box
ollama— runs a localllama3model onlocalhost:11434. Fully offline, no cloud calls.bedrock— uses AWS Bedrock via the infrastructure inai-backend-terraform/. Great for CI pipelines already running with an AWS IAM role.
-
The graph is never touched by the LLM. Suggestions go into
terravision.ai.ymlonly — the deterministicgraphdictis byte-identical with or without--ai-annotate. You can diff the file, review it, commit it, or delete it. -
Two-file annotation model. User-authored
terravision.ymland AI-generatedterravision.ai.ymlare auto-discovered and merged. User annotations always win on conflicts, so the AI can't override decisions you have made. -
Numbered flow sequences (format 0.2). The AI can propose
flows:blocks that render as numbered badges on nodes/edges plus a legend. Steps can target nodes (aws_lambda_function.api) or edges (source -> target) and numbering is continuous across flows. -
Auditable provenance. Every AI file includes a
generated_byblock recording backend, model, and ISO 8601 timestamp so you know exactly what produced the annotations. -
Single unified prompt. Replaces the old per-provider
*_REFINEMENT_PROMPTconstants and the graph-mutatingrefine_with_llm()path with oneANNOTATION_PROMPTinmodules/llm.py. Resource references are validated before writing, so hallucinated resource names are dropped. -
CI/CD ready. Drop
--ai-annotate bedrockinto existing pipelines — same IAM role, no extra secrets.
Migration Notes
- The old
refine_with_llm()and provider-specific refinement prompts have been removed. If you relied on LLM-modified graphs, switch to--ai-annotate <backend>and read annotations fromterravision.ai.yml. - Consider whether to commit
terravision.ai.yml(track AI suggestions over time) or.gitignoreit (regenerate each run).
Docs
NEW: Interactive HTML Diagrams!
- Pan, zoom, search and explore your architecture in any browser
- Animated flow along edges showing data direction when you click on a resource
- Click any resource to see plan attributes, metadata in a detail sidebar
- Full support for AWS, Google Cloud, and Azure
- Single self-contained .html file, no dependencies
Check it out now with
pip install --upgrade terravision
