terraform-state-manager

Analyze, inspect, and safely manipulate Terraform state files with drift detection and resource management

5 stars

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

$curl -o ~/.claude/skills/terraform-state-manager/SKILL.md --create-dirs "https://raw.githubusercontent.com/GuicedEE/ai-rules/main/skills/.curated/terraform-state-manager/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/terraform-state-manager/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How terraform-state-manager Compares

Feature / Agentterraform-state-managerStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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 guides

Related Skills

terraform-validator

5
from GuicedEE/ai-rules

Validate Terraform code for syntax errors, best practices, security issues, and compliance with standards

terraform-security-scanner

5
from GuicedEE/ai-rules

Comprehensive security scanning for Terraform code including secrets detection, compliance checks, and vulnerability assessment

terraform-resource-fetch

5
from GuicedEE/ai-rules

Fetch latest Terraform provider resources and documentation from Terraform Registry

terraform-project-generator

5
from GuicedEE/ai-rules

Generate complete Terraform project structure with main.tf, variables.tf, outputs.tf, backend.tf, and terraform.tf following best practices

terraform-plan-analyzer

5
from GuicedEE/ai-rules

Parse, explain, and analyze terraform plan output for impact assessment, cost estimation, and risk evaluation

terraform-module-scaffold

5
from GuicedEE/ai-rules

Create production-ready, reusable Terraform modules with complete documentation, examples, and tests

terraform-doc-generator

5
from GuicedEE/ai-rules

Auto-generate comprehensive README.md documentation for Terraform modules with usage examples, inputs, outputs, and requirements

terraform-code-generator

5
from GuicedEE/ai-rules

Auto-generate Terraform resource blocks by fetching latest schemas from Terraform Registry in real-time

skill-installer

5
from GuicedEE/ai-rules

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

5
from GuicedEE/ai-rules

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

5
from GuicedEE/ai-rules

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

5
from GuicedEE/ai-rules

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.