Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

State Surgery

ASecurity

Safe procedure for Terraform state manipulation — covers import, mv, rm, and state-split operations with pre/post verification steps and the rollback strategy for each operation.

7 stars
0 votes
0 copies
0 views
Added 9/23/2026
ai-agentspythongoshellawsazureterraformrefactoringbackend

Works with

cli

Security Analysis

A100/100

Scanned 9/23/2026

$npx -y skills add mcorbett51090/RavenClaude --skill state-surgery --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of State Surgery?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for State Surgery
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mcorbett51090-state-surgery/badge)](https://www.skillsdirectory.com/skills/mcorbett51090-state-surgery)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: state-surgery
description: "Safe procedure for Terraform state manipulation — covers import, mv, rm, and state-split operations with pre/post verification steps and the rollback strategy for each operation."
---

# State Surgery

## When to Use This

Terraform's desired state diverges from actual infrastructure — resources exist but aren't in state (need import), resources moved to a refactored module (need `state mv`), resources need to be removed from management without destroying them (need `state rm`), or a monolithic state needs to be split into smaller backends.

**Never run state surgery on a shared remote backend without first:**
1. Verifying no other `apply` is in progress (the lock will prevent it, but check).
2. Taking a manual state backup.
3. Running every command as a `--dry-run` equivalent first where available.

## Pre-Surgery Checklist

```shell
# 1. Backup current state
terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).tfstate

# 2. Verify the backup is valid JSON
python3 -m json.tool state-backup-*.tfstate > /dev/null && echo "Valid"

# 3. List current resources (baseline)
terraform state list > before.txt

# 4. Confirm no in-progress apply
# (Check your backend — S3: check the DynamoDB lock table; Azure: check the blob lease)
```

## Operation 1 — Import an Existing Resource

Use when: infrastructure exists in the cloud but is not tracked in state.

```shell
# 1. Write the resource block in your .tf files first (Terraform won't import without it)
# 2. Dry run: check what will be imported
terraform plan -generate-config-out=generated.tf   # TF 1.5+ only

# 3. Import
terraform import aws_s3_bucket.my_bucket my-bucket-name

# 4. Verify: plan should show no changes
terraform plan
# Expected output: "No changes. Your infrastructure matches the configuration."
# If the plan shows changes, the .tf config doesn't match the real resource — reconcile before proceeding.
```

**Mass import:** for many resources, write a script that calls `terraform import` per resource, but verify each one individually before moving to the next.

## Operation 2 — Move a Resource (Refactoring)

Use when: renaming a resource, moving it into a module, or moving it between modules. The physical cloud resource does not change.

```shell
# Before TF 1.1: use terraform state mv
terraform state mv aws_s3_bucket.old_name aws_s3_bucket.new_name
terraform state mv aws_instance.app module.compute.aws_instance.app

# TF 1.1+: prefer the moved {} block in .tf (tracked in source control, reviewable in PR)
# In your .tf file:
moved {
  from = aws_s3_bucket.old_name
  to   = aws_s3_bucket.new_name
}
```

Prefer `moved {}` blocks — they appear in `terraform plan` output, are reviewed in a PR, and are self-documenting. `terraform state mv` is for one-off migrations not suitable for the config.

After the move:
```shell
terraform plan  # Must show: 0 to add, 0 to change, 0 to destroy
```

## Operation 3 — Remove from State (Without Destroying)

Use when: transferring management to another state file, or abandoning Terraform management of a resource that should continue to exist.

```shell
terraform state rm aws_s3_bucket.legacy_bucket
# Verify it's gone from state
terraform state list | grep legacy_bucket  # should return nothing
```

After `state rm`, the resource still exists in the cloud. If you run `terraform apply` with the resource still in your config, Terraform will try to create a new one (and likely conflict). **Remove the resource block from your config at the same time.**

## Operation 4 — Split a Monolithic State

Use when: a single state file has grown to cover too many environments or components.

```
Plan:
old-state: [vpc, eks-cluster, rds, app-1, app-2]
new-state-infra: [vpc, eks-cluster, rds]
new-state-app: [app-1, app-2]
```

Procedure:
1. Initialize new backend configurations for each target state.
2. Pull old state: `terraform state pull > old.tfstate`.
3. For each resource moving to `new-state-infra`:
   ```shell
   terraform state mv -state=old.tfstate -state-out=infra.tfstate aws_vpc.main aws_vpc.main
   ```
4. Validate each new state: `terraform state list -state=infra.tfstate`.
5. Push to new remote backends:
   ```shell
   terraform state push -force infra.tfstate  # after switching backend config
   ```
6. Do NOT push until you've verified all resources are accounted for across the new states.
7. Only then remove resources from the old state.

## Post-Surgery Verification

```shell
# After any state operation
terraform state list > after.txt
diff before.txt after.txt  # verify only intended changes

terraform plan
# Must show: "No changes" for unaffected resources
# Any unexpected diff = investigate before applying
```

## Rollback

| Operation | Rollback |
|---|---|
| Import | `terraform state rm <address>` |
| State mv | `terraform state mv` in reverse, or restore backup |
| State rm | `terraform import` to re-add the resource |
| State split | Restore from backup state; re-push to original backend |

For any operation that produces an unexpected plan, restore from backup:
```shell
terraform state push state-backup-<timestamp>.tfstate
```

## Pitfalls

- Running state surgery without a backup — the only recovery from a corrupted state is manual reconciliation of all resources.
- Using `terraform state mv` when a `moved {}` block would work — the `moved {}` block is reviewable, the CLI command is not.
- Running `state rm` without removing the resource block from config — the next plan tries to create a duplicate.
- Importing a resource without matching the `.tf` config exactly — the post-import plan will show unexpected changes; applying those can mutate the real resource.
- Doing state surgery on a backend without checking the lock — two concurrent operations can corrupt the state if the lock isn't honored.

## See Also

- [`../../agents/iac-policy-and-state-engineer.md`](../../agents/iac-policy-and-state-engineer.md) — state backend safety and drift detection
- [`../../agents/iac-architect.md`](../../agents/iac-architect.md) — state isolation by blast radius

Attribution

mcorbett51090mcorbett51090
View sourceSee grades on GitHubMore from mcorbett51090 →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →