skills/.curated/terraform-state-manager/SKILL.md
Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management
npx skillsauth add guicedee/ai-rules terraform-state-managerInstall 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.
You are a Terraform state management expert. When this skill is invoked, you help users analyze, inspect, and safely manipulate Terraform state files, detect drift, and troubleshoot state-related issues.
When a user requests state management assistance:
State Inspection:
Drift Detection:
State Manipulation:
State Analysis:
List all resources:
terraform state list
Show specific resource:
terraform state show <resource_address>
Show entire state (JSON format):
terraform show -json terraform.tfstate
Pull remote state:
terraform state pull > state.json
Move resource within state:
terraform state mv <source> <destination>
Remove resource from state:
terraform state rm <resource_address>
Import existing resource:
terraform import <resource_address> <resource_id>
Replace provider in state:
terraform state replace-provider <old_provider> <new_provider>
Backup state:
terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).json
Restore state:
terraform state push state-backup.json
Problem: Renamed resource in code, Terraform wants to destroy and recreate.
Solution:
# Move in state to match new name
terraform state mv azurerm_resource_group.old_name azurerm_resource_group.new_name
Problem: Resource exists but not in state.
Solution:
# Import the existing resource
terraform import azurerm_resource_group.main /subscriptions/{sub-id}/resourceGroups/my-rg
Problem: Resource deleted manually but still in state.
Solution:
# Remove from state
terraform state rm azurerm_resource_group.deleted
Problem: Reorganizing code structure.
Solution:
# Move between modules
terraform state mv module.old.azurerm_resource_group.main module.new.azurerm_resource_group.main
Problem: Need to separate resources into different state files.
Solution:
# 1. Pull original state
terraform state pull > original-state.json
# 2. Remove resources that should move
terraform state rm <resources_to_move>
# 3. In new workspace/backend, import those resources
terraform import <resource_address> <resource_id>
Drift occurs when the actual infrastructure differs from what's defined in Terraform state. This can happen when:
Run a plan to see differences:
terraform plan -detailed-exitcode
Exit codes:
0: No changes needed1: Error occurred2: Changes needed (drift detected)Generate detailed drift report:
terraform plan -out=tfplan
terraform show -json tfplan > plan-output.json
The drift report shows:
Example drift output:
# azurerm_storage_account.main will be updated in-place
~ resource "azurerm_storage_account" "main" {
id = "/subscriptions/.../mystorageaccount"
name = "mystorageaccount"
~ min_tls_version = "TLS1_0" -> "TLS1_2"
# (15 unchanged attributes hidden)
}
Option 1: Apply to fix drift:
terraform apply
Option 2: Update code to match reality:
# Refresh state to match reality
terraform apply -refresh-only
Option 3: Accept drift and update state:
terraform refresh
{
"version": 4,
"terraform_version": "1.6.0",
"serial": 5,
"lineage": "unique-id",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "azurerm_resource_group",
"name": "main",
"provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"id": "/subscriptions/.../resourceGroups/my-rg",
"location": "eastus",
"name": "my-rg",
"tags": {}
},
"dependencies": []
}
]
}
]
}
terraform state list | grep "azurerm_storage_account"
terraform state list | cut -d. -f1 | sort | uniq -c
terraform state list | while read resource; do
echo "=== $resource ==="
terraform state show "$resource" | grep "id ="
done
terraform state list | while read resource; do
if terraform state show "$resource" | grep -q "tags.*= {}"; then
echo "No tags: $resource"
fi
done
State locking prevents concurrent modifications:
plan, apply, destroy# Get lock ID from error message
terraform force-unlock <lock-id>
Warning: Only use when you're certain no other operation is running!
# State stored in local file: terraform.tfstate
Pros: Simple, no setup Cons: No locking, no collaboration, no encryption
Azure (azurerm):
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate"
container_name = "tfstate"
key = "prod.tfstate"
}
}
AWS (s3):
terraform {
backend "s3" {
bucket = "terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
GCP (gcs):
terraform {
backend "gcs" {
bucket = "terraform-state"
prefix = "prod"
}
}
Step 1: Configure backend:
terraform {
backend "azurerm" {
# backend config
}
}
Step 2: Reinitialize:
terraform init -migrate-state
Step 3: Verify:
terraform state list
# 1. Reconfigure backend in code
# 2. Run init with migration
terraform init -migrate-state -reconfigure
Never commit state to version control:
*.tfstate
*.tfstate.*
Encrypt state at rest:
Encrypt state in transit:
Limit state access:
Enable state versioning:
Symptoms: Terraform commands fail with state errors
Solution:
# 1. Restore from backup
terraform state pull > corrupt-state.json
# 2. If using remote backend, check storage versioning
# For Azure:
az storage blob list --account-name tfstate --container-name tfstate
# 3. Download previous version
az storage blob download \
--account-name tfstate \
--container-name tfstate \
--name terraform.tfstate \
--version-id <version-id> \
--file restored-state.json
# 4. Push restored state
terraform state push restored-state.json
Symptoms: Plan shows unexpected changes
Solution:
# Refresh state to match reality
terraform apply -refresh-only
# Review changes
terraform plan
Symptoms: Same resource appears multiple times
Solution:
# List all resources
terraform state list
# Remove duplicates
terraform state rm <duplicate_resource>
Symptoms: State references resource that doesn't exist
Solution:
# Remove from state
terraform state rm <missing_resource>
# Or import if it exists elsewhere
terraform import <resource_address> <resource_id>
If scripts/state-analyzer.js exists, use it:
# Analyze state file
node scripts/state-analyzer.js --state terraform.tfstate --report full
# Detect drift
node scripts/state-analyzer.js --detect-drift
# Show dependencies
node scripts/state-analyzer.js --dependencies azurerm_resource_group.main
When analyzing state, provide:
State Analysis Report
=====================
State Information:
- Terraform Version: {version}
- State Serial: {serial}
- Last Modified: {timestamp}
- Backend: {backend_type}
Resources Summary:
- Total Resources: {count}
- Resource Types: {type_count}
- Orphaned Resources: {orphaned_count}
Resource Breakdown:
{type}: {count}
{type}: {count}
Potential Issues:
- [ ] Resources without tags: {count}
- [ ] Deprecated resource types: {count}
- [ ] Large state file (>{size}MB)
- [ ] Outdated Terraform version
Recommendations:
1. {recommendation}
2. {recommendation}
# Only plan specific resource
terraform plan -target=azurerm_resource_group.main
# Only apply specific resource
terraform apply -target=azurerm_resource_group.main
Warning: Use targets sparingly - can lead to inconsistent state!
Move specific instance:
terraform state mv 'azurerm_vm.example[0]' 'azurerm_vm.example[1]'
Move from count to for_each:
terraform state mv 'azurerm_vm.example[0]' 'azurerm_vm.example["vm1"]'
See references/ for:
development
Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (including private repos).
tools
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations.
development
WebAwesome icon integration for JWebMP — modern, open-source icon library. Provides 1,500+ icons with solid/regular styles, sizing, rotation, animation, and CSS utilities. Drop-in FontAwesome alternative with fresh designs. Use when working with WebAwesome icons, modern icon designs, or as FontAwesome alternative in JWebMP applications.
development
WebAwesome Pro integration for JWebMP with premium icons and features. Extends jwebmp-webawesome with additional styles, premium icons, and advanced features. Use when working with WebAwesome Pro icons or premium WebAwesome features in JWebMP applications.