DEV Community

Bartłomiej Danek
Bartłomiej Danek

Posted on • Originally published at bard.sh

why you need hcl-linter?

Why You Need hcl-linter?

If you've worked with HCL (HashiCorp Configuration Language) in Terraform or Terragrunt, you know the pain: formatting debates in code reviews, subtle typos in block names, drift between environments, and the endless "just run terraform fmt" dance. hcl-linter exists to move those conversations from human review into deterministic, fixable checks.

More Than Just Formatting

Unlike terraform fmt or terragrunt hclfmt - which only touch whitespace - hcl-linter enforces structure. It checks block order, naming conventions, required fields, path references, duplicate labels, and more. Most importantly, many of these rules are auto-fixable, so your CI can not only fail fast but also auto-clean legacy configs.

  • hcl-linter check ./ - CI-friendly lint that exits 1 on any issue
  • hcl-linter fix ./ - Apply fixable rules in-place (block order, array formatting, blank lines, naming)
  • hcl-linter fix ./ --dry-run - See exactly what would change before committing
  • hcl-linter fix ./ --format - Bootstrap formatting without any config

Config That Matches Your Files

hcl-linter uses per-filename config matching via .hcl-linter/ directory. One file per target filename (e.g., terragrunt.hcl, root.hcl, default.hcl as fallback). Config is HCL, not YAML or JSON - no context switching required. Configs support inheritance via extends and per-directory overrides (closest wins), making it ideal for monorepos.

# .hcl-linter/default.hcl
rules {
  block_order {
    enabled = true
    order   = ["include", "locals", "terraform", "dependency", "inputs"]
  }
  required_blocks {
    required {
      type  = "terraform"
      count = "once"
      error = "missing terraform block"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Rules That Matter in PRs

  • block_order - Enforces logical block sequencing; unlisted blocks placed after listed ones
  • array_format - 1 item inline, 2+ items multiline with trailing commas
  • name_validation - Enforces snake_case (or custom regex) on labels
  • duplicates - Catches duplicate dependency "x" or include "x" labels
  • required_fields - Ensures critical attributes exist when a block is present
  • dependency_paths - Validates config_path actually exists on disk
  • remote_state - Enforces backend when require_backend = true
  • hcl_functions - Validates find_in_parent_folders paths and warns on get_env without defaults
  • terraform_block - Checks source, version format, and deprecations
  • count_for_each - Warns on count = 0, for_each = {}, and conflicts
  • dependency_outputs - Validates dependency.x.outputs.y against actual outputs

Fix-Only Rules

Some issues can't be auto-fixed safely (e.g., missing source could hide bugs). Others - like formatting and ordering - are fix-only with no Check phase: blank_lines cleans up whitespace; array_format normalizes lists; block_order reorders blocks.

Zero-Config Fast Path

No config yet? Run hcl-linter fix ./ --format for opinionated defaults:

  • Block order: include → locals → terraform → dependency → inputs
  • Arrays with 2+ items → multiline with trailing commas
  • Blank-line cleanup within and between blocks

This is perfect for one-off formatting or bootstrapping a new project before introducing config-based rules.

CI Integration

In CI, use hcl-linter check ./ for strict non-zero exit on violations, or hcl-linter fix ./ --dry-run to detect byte-level drift - including drift from fix-only rules that check would silently pass.

# Validate configs for typos
hcl-linter validate-config

# Lint all matching files
hcl-linter lint ./ --verbose

# Enforce formatting without config
hcl-linter fix ./ --format --dry-run
Enter fullscreen mode Exit fullscreen mode

Why This Thread Matters

As teams grow and HCL files multiply, the drift compounds: noisy diffs, review time spent on layout, and ../vpc paths that silently point to moved resources. hcl-linter moves those concerns into deterministic, automated checks - not human reviewers.

The config is HCL. The rules are per-file/type. Some fixes are automatic, some not, because we still need people for some chores.

Follow the thread and stay tuned!


Originally published at https://bard.sh/posts/hcl_linter/

Top comments (0)