terraform-state-manager
Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management
Best use case
terraform-state-manager is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management
Teams using terraform-state-manager should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/terraform-state-manager/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How terraform-state-manager Compares
| Feature / Agent | terraform-state-manager | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Terraform State Manager
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.
## Your Task
When a user requests state management assistance:
1. **State Inspection**:
- List all resources in state
- Show resource details
- Identify orphaned resources
- Find unused resources
2. **Drift Detection**:
- Compare state with actual infrastructure
- Identify configuration drift
- Show differences between state and reality
- Suggest remediation actions
3. **State Manipulation**:
- Move resources between states
- Remove resources from state
- Import existing resources
- Rename resources
4. **State Analysis**:
- Generate state reports
- Identify dependencies
- Show resource relationships
- Analyze state size and complexity
## State Commands Reference
### Inspecting State
**List all resources**:
```bash
terraform state list
```
**Show specific resource**:
```bash
terraform state show <resource_address>
```
**Show entire state** (JSON format):
```bash
terraform show -json terraform.tfstate
```
**Pull remote state**:
```bash
terraform state pull > state.json
```
### Manipulating State
**Move resource within state**:
```bash
terraform state mv <source> <destination>
```
**Remove resource from state**:
```bash
terraform state rm <resource_address>
```
**Import existing resource**:
```bash
terraform import <resource_address> <resource_id>
```
**Replace provider in state**:
```bash
terraform state replace-provider <old_provider> <new_provider>
```
### Advanced Operations
**Backup state**:
```bash
terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).json
```
**Restore state**:
```bash
terraform state push state-backup.json
```
## Common State Scenarios
### Scenario 1: Resource Renamed in Configuration
**Problem**: Renamed resource in code, Terraform wants to destroy and recreate.
**Solution**:
```bash
# Move in state to match new name
terraform state mv azurerm_resource_group.old_name azurerm_resource_group.new_name
```
### Scenario 2: Resource Created Outside Terraform
**Problem**: Resource exists but not in state.
**Solution**:
```bash
# Import the existing resource
terraform import azurerm_resource_group.main /subscriptions/{sub-id}/resourceGroups/my-rg
```
### Scenario 3: Resource Stuck in State
**Problem**: Resource deleted manually but still in state.
**Solution**:
```bash
# Remove from state
terraform state rm azurerm_resource_group.deleted
```
### Scenario 4: Move Resource to Different Module
**Problem**: Reorganizing code structure.
**Solution**:
```bash
# Move between modules
terraform state mv module.old.azurerm_resource_group.main module.new.azurerm_resource_group.main
```
### Scenario 5: Split State Files
**Problem**: Need to separate resources into different state files.
**Solution**:
```bash
# 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 Detection
### What is Drift?
Drift occurs when the actual infrastructure differs from what's defined in Terraform state. This can happen when:
- Resources modified manually through portal/CLI
- Changes made by other tools
- Resources deleted outside Terraform
- Automatic scaling or updates
### Detecting Drift
**Run a plan to see differences**:
```bash
terraform plan -detailed-exitcode
```
Exit codes:
- `0`: No changes needed
- `1`: Error occurred
- `2`: Changes needed (drift detected)
**Generate detailed drift report**:
```bash
terraform plan -out=tfplan
terraform show -json tfplan > plan-output.json
```
### Analyzing Drift
The drift report shows:
- **Resource changes**: What will be modified
- **Attribute changes**: Specific values that differ
- **Dependencies**: What else might be affected
**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)
}
```
### Responding to Drift
**Option 1: Apply to fix drift**:
```bash
terraform apply
```
**Option 2: Update code to match reality**:
```bash
# Refresh state to match reality
terraform apply -refresh-only
```
**Option 3: Accept drift and update state**:
```bash
terraform refresh
```
## State File Structure
### State File Format (Simplified)
```json
{
"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": []
}
]
}
]
}
```
### Key State Components
- **version**: State file format version
- **terraform_version**: Terraform version that wrote this state
- **serial**: Increments with each state change
- **lineage**: Unique ID for this state (prevents mixing states)
- **resources**: All managed resources
- **outputs**: Output values
## State Analysis Patterns
### Find All Resources of a Type
```bash
terraform state list | grep "azurerm_storage_account"
```
### Count Resources by Type
```bash
terraform state list | cut -d. -f1 | sort | uniq -c
```
### Show All Resource IDs
```bash
terraform state list | while read resource; do
echo "=== $resource ==="
terraform state show "$resource" | grep "id ="
done
```
### Find Resources Without Tags
```bash
terraform state list | while read resource; do
if terraform state show "$resource" | grep -q "tags.*= {}"; then
echo "No tags: $resource"
fi
done
```
## State Locking
### Understanding State Locking
State locking prevents concurrent modifications:
- **Automatic**: Happens during `plan`, `apply`, `destroy`
- **Backends**: Supported by azurerm, s3, consul, etc.
- **Force unlock**: Use only when necessary
### Unlock a Locked State
```bash
# Get lock ID from error message
terraform force-unlock <lock-id>
```
**Warning**: Only use when you're certain no other operation is running!
## State Backends
### Local Backend (Default)
```hcl
# State stored in local file: terraform.tfstate
```
**Pros**: Simple, no setup
**Cons**: No locking, no collaboration, no encryption
### Remote Backend (Recommended)
**Azure (azurerm)**:
```hcl
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstate"
container_name = "tfstate"
key = "prod.tfstate"
}
}
```
**AWS (s3)**:
```hcl
terraform {
backend "s3" {
bucket = "terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
```
**GCP (gcs)**:
```hcl
terraform {
backend "gcs" {
bucket = "terraform-state"
prefix = "prod"
}
}
```
## State Migration
### Migrate from Local to Remote
**Step 1: Configure backend**:
```hcl
terraform {
backend "azurerm" {
# backend config
}
}
```
**Step 2: Reinitialize**:
```bash
terraform init -migrate-state
```
**Step 3: Verify**:
```bash
terraform state list
```
### Migrate Between Backends
```bash
# 1. Reconfigure backend in code
# 2. Run init with migration
terraform init -migrate-state -reconfigure
```
## State File Security
### Best Practices
1. **Never commit state to version control**:
```gitignore
*.tfstate
*.tfstate.*
```
2. **Encrypt state at rest**:
- Azure Storage: Enable encryption
- S3: Enable server-side encryption
- GCS: Automatic encryption
3. **Encrypt state in transit**:
- Use HTTPS/TLS for remote backends
- Configure secure backend authentication
4. **Limit state access**:
- Use RBAC on storage accounts
- Implement least-privilege access
- Use managed identities when possible
5. **Enable state versioning**:
- Azure: Enable blob versioning
- S3: Enable versioning on bucket
- GCS: Enable object versioning
## State Troubleshooting
### Issue: State is Corrupted
**Symptoms**: Terraform commands fail with state errors
**Solution**:
```bash
# 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
```
### Issue: State Out of Sync
**Symptoms**: Plan shows unexpected changes
**Solution**:
```bash
# Refresh state to match reality
terraform apply -refresh-only
# Review changes
terraform plan
```
### Issue: Duplicate Resources in State
**Symptoms**: Same resource appears multiple times
**Solution**:
```bash
# List all resources
terraform state list
# Remove duplicates
terraform state rm <duplicate_resource>
```
### Issue: Resource Not Found
**Symptoms**: State references resource that doesn't exist
**Solution**:
```bash
# Remove from state
terraform state rm <missing_resource>
# Or import if it exists elsewhere
terraform import <resource_address> <resource_id>
```
## Script Integration
If `scripts/state-analyzer.js` exists, use it:
```bash
# 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
```
## State Analysis Report Format
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}
```
## Advanced State Operations
### Use Targeted Operations
```bash
# 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!
### Working with Count/For-Each
**Move specific instance**:
```bash
terraform state mv 'azurerm_vm.example[0]' 'azurerm_vm.example[1]'
```
**Move from count to for_each**:
```bash
terraform state mv 'azurerm_vm.example[0]' 'azurerm_vm.example["vm1"]'
```
## State Hygiene Checklist
- [ ] State stored in remote backend
- [ ] State encryption enabled
- [ ] State versioning enabled
- [ ] State locking configured
- [ ] Regular state backups
- [ ] Access controls in place
- [ ] State file not in version control
- [ ] Drift detection automated
- [ ] Resource tagging enforced
- [ ] State documentation maintained
## Reference Files
See `references/` for:
- State file format specification
- Backend comparison matrix
- Drift detection strategies
- State migration guidesRelated Skills
terraform-validator
Validate Terraform code for syntax errors, best practices, security issues, and compliance with standards
terraform-security-scanner
Comprehensive security scanning for Terraform code including secrets detection, compliance checks, and vulnerability assessment
terraform-resource-fetch
Fetch latest Terraform provider resources and documentation from Terraform Registry
terraform-project-generator
Generate complete Terraform project structure with main.tf, variables.tf, outputs.tf, backend.tf, and terraform.tf following best practices
terraform-plan-analyzer
Parse, explain, and analyze terraform plan output for impact assessment, cost estimation, and risk evaluation
terraform-module-scaffold
Create production-ready, reusable Terraform modules with complete documentation, examples, and tests
terraform-doc-generator
Auto-generate comprehensive README.md documentation for Terraform modules with usage examples, inputs, outputs, and requirements
terraform-code-generator
Auto-generate Terraform resource blocks by fetching latest schemas from Terraform Registry in real-time
skill-installer
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).
skill-creator
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.
jwebmp-webawesome
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.
jwebmp-webawesome-pro
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.