cloud IaC terraform tfc claude-curated

Most day-to-day Terraform Cloud (TFC) work happens through VCS-driven runs: open a PR, see the speculative plan, merge to apply. But there are operations the web UI doesn’t handle well — state surgery, narrow targeting, importing legacy resources. For those, you drop down to the local CLI talking to the same TFC backend. See Terraform Cloud Workspaces for workspace fundamentals.

Remote vs local execution modes

A TFC workspace runs in one of two execution modes:

  • Remote (default) — terraform plan/apply runs on TFC’s workers. The CLI uploads a snapshot of the configuration and streams output back. State stays in TFC.
  • Local (execution_mode = local) — TFC still owns the state and variables, but the run executes on the developer’s machine. The CLI fetches state, runs locally, pushes state back. Locking still works.

Local mode is useful when the run needs network access TFC’s workers don’t have (a private VPN, an on-prem registry, a network appliance) or when iterating quickly on a long plan and you don’t want to wait in the run queue.

When you bypass TFC and use CLI directly

Even with a remote-execution workspace, the CLI is the tool of choice for surgical operations.

terraform import

Bring an existing cloud resource under Terraform management without recreating it.

terraform import aws_s3_bucket.legacy my-existing-bucket

The CLI command imports one resource at a time and writes to state immediately. In TF 1.5+ there’s also a declarative Terraform Import Block which is preferable for any change you want reviewed in a PR.

terraform state rm

Remove a resource from state without destroying the underlying infra. Use cases:

  • A resource was deleted out of band; state still references it; apply keeps trying to reconcile a ghost. See Terraform State Drift.
  • A resource is being moved to another module or workspace; state rm from the source, then re-import in the target.
  • A resource was created in the wrong workspace and you need to disown it.
terraform state rm aws_iam_role.orphan

terraform apply -target=...

Apply changes to a single resource (or module) instead of the whole graph.

terraform apply -target=aws_lambda_function.api

Useful when the global plan has unrelated drift you don’t want to handle yet, or when a long plan is blocked on something irrelevant. HashiCorp explicitly calls this an exceptional-case tool — use it, document it, then run a full apply afterwards to catch up.

terraform taint (deprecated)

taint marked a resource for replacement on the next apply. Replaced in TF 0.15.2+ by:

terraform apply -replace=aws_instance.bad

-replace is preferable because it shows up in the plan rather than mutating state silently.

Authenticating CLI to TFC

The CLI needs a TFC API token to talk to the backend.

terraform login

This opens a browser, prompts you to generate a user token, and writes it to ~/.terraform.d/credentials.tfrc.json. Subsequent CLI commands against any workspace in that organisation use the token automatically.

For CI runners use a team API token (or a workspace-scoped token) and inject it via TF_TOKEN_app_terraform_io=<token> rather than running terraform login in a non-interactive context. Apply least privileges when scoping the token.

The risk of CLI bypass

Every operation that goes through the TFC web UI or VCS-driven run is reviewed, logged, and policy-checked. Every operation that goes through the CLI bypasses:

  • PR review (no diff for a teammate to read)
  • Sentinel / OPA policy gates (these only run on remote runs)
  • The run history that auditors look at later
  • Slack notifications and other run-event hooks

For state surgery you often have no choice — state rm is not a thing the UI exposes. But it does mean every CLI operation should be:

  1. Announced in chat or a ticket before you do it.
  2. Documented after — what, why, the resource address.
  3. Followed by a full apply through the normal channel to verify state matches reality.

Pattern: TFC for the 95%, CLI for the 5%

A reasonable working pattern:

  • Default path — change config, open PR, TFC posts a speculative plan, reviewer approves, merge triggers apply. See CI CD for Terraform and GitOps for the broader workflow.
  • Surgical path — for import, state rm, state mv, -target, -replace: use the CLI, log the action, follow with a normal run.
  • Never — direct edits to the state file, even with the CLI. State is treated as read-only data; mutations go through Terraform commands so the lock and version are honoured.

Treating the CLI as a scalpel rather than the primary interface keeps the audit trail clean and avoids the slow drift where everyone develops their own undocumented procedures.

See also

References