September 24, 2026

Terraform Query: What It Is and How It Works

~ min read
~0 min read

TL;DR

  • terraform query is a native CLI command for discovering infrastructure that exists in the cloud but isn't tracked in Terraform state.
  • It shipped in Terraform 1.14, generally available on November 19, 2025, built around a new list block and .tfquery.hcl files kept separate from the regular plan graph.
  • The workflow runs in two steps: discover matching resources with terraform query, then optionally generate importable configuration with the -generate-config-out flag.
  • The real limitation is provider support. A provider has to implement list resource support before terraform query works against it, and it isn't available in OpenTofu yet.
  • StackGuardian's SGCode solves the same underlying problem: unmanaged infrastructure outside code, across multiple clouds, without waiting for a provider to add support first.

Every Terraform user eventually encounters infrastructure that exists in the cloud but isn't in Terraform state. Someone provisioned a resource through the console during an incident, a script ran once and was never checked in, or an account was inherited from an acquisition with no documentation. Until recently, finding that infrastructure meant either manually clicking through a cloud console or writing a one-off script to cross-reference resource IDs, since Terraform had no native way to ask, "What's actually out there that I don't already know about?"

This post covers what terraform query discovers, how the underlying list block and .tfquery.hcl files work, where the feature still falls short, and how StackGuardian's SGCode approaches the same discovery problem from a different angle.

What Terraform Query Discovers

terraform query is a native command that searches real, running infrastructure for resources matching defined criteria, without requiring that infrastructure to already exist in Terraform state or configuration. It answers a question Terraform previously had no built-in way to ask: what's running in this account that isn't managed here yet.

HashiCorp built this specifically to address a familiar set of problems that accumulate as cloud environments scale: wasted spend on resources nobody's tracking, configuration drift on things nobody's watching, missing policy coverage for anything outside state, and shadow infrastructure that surfaces during an incident rather than a planned review. Before this feature existed, closing that gap meant either the older terraform import command run on one resource at a time, or third-party tools built specifically to fill the void, since Terraform itself had no discovery mechanism of its own.

How the List Block and .tfquery.hcl Files Work

Query definitions live in files with the .tfquery.hcl extension and are deliberately kept separate from regular .tf configuration. That separation isn't incidental: list operations are read-only and exploratory by nature, and mixing them into the normal plan graph would blur the line between "here's what I'm declaring" and "here's what I'm looking for."

A query file defines one or more list blocks, each specifying a resource type to search for and the criteria to search by:

# discover.tfquery.hcl
list "aws_instance" "untracked" {
  provider = aws

  config {
    filter {
      name   = "tag:ManagedBy"
      values = ["!terraform"]
    }
  }
}

Running terraform query in a directory containing this file checks for every .tfquery.hcl file present, queries the relevant provider's API for matching resources, and prints the results to the terminal. Nothing changes in state at this point; the command only looks and reports.

The more useful step comes with the -generate-config-out flag:

terraform query -generate-config-out=discovered.tf

This writes a new file containing both import blocks and the corresponding resource blocks needed to bring the discovered infrastructure under management. Review and commit that generated file, then run terraform apply as usual, to pull the resources into state. Nothing gets imported automatically just by running the query.

For scripted or CI-driven use, the -json flag switches the output to machine-readable JSON instead of the default human-readable text, which is useful for piping results into another tool rather than reading them directly.

Where Terraform Query Still Falls Short

The feature is genuinely useful, but it has real boundaries worth knowing before relying on it.

Provider support isn't universal. A provider has to explicitly implement list resource support before terraform query works against it at all. This isn't a hypothetical gap; running a query against a resource type the provider hasn't implemented returns an explicit error rather than an empty result, as confirmed in an open GitHub issue against the GitHub provider itself, which still doesn't support list resources for something as basic as organization membership.

