terrafax
AI-powered CLI that parses Terraform modules and outputs structured Markdown docs so your infra docs are never wrong again.
Overview
terrafax is a command-line tool that reads Terraform infrastructure files and automatically generates clean, structured Markdown documentation using Claude. Point it at any Terraform directory and it produces human-readable docs covering every resource, variable, output, and module dependency.
The Problem It Solves
Infrastructure documentation is almost always wrong. It starts as a good intention on day one and quietly rots as the codebase evolves. Engineers spend time reading .tf files directly, guessing at intent, or maintaining docs nobody trusts. terrafax treats documentation as a derived artifact, generated from the source of truth.
How It Works
terrafax [PATH] [--output OUTPUT] [--format readme|per-module]
The tool is built around three focused modules:
parser.py: Recursively scans a directory for .tf files, groups them by parent directory (one group per Terraform module), and concatenates their contents with file headers for context.
generator.py: Sends each module’s content to Claude via the Anthropic Python SDK. The system prompt instructs Claude to return only structured Markdown following a fixed schema (Summary, Resources, Variables, Outputs, Module Dependencies, How to Use). Streaming is used via .stream() with .get_final_message() to handle large responses without timeouts.
writer.py: Writes the output either as a single README.md (combining all modules) or as one .md file per module, depending on the --format flag.
Prompt Caching
The system prompt is marked with cache_control: ephemeral on every API call. This means the first call in a run pays the full token cost to write the prompt to cache; every subsequent module call reads from cache at ~10% of the original cost. For a project with many modules this makes a meaningful difference in both latency and spend.
Self-Documenting Demo
The README.md in this repo was not hand-written, it was generated by running terrafax against the sample infra/ module included in the project. The repo ships with proof of its own output.
Stack
| Layer | Tool |
|---|---|
| CLI | click |
| Environment | python-dotenv |
| LLM | Claude (claude-sonnet-4-6) via Anthropic Python SDK |
| Output | Plain Markdown |
What’s Next
The immediate concept maps naturally onto a LangChain-based architecture. A few directions worth exploring:
- LangChain chains: Replace the direct SDK call with an
LLMChainorLCELpipeline, making it easier to swap models (OpenAI, Bedrock, local) without rewriting the core logic. - RAG over existing docs: Use a vector store to retrieve prior documentation for a module and feed it into the prompt, so Claude can produce diffs rather than full rewrites on subsequent runs.
- LangGraph agent: Let an agent decide how to chunk large modules, summarize dependencies across the full project graph, and iteratively refine output based on validation rules.
- CI integration: Run as a GitHub Actions step so docs are regenerated and committed automatically whenever
.tffiles change. - Multi-cloud: Extend parsing to ARM templates (Azure) and Deployment Manager configs (GCP) using the same generation pipeline.