Terraform & HCL Formatter

Paste Terraform, Terragrunt, Packer or Nomad configuration and get the canonical `terraform fmt` layout without installing the CLI. Infrastructure code often contains account IDs and secrets, so it is formatted entirely in this tab.

Input

Settings

History

Load from URL

terraform fmt rules, without the binary

PasteKit uses a built-in HCL parser and printer (terraform fmt style). It applies the same conventions HashiCorp’s formatter applies:

  • every attribute and nested block goes on its own line, indented by one level per block
  • the = signs of consecutive single-line attributes are aligned into a column
  • spacing inside expressions is made canonical: a = b, { Name = "site" }, [1, 2]
  • block headers are written as resource "type" "name" {

Like terraform fmt, it is conservative about everything else. Line breaks you chose inside lists, function calls and parentheses are kept, blank lines between blocks are left alone, and strings, ${...} templates and heredocs are printed exactly as written. Comments in all three styles (#, //, /* */) stay attached to the lines they describe.

Any HCL2 file works, not just Terraform: .tfvars, terragrunt.hcl, Packer templates, Nomad job specs and Vault or Consul configuration all share the syntax.

Indentation and keyboard shortcuts

There are no HCL-specific options. Terraform’s own style is two spaces, which is also the toolbar default; you can choose another indent or tabs if a non-Terraform tool expects them, but terraform fmt -check in CI will only accept two spaces. Alignment widths are computed per group, so a blank line, a comment line or a nested block starts a new alignment group, exactly as in the CLI.

Ctrl/Cmd+Enter formats, Ctrl/Cmd+Shift+C copies, and Ctrl/Cmd+K opens the command palette. Configuration files have no minified form, so Ctrl/Cmd+Shift+M is not offered.

Errors and limits

The parser stops at the first structural problem and points at it: an unclosed { names the block type and the line it was opened on, an unterminated heredoc names the marker it was waiting for, and two attributes written on one line separated by a comma are flagged with a hint to split them. A missing = shows up as “Expected ‘{’ to open block”, because name value looks like the start of a nested block to an HCL parser.

This is a formatter, not terraform validate. It does not download providers, so unknown resource types, misspelled arguments or wrong variable types are not reported. Run terraform validate or tflint for that.

JSON-syntax Terraform (.tf.json) is plain JSON; format it with the JSON formatter instead.

A practical workflow for code review: paste the block from a pull request, format it, and compare. If the result differs from what was committed, the author’s editor is not running terraform fmt on save, and CI with terraform fmt -check -recursive will fail. Formatting here first saves a round trip through the pipeline. The same applies to modules copied from documentation or the Terraform Registry, whose examples are frequently pasted with inconsistent indentation.

Examples

Module call and for_each

All seven module arguments share one alignment column; the second block aligns separately.

Input
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.8.1"
name = "main"
cidr = "10.0.0.0/16"
azs = ["ap-southeast-1a","ap-southeast-1b"]
enable_nat_gateway = true
}
resource "aws_iam_user" "dev" {
for_each = toset(["aisha","ben"])
name = each.key
}
Output
module "vpc" {
  source             = "terraform-aws-modules/vpc/aws"
  version            = "5.8.1"
  name               = "main"
  cidr               = "10.0.0.0/16"
  azs                = ["ap-southeast-1a", "ap-southeast-1b"]
  enable_nat_gateway = true
}
resource "aws_iam_user" "dev" {
  for_each = toset(["aisha", "ben"])
  name     = each.key
}
Open this example in the tool

A .tfvars file

Top-level variable assignments are aligned and spacing inside the object and list is normalised.

Input
region="eu-west-1"
instance_type = "t3.micro"
tags={Team="platform",CostCenter="1234"}
allowed_cidrs=["10.0.0.0/8","192.168.0.0/16"]
Output
region        = "eu-west-1"
instance_type = "t3.micro"
tags          = { Team = "platform", CostCenter = "1234" }
allowed_cidrs = ["10.0.0.0/8", "192.168.0.0/16"]
Open this example in the tool

for expression and heredoc

The heredoc body is left byte-for-byte; the attribute before it is not aligned with it because a heredoc is multi-line.

Input
locals {
names = [for u in var.users : upper(u.name) if u.active]
policy = <<EOT
{"Version": "2012-10-17"}
EOT
}
Output
locals {
  names = [for u in var.users : upper(u.name) if u.active]
  policy = <<EOT
{"Version": "2012-10-17"}
EOT
}
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Unclosed '{' of block 'resource' opened on line 1
Explained
A block body is never closed, so the parser reaches the end of the file still inside it.Add the missing ‘}’ at the end of that block. Nested blocks inside it are a common place to lose one.
Expected '{' to open block 'x', found '1'An attribute was written without =, so x 1 looks like the header of a block named x.Write it as x = 1.
Unterminated string starting on line 1A quoted string has no closing " before the end of the line. HCL strings cannot span lines.Close the quote, or switch to a heredoc (<<EOT ... EOT) for multi-line text.
Unexpected ',' in the value of 'a'Two attributes were put on one line separated by a comma, as you might in JSON.Put each attribute on its own line. Commas belong only inside { } object values and [ ] lists.
Unterminated heredoc: no closing 'EOF' line for the heredoc starting on line 1The terminator line is missing, misspelled or has other text on it.Add a line containing only the marker (leading spaces are allowed with <<-EOF).

Frequently asked questions

Is the output identical to terraform fmt?

It follows the same rules: two-space indentation, aligned equals signs and canonical spacing, with your own line breaks and heredocs untouched. It is an independent implementation, so report any difference you find.

Does it validate my Terraform?

It checks syntax only. Provider schemas, references and types are checked by terraform validate, which needs the providers installed.

Can I format Terragrunt or Packer files?

Yes. terragrunt.hcl, Packer .pkr.hcl and Nomad job files use the same HCL2 syntax and format the same way.

Will it change the values or interpolations in my strings?

No. Quoted strings, template interpolations and heredoc bodies are printed exactly as written; only whitespace between tokens is adjusted.

Related tools