Skip to content

A two-resource plan is enough to see what separates a Rootform fact from a Terraform reference. This tutorial plans a VPC and a subnet, then follows the subnet's placement from the plan evidence into the Explorer and rootform explain, with and without the saved plan. Read it to understand unknown until apply, saved-plan pairing, and the difference between a resolved and an indeterminate closure. If you have not opened a Form yet, the quickstart comes first; if you only want your own plan open, Analyze your plan or state is the shorter path.

You need Rootform, Terraform, and the AWS provider download for planning. No cloud account is involved: the placeholder provider credentials grant no access, and the provider skips its account and metadata checks. Rootform's embedded AWS Dialect interprets these resources, so there is nothing to configure. With OpenTofu, run tofu in place of terraform.

  1. Create input

    Create an empty directory for the example:

    mkdir rootform-first-architecture
    cd rootform-first-architecture
    Shell

    Save this complete configuration as main.tf in that directory:

    main.tf HCL
    terraform {
    required_providers {
    aws = {
    source = "hashicorp/aws"
    version = "= 6.62.0"
    }
    }
    }
    provider "aws" {
    region = "us-east-1"
    access_key = "example"
    secret_key = "example"
    max_retries = 1
    skip_credentials_validation = true
    skip_metadata_api_check = true
    skip_region_validation = true
    skip_requesting_account_id = true
    }
    resource "aws_vpc" "main" {
    cidr_block = "10.20.0.0/16"
    }
    resource "aws_subnet" "application" {
    vpc_id = aws_vpc.main.id
    cidr_block = "10.20.1.0/24"
    }

    The subnet's vpc_id references an ID that will be known only after apply. Rootform can still establish its placement when the saved plan pairs with the export.

  2. Produce the plan

    Run these commands in the directory containing main.tf:

    terraform init
    terraform plan -out=plan.tfplan
    terraform show -json plan.tfplan > plan.json
    Shell

    terraform plan creates the saved plan; terraform show -json exports that same plan in the JSON shape Rootform accepts. init downloads the AWS provider, which only the planning tool uses. Rootform reads the two exported files; it never runs Terraform, OpenTofu, or the provider. Keep both plan files out of Git: in real projects they can contain secrets in clear text.

  3. Open the architecture

    rootform run plan.json --plan-file plan.tfplan
    Shell

    If your browser does not open automatically, open the Explorer address shown in the terminal. The command keeps running until you press Ctrl+C. The summary includes this excerpt:

    Run output excerpt OUTPUT
    Plan analyzed
    Enrichment Saved plan paired with this plan JSON (1 module)
    Stage Planned
    Stages Recorded (reconstructed), Refreshed, Planned
    Architecture
    Instances 2
    Interpreted 2
    Contexts 1

    Enrichment means the saved plan paired with this JSON export: their version, timestamp, and configuration shape agree, so Rootform can read the configuration reference behind the placement. Pairing enables that enrichment; it does not prove that both files came from one planning operation.

    Instances counts the resource instances in the plan: the VPC and the subnet. Interpreted counts the instances a Rule matched, here both; a matched Rule does not by itself settle every fact. The context count shows one placement fact. Inspect the subnet below to see its endpoint and the closure that justified it.

  4. Inspect the subnet

    The first scene contains the aws_vpc.main card. Use Open aws_vpc.main, then select aws_subnet.application. In the Inspector's Details tab, Where lists aws_vpc.main. The subnet appears inside that VPC because the AWS Dialect established a placement. Rootform does not draw every Terraform reference as a connection.

  5. Follow the placement evidence

    Open the Inspector's Evidence tab. Under Network context, expand Resolution. It names Rule aws.rule.subnet, source.vpc_id, and Reference traversal as the evidence for the fact from the subnet to aws_vpc.main. Under Closures, Network placement to virtual network is Resolved with one fact. The saved plan's direct aws_vpc.main.id reference identifies the VPC even though its ID is unknown until apply. Run the same analysis without the saved plan to see the limit:

    rootform run plan.json --no-serve
    Shell
    Plan-only excerpt OUTPUT
    Architecture
    Instances 2
    Interpreted 2
    Facts none determined
    Uncertainty
    Planned
    Indeterminate closures 1
    Unknown until apply 1

    The VPC ID is unknown until apply. The JSON export alone does not say which instance vpc_id refers to, so the closure stays indeterminate rather than becoming a guessed placement. See saved-plan pairing for the pairing check and refusal behavior.

  6. Save the architecture

    rootform run plan.json --plan-file plan.tfplan --no-serve -o analysis.json
    Shell
    Saved architecture excerpt OUTPUT
    Plan analyzed
    Enrichment Saved plan paired with this plan JSON (1 module)
    Architecture
    Instances 2
    Contexts 1
    Wrote analysis.json

    The Form retains the stages, facts, closures, diagnostics, and evidence. Reopen it with rootform run analysis.json without the plan files.

  7. Explain the architecture

    rootform explain instance aws_subnet.application --input analysis.json
    Shell
    Subnet explanation excerpt OUTPUT
    Instance explained
    aws_subnet.application
    Interpretation applied aws.rule.subnet as subnet
    Conclusion Interpreted as subnet by aws.rule.subnet: network context to
    aws_vpc.main.
    Facts
    -> context network aws_vpc.main evidence: traversal
    Closures
    context network -> virtual-network
    via source.vpc_id, match exact by id
    resolved, 1 fact

    The explanation names the interpreting Rule and the evidence behind the placement. It makes no claim that this infrastructure has been applied.

  8. Optional: self-contained HTML

    rootform run plan.json --plan-file plan.tfplan --no-serve -o architecture.html
    Shell

    Open architecture.html in a browser. It contains the interactive Explorer and its assets in one file and makes no network requests. It still shows instance names and network placement, so share it only with readers allowed to see that information.

Every fact in a larger Form works this way: a Rule declares what a reference means, the evidence settles it or leaves it indeterminate, and the Form keeps the closure so you can ask why. Rootform describes planned instances, so count and for_each can make an architecture larger than the number of declarations. Choose an input explains when state or a saved Form answers your question better.

Next, read Forms and stages for the model behind closures and stages, or see how the same uncertainty reaches a verdict in Understand Policy outcomes.