terraform/module-generation/skills/terraform-stacks/SKILL.md
Guide for HashiCorp Terraform Stacks — creating, modifying, and validating Stack configurations (.tfcomponent.hcl, .tfdeploy.hcl), managing multi-region/multi-environment infrastructure.
npx skillsauth add lidge-jun/cli-jaw-skills terraform-stacksInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Extension | Purpose |
|-----------|---------|
| .tfcomponent.hcl | Component configuration |
| .tfdeploy.hcl | Deployment configuration |
| .terraform.lock.hcl | Provider lock file (generated) |
All files live at the Stack repository root. HCP Terraform processes them in dependency order.
my-stack/
├── variables.tfcomponent.hcl
├── providers.tfcomponent.hcl
├── components.tfcomponent.hcl
├── outputs.tfcomponent.hcl
├── deployments.tfdeploy.hcl
├── .terraform.lock.hcl # generated
└── modules/ # only if using local modules
├── s3/
└── compute/
Module sources (no local modules/ dir needed for remote sources):
./modules/vpcterraform-aws-modules/vpc/awsapp.terraform.io/<org-name>/vpc/awsgit::https://github.com/org/repo.git//path?ref=v1.0.0Variables require a type field. The validation argument is not supported.
variable "aws_region" {
type = string
description = "AWS region for deployments"
default = "us-west-1"
}
variable "identity_token" {
type = string
description = "OIDC identity token"
ephemeral = true # prevents persistence in state
}
variable "instance_count" {
type = number
nullable = false
}
Use ephemeral = true for credentials and tokens (prevents state persistence). Use stable for longer-lived values like license keys.
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.5.0"
}
}
Differences from traditional Terraform:
for_each meta-argumentconfig block# Single provider
provider "aws" "this" {
config {
region = var.aws_region
assume_role_with_web_identity {
role_arn = var.role_arn
web_identity_token = var.identity_token
}
}
}
# Multiple providers with for_each
provider "aws" "configurations" {
for_each = var.regions
config {
region = each.value
assume_role_with_web_identity {
role_arn = var.role_arn
web_identity_token = var.identity_token
}
}
}
Prefer workload identity (OIDC) — avoids long-lived static credentials, provides temporary scoped credentials per deployment run. Configure with identity_token blocks and assume_role_with_web_identity. Setup: https://developer.hashicorp.com/terraform/cloud-docs/dynamic-provider-credentials
Each Stack needs at least one component. Components reference modules from local paths, registries, or Git.
component "vpc" {
source = "app.terraform.io/my-org/vpc/aws"
version = "2.1.0"
inputs = {
cidr_block = var.vpc_cidr
name_prefix = var.name_prefix
}
providers = {
aws = provider.aws.this
}
}
Referencing outputs:
component.<name>.<output>for_each: component.<name>[key].<output>[for x in component.s3 : x.bucket_name]provider.<type>.<alias> or provider.<type>.<alias>[each.value]Dependencies are inferred automatically from component references.
See references/component-blocks.md for dependencies, for_each, public registry, Git sources.
Outputs require a type argument. preconditions not supported.
output "vpc_id" {
type = string
description = "VPC ID"
value = component.vpc.vpc_id
}
output "endpoint_urls" {
type = map(string)
value = {
for region, comp in component.api : region => comp.endpoint_url
}
}
Works identically in .tfcomponent.hcl and .tfdeploy.hcl:
locals {
common_tags = {
Environment = var.environment
ManagedBy = "Terraform Stacks"
Project = var.project_name
}
}
Safely remove components. Requires the component's providers for teardown.
removed {
from = component.old_component
source = "./modules/old-module"
providers = {
aws = provider.aws.this
}
}
Generate JWT tokens for OIDC authentication:
identity_token "aws" {
audience = ["aws.workload.identity"]
}
Reference in deployments: identity_token.<name>.jwt
Access HCP Terraform variable sets:
store "varset" "aws_credentials" {
id = "varset-ABC123"
source = "tfc-cloud-shared"
category = "terraform"
}
deployment "production" {
inputs = {
aws_access_key = store.varset.aws_credentials.AWS_ACCESS_KEY_ID
}
}
See references/deployment-blocks.md for details.
Minimum 1, maximum 20 deployments per Stack:
deployment "production" {
inputs = {
aws_region = "us-west-1"
instance_count = 3
role_arn = local.role_arn
identity_token = identity_token.aws.jwt
}
}
deployment "development" {
inputs = {
aws_region = "us-east-1"
instance_count = 1
identity_token = identity_token.aws.jwt
}
}
To destroy: set destroy = true, upload configuration, approve destroy run, then remove the block. See references/deployment-blocks.md.
Group deployments for shared settings (Premium tier):
deployment_group "canary" {
auto_approve_checks = [deployment_auto_approve.safe_changes]
}
deployment "dev" {
inputs = { /* ... */ }
deployment_group = deployment_group.canary
}
Auto-approve rules for deployment plans (Premium tier):
deployment_auto_approve "safe_changes" {
deployment_group = deployment_group.canary
check {
condition = context.plan.changes.remove == 0
reason = "Cannot auto-approve plans with resource deletions"
}
}
Context variables: context.plan.applyable, context.plan.changes.add/change/remove/total, context.success
orchestrate blocks are deprecated — use deployment_group and deployment_auto_approve instead.
Link Stacks by publishing outputs from one and consuming in another:
# Network Stack — publish
publish_output "vpc_id_network" {
type = string
value = deployment.network.vpc_id
}
# Application Stack — consume
upstream_input "network_stack" {
type = "stack"
source = "app.terraform.io/my-org/my-project/networking-stack"
}
deployment "app" {
inputs = {
vpc_id = upstream_input.network_stack.vpc_id_network
}
}
See references/linked-stacks.md for complete documentation.
GA as of Terraform CLI v1.13+. Stacks count toward RUM for HCP Terraform billing.
terraform stacks init # Download providers, modules, generate lock file
terraform stacks providers-lock # Regenerate lock file
terraform stacks validate # Check syntax without uploading
No plan or apply commands — uploading configuration triggers deployment runs.
terraform stacks configuration upload
terraform stacks deployment-run list
terraform stacks deployment-group watch -deployment-group=...
terraform stacks deployment-run approve-all-plans -deployment-run-id=...
terraform stacks deployment-group approve-all-plans -deployment-group=...
terraform stacks deployment-run cancel -deployment-run-id=...
terraform stacks create # Create new Stack (interactive)
terraform stacks fmt # Format Stack files
terraform stacks list # Show all Stacks
terraform stacks version # Display version
terraform stacks configuration list
terraform stacks configuration fetch -configuration-id=...
terraform stacks deployment-group rerun -deployment-group=...
For automation/CI/CD, use the HCP Terraform API instead of CLI watch commands (which stream indefinitely).
GET /api/v2/stack-deployment-steps/{step-id}/artifacts?name=apply-descriptionstack_deployment_step_id query parametercurl -L)See references/api-monitoring.md for full workflow, authentication, and polling patterns.
for_each on providers and components.See references/examples.md for complete working examples.
.terraform.lock.hcl to version controldestroy = true, upload, approve destroy runstack_deployment_step_id query parameterSee references/troubleshooting.md for detailed solutions.
references/component-blocks.md — Component block syntax and argumentsreferences/deployment-blocks.md — Deployment block configuration optionsreferences/linked-stacks.md — Publishing outputs and upstream inputsreferences/examples.md — Multi-region and dependency examplesreferences/api-monitoring.md — API workflow for automationreferences/troubleshooting.md — Common issues and solutionsdevelopment
Native Web UI structured renderer schemas for compose-block drafts, search-results cards, dataframe tables, chart-json charts, and diff output
tools
Unified search hub. Route any web/real-time/X lookup through a 4-tier escalation: built-in web search → cli-jaw browser CDP → progrok Grok OAuth → web-ai (Grok Expert / GPT Pro). Use for: search, 검색, web search, latest news, real-time info, X/Twitter, fact lookup, deep research.
development
UI/UX intent discovery, design vocabulary, product personalities, UX state patterns, typography line break judgment, favicon/product logo design, and logo trust section design. Use when user design direction is vague, when building onboarding/empty/error states, when setting up favicons or product logos, or when referencing a product aesthetic.
development
Canonical owner of module boundary rules, circular dependency detection/prevention, implicit coupling taxonomy, barrel/re-export discipline, and boundary-only defensive programming. Referenced by dev, dev-code-reviewer, dev-backend, dev-frontend stubs.