Terraform Commands
The stategraph tf command group plans and applies Terraform changes through Stategraph. These commands replace terraform plan and terraform apply — Stategraph computes the plan scope from your change, runs the underlying Terraform binary, and records everything in a transaction.
Two top-level aliases save typing: stategraph plan is stategraph tf plan, and stategraph apply is stategraph tf apply.
Commands
| Command | Description |
|---|---|
stategraph tf plan |
Plan changes by comparing local HCL against the current state |
stategraph tf apply |
Apply a saved plan file, or plan and apply in one step |
stategraph tf show |
Re-display a plan file, optionally as JSON |
stategraph tf mtx |
Plan across multiple states in a single atomic transaction |
The classic workflow is plan-then-apply: plan --out writes a plan file, you review it, then apply commits it. --out is optional — without it, plan just shows a read-only preview. You can also skip the saved plan entirely and run stategraph tf apply with no plan file to plan, review the diff, and apply in one step.
# From your root module directory
stategraph tf plan --tenant <tenant-id> --out plan.json
stategraph tf apply plan.json
See Velocity Setup for the end-to-end onboarding flow, including importing your existing state first.
stategraph tf plan
Plan Terraform changes by comparing local HCL against the current state in Stategraph. Outputs a plan file for review before applying. Run it from your root module directory — the state is auto-discovered from stategraph.json if --state is not passed.
stategraph tf plan --tenant <tenant-id> [--out <plan-file>] [options]
Options
| Option | Required | Description |
|---|---|---|
--tenant |
Yes | Tenant ID (UUID), or set STATEGRAPH_TENANT_ID |
--out |
No | File to save the plan to for a later stategraph tf apply. When omitted, the plan is shown as a read-only preview and no plan file is written. |
--state |
No | State ID (auto-discovered from stategraph.json if not set) |
--workspace |
No | Workspace name (default: "default") |
--var |
No | Set a variable (key=value, repeatable) |
--var-file |
No | Path to a variable file |
--force |
No | Force a node address into the plan; supports globs (e.g., data.*). Repeatable. |
--force-files |
No | Attach all files matching a path glob (e.g., '**/*.yml') to every file() / templatefile() / fileset() call — an escape hatch for paths Stategraph cannot resolve statically. Repeatable. |
--skip-refresh |
No | Skip the state refresh (passes -refresh=false to the underlying terraform plan) |
--skip-costs |
No | Skip fetching the cost-delta preview after the plan diff |
--costs-wait |
No | Maximum seconds to wait for the cost delta (default: 3). Cannot be combined with --skip-costs. |
--batch-size |
No | Batch size for transaction log appends (performance tuning) |
--parallel-batches |
No | Number of parallel batches for transaction log appends (performance tuning) |
--detailed-exitcode |
No | Return tofu/terraform-compatible exit codes (for CI scripting) |
Pass the same --var / --var-file flags you use with terraform plan.
Example
stategraph tf plan --tenant 550e8400-e29b-41d4-a716-446655440000 --out plan.json
The plan output ends with the familiar summary line, followed by a cost preview when cost analysis is configured:
Plan: 1 to add, 0 to change, 0 to destroy.
Costs:
Totals:
Monthly: 130.82 USD → 140.16 USD (+9.34 USD)
...
If the cost preview is not ready within --costs-wait seconds, the plan prints a hint pointing at stategraph tx costs instead — see Plan-Time Cost.
Forcing resources into a plan
By default, Stategraph plans only what your change touches. --force widens the plan to additional addresses:
# Re-plan every data source
stategraph tf plan --tenant <tenant-id> --out plan.json --force 'data.*'
# Force one module into the plan
stategraph tf plan --tenant <tenant-id> --out plan.json --force 'module.networking.*'
stategraph tf apply
Apply Terraform changes. With a saved plan file, apply commits a plan generated earlier by stategraph tf plan --out. With no plan file, it runs a fresh plan, shows the diff, and prompts for approval before committing — a one-step alternative to the plan-then-apply flow.
stategraph tf apply [options] [<plan-file>]
Arguments
| Argument | Required | Description |
|---|---|---|
<plan-file> |
No | Plan file produced by stategraph tf plan or stategraph tf mtx. When omitted, apply runs a fresh plan, shows the diff, and prompts for approval before committing. |
Options
| Option | Required | Description |
|---|---|---|
--skip-revision-check |
No | Skip the revision hash check between plan and apply |
The plan file records the state revision it was computed against. If the state changed between plan and apply, apply refuses to run so you never apply a stale plan — re-plan instead. --skip-revision-check overrides this guard.
Applying without a plan file
When you omit the <plan-file> argument, stategraph tf apply runs a fresh plan, shows the diff, and prompts for approval before committing — the same one-step flow as terraform apply. Pass --auto-approve to skip the prompt:
stategraph tf apply --tenant <tenant-id> --auto-approve
The approval prompt requires an interactive terminal. With a non-tty stdin or --silent (STATEGRAPH_SILENT), the apply fails unless --auto-approve is also given — combine --silent with --auto-approve to apply non-interactively in CI.
In this plan-less form, apply accepts the same flags as stategraph tf plan to configure the fresh plan it runs: --tenant, --state, --workspace, --var, --var-file, --force, --force-files, --skip-refresh, --skip-costs, --costs-wait, --batch-size, and --parallel-batches. When a saved plan file is supplied these flags are unnecessary — the plan already captured those choices — and several are rejected as a usage error.
Example
stategraph tf apply plan.json
stategraph tf show
Show a previously generated plan file. By default it re-displays the plan in human-readable form; with --json it emits the plan as JSON with all names unmangled, which is useful for policy checks and tooling.
stategraph tf show [options] <plan-file>
Options
| Option | Required | Description |
|---|---|---|
--json |
No | Emit the plan as JSON |
Example
# Review a plan again before applying
stategraph tf show plan.json
# Feed the plan into tooling
stategraph tf show --json plan.json | jq '.'
stategraph tf mtx
Plan Terraform changes across all workspaces in each given directory's group, in a single atomic transaction. Either every state applies or none do. Each directory must contain a stategraph.json.
stategraph tf mtx --tenant <tenant-id> --out <plan-file> [options] <dir>...
Arguments
| Argument | Required | Description |
|---|---|---|
<dir>... |
Yes | One or more directories containing stategraph.json |
Options
| Option | Required | Description |
|---|---|---|
--tenant |
Yes | Tenant ID (UUID), or set STATEGRAPH_TENANT_ID |
--out |
Yes | File to write the plan to |
--force |
No | Force a node address into the plan; supports globs. Repeatable. |
--skip-refresh |
No | Skip the state refresh during plan |
--skip-costs |
No | Skip fetching the cost-delta preview |
--costs-wait |
No | Maximum seconds to wait for the cost delta (default: 3) |
--batch-size |
No | Batch size for transaction log appends (performance tuning) |
--parallel-batches |
No | Number of parallel batches for transaction log appends (performance tuning) |
--detailed-exitcode |
No | Return tofu/terraform-compatible exit codes (for CI scripting) |
Example
stategraph tf mtx --tenant <tenant-id> --out plan.json ./networking ./compute ./application
stategraph tf apply plan.json
See Multi-State Transactions for cross-state dependency semantics and guarantees.
Configuration
By default, the plan and apply stages execute tofu (OpenTofu). Set the TF_CMD environment variable to use a different binary, such as terraform.
| Environment Variable | Description |
|---|---|
TF_CMD |
Path to the Terraform/OpenTofu binary (default: tofu) |
STATEGRAPH_TENANT_ID |
Tenant ID (alternative to --tenant) |
STATEGRAPH_WORKSPACE |
Workspace name (alternative to --workspace) |
STATEGRAPH_COSTS_WAIT_SECONDS |
Deployment-level default for --costs-wait |
STATEGRAPH_TX_BATCH_SIZE |
Default for --batch-size |
STATEGRAPH_TX_PARALLEL_BATCHES |
Default for --parallel-batches |
Next Steps
- Velocity Setup - Import your state and run the first plan
- Multi-State Transactions - The
tf mtxworkflow in depth - Plan-Time Cost - Reading the
Costs:block - Refactor - Generate
movedblocks during HCL restructuring - Transactions - Inspect the transactions plans create