It's Terraform-only. OpenTofu doesn't have an equivalent command yet. A feature request tracking this (opentofu/opentofu#3787) remains open and unimplemented as of this writing, tagged "pending-decision," meaning teams standardized on OpenTofu don't get this discovery capability right now.

Each query is scoped to one provider at a time. No built-in mechanism lets a single query aggregate results across AWS, Azure, and GCP simultaneously. A multi-cloud discovery effort involves running separate queries for each provider and manually reconciling the results, since the tool itself doesn't cross provider boundaries.

How StackGuardian Approaches the Same Discovery Problem

terraform query and StackGuardian's SGCode are solving the same underlying problem, infrastructure that exists but isn't managed, from different starting points. terraform query is a CLI command scoped to any provider that implements list support. SGCode is a platform capability built specifically to discover and codify unmanaged infrastructure as an ongoing practice, not a one-off command.

SGCode's Cloud Inventory connects directly to AWS, Azure, and GCP accounts and discovers every resource across the environment in a single pass, cross-referencing its findings against connected state backends to determine what's already covered and what isn't. That cross-cloud reach doesn't depend on any individual provider having implemented a specific list resource type, since SGCode isn't working through Terraform's provider plugin interface the way terraform query does.

Where -generate-config-out produces import and resource blocks for a human to review, SGCode's AI-powered codification does something comparable but goes further: it generates the Terraform or OpenTofu configuration, resolves dependencies between the discovered resource and anything it references, and validates the output through an internal plan run before proposing anything, publishing the result as a pull request to a connected Git repository rather than a local file waiting to be reviewed and applied manually.

None of this makes terraform query redundant. They sit at different layers: one is a CLI primitive inside Terraform itself, scoped to whatever a given provider supports; the other is a platform capability designed to run continuously across a multi-cloud estate regardless of provider-level implementation status.

When Each Approach Makes Sense

terraform query fits a team already deep in the Terraform ecosystem, working with a provider that has implemented list support, doing a scoped, one-off discovery task, finding untagged EC2 instances in a specific account, for example, where the CLI workflow is fast, and the provider gap doesn't matter.

SGCode fits ongoing, cross-cloud discovery as a continuous practice rather than a single task, especially in brownfield environments with years of unmanaged infrastructure across multiple cloud accounts, where waiting on provider-by-provider list-resource support isn't a realistic workaround.

These aren't mutually exclusive. A team could reasonably use terraform query for a quick, scoped AWS discovery task while relying on SGCode for broader, ongoing coverage tracking across every cloud account the organization runs.

Conclusion

terraform query is a real step forward for a problem that used to require manual console work or a third-party tool bolted onto Terraform. The list block and .tfquery.hcl file design are genuinely well thought out, keeping discovery cleanly separate from the regular plan graph. But it's early, provider support is inconsistent, and it doesn't exist in OpenTofu at all yet.

The underlying problem, infrastructure existing outside code, isn't new, and it isn't solved by any single command. StackGuardian's SGCode treats it as a continuous practice rather than a one-off CLI action: cross-cloud by default, without depending on any individual provider implementing list support first. Explore how SGCode discovers and codifies unmanaged infrastructure alongside whatever Terraform-native tooling a team already relies on.

FAQs

1. What is the terraform query used for?

terraform query discovers infrastructure resources that exist in the cloud but aren't currently tracked in Terraform state or configuration. It finds unmanaged resources, audits what's running against what's declared in code, and can optionally generate the configuration needed to bring those resources under management.

2. Does terraform query work with every Terraform provider?

No. A provider must explicitly implement list resource support before a terraform query can discover resources of that type. Providers that haven't implemented it, the GitHub provider is a confirmed example, return an explicit error rather than results when queried.

3. Is terraform query available in OpenTofu?

Not yet. A feature request tracking equivalent functionality remains open on OpenTofu's repository and is marked pending-decision as of this writing, so teams running OpenTofu don't currently have a native equivalent to this command.

4. How does StackGuardian's SGCode differ from terraform query for discovering unmanaged resources?

SGCode discovers resources across AWS, Azure, and GCP in a single platform, without depending on any individual provider having implemented list resource support the way terraform query requires. It also goes further than discovery, generating and validating Terraform or OpenTofu configuration for what it finds and publishing the result as a pull request, rather than producing a local file for manual review and apply.

5. Can terraform query results be automatically imported into Terraform state?

Not automatically from the query itself. Running a terraform query with the -generate-config-out flag produces a file containing import and resource blocks, but nothing changes in state until that generated configuration is reviewed and terraform apply is run against it.

‍

Share article