Skip to content
Infrastructure as Code iac getting-started 4 min read

Editor & Dev Setup

A good Terraform workflow is more than the CLI: it’s editor feedback as you type, automatic formatting so diffs stay clean, a linter that catches mistakes before plan, and a .gitignore that keeps secrets and bulky cache files out of version control. Investing an hour in this setup pays off on every change you make afterward, and it standardizes the experience across your whole team. This page configures the HashiCorp Terraform VS Code extension, format-on-save, tflint, and pre-commit hooks. Everything here applies equally to OpenTofu — the file format and tooling are shared.

Installing the VS Code extension

The official HashiCorp Terraform extension (hashicorp.terraform) is the single biggest productivity boost. It bundles the terraform-ls language server, giving you syntax highlighting, semantic autocompletion for resource arguments, hover documentation pulled from the provider schema, go-to-definition across modules, and inline diagnostics. Install it from the marketplace or the command line.

code --install-extension hashicorp.terraform

Once installed, open any directory containing .tf files and the language server initializes automatically. After your first terraform init, completion becomes schema-aware: typing inside an aws_instance block suggests real arguments like ami, instance_type, and tags, and flags unknown ones immediately.

Tip: The language server reads provider schemas from the .terraform directory created by terraform init. If autocompletion seems incomplete, run terraform init in the workspace and reload the window.

Format on save with terraform fmt

terraform fmt rewrites configuration to the canonical HCL style — consistent indentation, aligned = signs, and ordered arguments. Running it automatically on every save means formatting never shows up as noise in code review. Configure VS Code to use the extension as the default formatter for Terraform files and format on save.

{
  "editor.formatOnSave": true,
  "[terraform]": {
    "editor.defaultFormatter": "hashicorp.terraform",
    "editor.formatOnSave": true
  },
  "[terraform-vars]": {
    "editor.defaultFormatter": "hashicorp.terraform",
    "editor.formatOnSave": true
  }
}

Drop this into your repository’s .vscode/settings.json so the convention travels with the project. To check formatting from the CLI or in CI, use the recursive check mode, which exits non-zero if anything is unformatted:

terraform fmt -recursive -check -diff

Output:

main.tf
--- old/main.tf
+++ new/main.tf
@@ -1,4 +1,4 @@
 resource "aws_s3_bucket" "logs" {
-    bucket = "my-app-logs"
+  bucket = "my-app-logs"
 }

Linting with tflint

terraform validate only checks that your configuration is internally consistent. tflint goes further: it catches provider-specific errors such as invalid instance types, deprecated syntax, unused declarations, and naming-convention violations — often before you ever run a plan. Install it and add the AWS ruleset for deep cloud-aware checks.

brew install tflint        # macOS; see releases for Linux/Windows
tflint --init              # downloads configured plugins

Configure it with a .tflint.hcl file at the repository root. The AWS plugin validates resource arguments against the real AWS API surface.

plugin "aws" {
  enabled = true
  version = "0.35.0"
  source  = "github.com/terraform-linters/tflint-ruleset-aws"
}

rule "terraform_naming_convention" {
  enabled = true
  format  = "snake_case"
}

rule "terraform_unused_declarations" {
  enabled = true
}

Run it against your code from the project directory:

tflint --recursive

Output:

2 issue(s) found:

Warning: variable "region" is declared but not used (terraform_unused_declarations)
  on variables.tf line 3:
   3: variable "region" {

Error: "t2.tiny" is an invalid instance type (aws_instance_invalid_type)
  on main.tf line 12:
  12:   instance_type = "t2.tiny"

Automating checks with pre-commit hooks

Linters only help if they run consistently. pre-commit runs formatting and validation automatically every time you commit, so broken or unformatted code never reaches the repository. Add a .pre-commit-config.yaml using the community Terraform hooks.

repos:
  - repo: https://github.com/antonbabenko/pre-commit-terraform
    rev: v1.96.1
    hooks:
      - id: terraform_fmt
      - id: terraform_validate
      - id: terraform_tflint
      - id: terraform_docs

Install the framework and wire it into your git hooks once per clone:

pip install pre-commit
pre-commit install

From now on, git commit runs every hook and blocks the commit if any fail. You can also run the full suite manually against all files — handy in CI:

pre-commit run --all-files

Output:

Terraform fmt............................................................Passed
Terraform validate.......................................................Passed
Terraform tflint.........................................................Passed
Terraform docs...........................................................Passed

A Terraform .gitignore

Two categories of files must never be committed. The .terraform/ directory holds downloaded providers and modules (large, machine-specific) and state files can contain plaintext secrets like database passwords. Add a .gitignore at the repository root.

# Local .terraform directories and downloaded plugins
**/.terraform/*

# State files — may contain sensitive values
*.tfstate
*.tfstate.*

# Crash logs and plan output
crash.log
*.tfplan

# Variable files that hold secrets (commit *.tfvars.example instead)
*.auto.tfvars
secrets.tfvars

# Keep lock file in version control — do NOT ignore .terraform.lock.hcl

Warning: Always commit .terraform.lock.hcl. It pins exact provider versions and checksums so every machine and CI run resolves identical providers — the same role package-lock.json plays in Node projects.

Best Practices

  • Install the official hashicorp.terraform extension and run terraform init so the language server provides schema-aware completion and diagnostics.
  • Commit a .vscode/settings.json with format-on-save so HCL style is enforced for everyone without manual effort.
  • Run terraform fmt -check and tflint in CI to reject unformatted or invalid code at the pull-request stage.
  • Use pre-commit to run fmt, validate, and tflint locally, catching problems before they ever leave your machine.
  • Ignore .terraform/, *.tfstate, and secret *.tfvars, but always version .terraform.lock.hcl for reproducible provider resolution.
  • Pin tool and plugin versions (extension, tflint ruleset, pre-commit rev) so the toolchain is reproducible across the team and CI.
Last updated June 14, 2026
Was this helpful?