12.2 Inspect State with the CLI

Key Takeaways

  • terraform state list prints resource addresses in state; optional address patterns or -id= filter the list
  • terraform state show ADDRESS prints one resource's attributes for humans, not for scripts
  • terraform show and terraform show -json inspect the whole latest state snapshot or a saved plan file
  • terraform output reads root-module outputs from state; -json and -raw are the automation forms
  • These inspect commands do not create, update, or destroy infrastructure
Last updated: August 2026

12.2 Inspect State with the CLI

Quick Answer: terraform state list names what is in state. terraform state show ADDRESS prints one resource for a human. terraform show (optionally -json) prints the whole current state snapshot or a saved plan file. terraform output prints root-module outputs. None of these commands create, update, or destroy infrastructure.

Objective 7b on Terraform Associate (004) is: use the CLI to inspect state on Terraform 1.12. Chapter 11 already covered backends, locking, and drift operations (state mv, state rm, apply -replace). This section is the read side. If you answer 7b with state rm or import, you picked a mutating command.

Official references: terraform state, terraform state list, terraform state show, terraform show, and terraform output.

Why this objective appears on 004

Operators need to answer "what does Terraform think it owns?" without applying. The exam mixes four similar verbs on purpose: show versus state show, state list versus output, human text versus -json. A candidate who greps terraform.tfstate by hand, or who thinks state show returns the JSON schema, fails 7b.

The inspect toolkit

CommandScopeTypical consumerChanges infrastructure?
terraform state list [address...]Addresses in state (all, or filtered)Humans, grep, scripts that only need namesNo
terraform state show ADDRESSOne resource instanceHumans at a terminalNo
terraform show [file]Entire latest state snapshot, or a state/plan fileHumans reviewing state or a saved planNo
terraform show -json [file]Same, machine-readableCI, custom tools, documented JSON formatNo
terraform output [NAME]Root-module outputs stored in stateHumans; -json / -raw for scriptsNo

All terraform state subcommands work with remote state the same way they work with local state. A read still does a network round-trip to the backend. Read-only subcommands (list, show) do not write backup files. Mutating subcommands (mv, rm, replace-provider) always write backups — that is chapter 11, not 7b.

terraform state list
terraform state list aws_instance.web
terraform state list module.elb
terraform state list -id=sg-1234abcd

terraform state show 'aws_instance.web'
terraform state show 'aws_instance.web[0]'
terraform state show 'aws_instance.web["env"]'
terraform state show 'module.foo.aws_instance.web'

terraform show
terraform show tfplan
terraform show -json
terraform show -json tfplan

terraform output
terraform output lb_address
terraform output -json
terraform output -raw lb_address

terraform state list

Usage: terraform state list [options] [address...].

With no addresses, it lists every resource instance in the current state's snapshot, including nested modules. With one or more address patterns, it lists matching instances only. Official sort order: module depth first (root resources, then deeper modules), then alphabetically. That is why aws_instance.foo appears before module.elb.aws_elb.main.

Patterns use resource addressing:

  • aws_instance.bar lists every index (bar[0], bar[1]).
  • module.elb lists that module and its submodules.
  • -id=sg-1234abcd lists the instance whose provider ID is that string. Useful when you know the security-group ID from the console and need the Terraform address.

-state=path is a legacy local-backend option. On a configured remote backend, you do not point state list at a random file to "inspect production." You select the workspace / backend that already holds that state.

state list prints addresses, not attribute values. It is the inventory command.

terraform state show versus terraform show

This contrast is the 7b discriminator.

terraform state show ADDRESS requires an address that points to exactly one instance. It prints that instance's attributes in a human-oriented HCL-like dump. HashiCorp states the output is not for programmatic consumption. Do not parse it in CI. Indexed addresses need quoting ('packet_device.worker[0]', 'packet_device.worker["example"]').

terraform show [file] prints a human-readable view of:

  • the latest state snapshot, if you pass no path, or
  • a state file or a saved plan file, if you pass that path.

Use it to inspect a terraform plan -out=tfplan artifact before terraform apply tfplan (chapter 5). Use it to read "state as Terraform sees it" without opening the raw JSON blob.

terraform show -json is the documented machine-readable path. For state (including the no-path case) it emits the JSON state representation. For a plan file it emits plan + configuration + current state. The schema lives in HashiCorp's JSON output format docs. Official caveats on 1.12:

  • -json prints sensitive values in plaintext. Treat the stream as a secret.
  • If providers were upgraded to a new schema version since the snapshot was written, upgrade/refresh state before expecting show -json to decode it cleanly.
  • A plan you want to inspect as JSON should not have been created with -refresh=false.
flowchart LR
    State["Current state snapshot"] --> List["state list<br/>addresses only"]
    State --> One["state show ADDRESS<br/>one resource, human text"]
    State --> All["show / show -json<br/>whole snapshot"]
    PlanFile["Saved plan file"] --> All
    State --> Out["output / output -json<br/>root outputs"]

If a question says "print the ami of aws_instance.web for the on-call engineer," the command is terraform state show aws_instance.web. If it says "dump the entire state for an inventory tool" or "inspect the saved plan as JSON," the command is terraform show -json (with a plan path when the subject is the plan). If it says "list every address in module vpc," the command is terraform state list module.vpc.

terraform output

Usage: terraform output [options] [NAME].

Outputs are not the same as resource attributes in state. output reads values Terraform already stored from output blocks in the root module. Child-module outputs appear only if the root re-exports them.

InvocationResult
terraform outputAll root outputs, human format; sensitive = true values show as <sensitive>
terraform output NAMEThat one value; sensitive values are not redacted when you name them
terraform output -jsonStable JSON object (or a single value if NAME is set); sensitive values in plaintext
terraform output -raw NAMEBare string/number/bool for shell scripts; not for objects/lists — use -json

Ephemeral outputs are omitted entirely, even by name. They are never stored in state (objective 4h). -raw is UTF-8 text, not raw bytes.

Human terraform output formatting can change between versions. Automation should use -json (and jq) or -raw for a single primitive. That is the same philosophy as show -json versus state show.

Inspect means do not change infrastructure

7b commands read. They do not add instances, destroy buckets, or rewrite resource bindings.

They may still:

  • contact a remote backend to fetch the snapshot,
  • print secrets (show -json, output -json, output -raw, output NAME for a sensitive output),
  • fail if the working directory is not initialized or the backend is unreachable.

They do not refresh remote objects the way terraform plan does. state show prints what is in the snapshot, which can be stale relative to the cloud account. If the question is "did someone change the instance type in the console?," inspection of state is not enough — that is a plan / refresh / drift question (6d). If the question is "what address and attributes does this workspace currently record?," inspection is enough.

Do not confuse inspect with:

  • terraform state pull — raw state JSON to stdout (useful, but 7b's documented human/JSON pair is show / show -json).
  • terraform console — expression REPL against configuration + state, not the listed 7b toolkit.
  • terraform apply / import / state rm / state mv — mutations.

Scenario: the Friday incident

On-call Jordan needs the production NAT gateway's Elastic IP without opening the AWS console. The root module exports nat_eip. terraform output -raw nat_eip prints the address for a script. A teammate asks whether aws_nat_gateway.this is even in this workspace. terraform state list aws_nat_gateway.this prints the address (or nothing). To see allocation_id and subnet_id as recorded, Jordan runs terraform state show aws_nat_gateway.this. An inventory job needs the whole snapshot; CI runs terraform show -json and parses the documented structure. Nobody runs apply. Nobody opens terraform.tfstate in an editor.

Later, a saved plan tfplan is waiting for approval. Reviewers run terraform show tfplan, not terraform state show, because a plan is not a single resource address.

004 traps for objective 7b

  • terraform show is the whole state or a plan file. terraform state show is one address.
  • state show is human text. Programmatic state is terraform show -json.
  • state list lists addresses; output lists root outputs.
  • -json and several output forms reveal sensitive values.
  • Inspect commands do not refresh or apply.
  • output does not print child-module outputs unless the root re-exports them.
Test Your Knowledge

On Terraform 1.12, how do terraform show and terraform state show differ?

A
B
C
D
Test Your Knowledge

A CI job must read the current workspace state with a stable, documented machine-readable format. Which command does HashiCorp point you to?

A
B
C
D
Test Your Knowledge

Which set of Terraform 1.12 commands inspects state or outputs without creating, updating, or destroying infrastructure?

A
B
C
D