Insights | NextLink Labs

Importing Existing Infrastructure into Terraform with Claude Code

Written by Alex Podobnik | Apr 24, 2026 11:21:25 PM

Every consulting engagement has the same moment. The client walks you through their AWS account and at some point says "yeah, someone set that up manually a while back." Then you open the console and find 15 EC2 instances, a dozen S3 buckets, and a VPC with security groups that no one fully understands. All created by hand. None of it in Terraform.

Getting this stuff under Terraform management is one of the most tedious jobs in infrastructure work. Not because it's hard. Because it's slow. You're mapping JSON output to HCL arguments, looking up import ID formats, and running terraform plan over and over until the diff is clean.

Claude Code changes the workflow significantly. Instead of doing each step manually and copy-pasting between terminals, you can hand it the whole job and let it run. Here's how we've been doing it at NextLink Labs.

The Old Way

The traditional workflow for importing a single resource looks something like this:

1. Find the resource in AWS (console or CLI)

 

2. Figure out the correct Terraform resource type

 

3. Write the HCL by hand

 

4. Run terraform import with the right ID format

 

5. Run terraform plan and see a huge diff

 

6. Tweak the HCL to match the live state

 

7. Repeat steps 5 and 6 until the diff is clean

 

For one resource, this takes maybe 15 minutes. For 50 resources, it's a full day or more. Most of that time is spent on steps 3 through 6, which is just mechanical translation work.

Set Up Your CLAUDE.md

Before you start importing anything, add your Terraform conventions to a CLAUDE.md file in your repo root. Claude Code reads this automatically at the start of every session, so you don't repeat yourself on every prompt.

# Terraform Import Conventions
- Use Terraform 1.5+ import block syntax, not the CLI import command
- All resources must include tags that merge var.tags with resource-specific tags
- Use specific variable types (objects, lists), not bare strings
- Skip read-only and computed attributes in resource blocks
- Put import blocks in imports.tf, resource definitions in the appropriate module file
- Follow existing naming conventions in the repo

 

This keeps the output consistent across sessions and means you can hand this workflow to anyone on your team without them needing to know the right prompts.

Let Claude Code Pull the Resource Details

Here's the big shift from the chat interface. Claude Code has access to your shell, which means it can run AWS CLI commands directly. You don't need to pre-pull JSON files and feed them in.

I need to import the VPC <VPC_ID> and all its subnets into Terraform.

Run the AWS CLI to get the details, then generate the HCL and import blocks.

 

Claude Code will run the describe commands itself, read the output, and write the Terraform files. You're watching it work instead of doing the translation by hand.

For this to work you just need your AWS credentials configured in whatever shell Claude Code is running in. If you're using profiles, mention which one:

Use the prod-account AWS profile. Import the VPC <VPC_ID> and its subnets into the networking module.

 

The Agentic Loop

This is the part that makes Claude Code significantly faster than the chat interface. Instead of you running terraform plan, reading the diff, pasting it back, and asking for fixes, Claude Code does the whole cycle.

Import this RDS instance: prod-api-db

Pull the details from AWS, generate the HCL and import block,
run terraform init and plan, and keep fixing the config until
the plan shows no changes.

 

Claude Code will:

 
Run aws rds describe-db-instances to get the resource details
 
Write the resource block and import block to the right files
 
Run terraform init and terraform plan
 
Read the plan output and spot the diffs
 
Update the HCL to fix whatever doesn't match
 
Run plan again and repeat until the diff is clean

That loop of plan, read, fix, re-plan is where most of the time goes in manual imports. Having Claude Code do it unattended compresses that from 15 to 20 minutes per resource down to a couple of minutes. You just review the final result.

Bulk Imports

For larger jobs, tell Claude Code to work through a set of resources:

Import all S3 buckets in the prod-account profile into the storage module.

List the buckets first, then import them one at a time. For each bucket,
pull the versioning, encryption, and tagging config. Generate the HCL
and import blocks, and run plan after each one to make sure it's clean.

 

Claude Code will iterate through the list, running CLI commands, writing HCL, and validating as it goes. For 25 buckets this takes maybe 20 to 30 minutes of Claude Code working while you do something else. Doing it by hand would be most of a day.

You can also scope it down if you don't want to import everything at once:

List all S3 buckets in the account. Only import the ones with
the "production" tag. Skip anything with "temp" or "test" in the name.

 

Import Blocks Over CLI Imports

One thing worth calling out. We always use the Terraform 1.5+ import block syntax instead of the terraform import CLI command. Claude Code will default to this if you've got it in your CLAUDE.md, but it's worth understanding why.

Import blocks are declarative. They live in your code, they're reviewable in merge requests, and they run as part of terraform plan and apply. The CLI command is imperative and modifies state directly, which makes it harder to track and easier to mess up.

Claude Code generates them like this:

import {
  to = aws_vpc.main
  id = "<VPC_ID>"
}

import {
  to = aws_subnet.private_a
  id = "<SUBNET_ID>"
}

 

For most resources the import ID is just the resource ID. But some have weird formats. Security group rules use a compound ID like sg-123_ingress_tcp_443_443_0.0.0.0/0. IAM policy attachments need an ARN. Claude Code knows these formats, so you don't have to look them up.

Tricky Parts

 
Dependencies between resources. An EC2 instance might reference a security group that references another security group. If you import them in the wrong order, the plan will be messy. Tell Claude Code to work in layers: networking first, then security groups, then compute, then application-level resources. It usually figures this out on its own, but being explicit helps.
 
terraform plan -generate-config-out exists but it's rough. Terraform has a built-in config generation feature that works with import blocks. Worth knowing about, but the output usually needs a lot of cleanup. Claude Code produces cleaner HCL, especially for complex resources with nested blocks like aws_lb_listener rules or security groups with many rules.
 
State file conflicts. If someone else is already managing some of these resources in a different state file, you'll get conflicts. Have Claude Code run terraform state list on any existing workspaces before you start importing to make sure there's no overlap.
 
Review what it writes. Claude Code working autonomously is fast, but you should still review the final HCL before applying. Check that it didn't add attributes you don't want to manage, that the resource naming makes sense, and that it put things in the right files. The agentic loop gets you to a clean plan quickly, but a clean plan doesn't always mean the code is structured the way you want it.

When to Use This

This workflow is a good fit when:

 
A client has existing infrastructure they want in Terraform
 
You're migrating from CloudFormation or another IaC tool and want to rebuild the HCL
 
Someone manually created resources during an incident and now they need to be brought into the codebase
 
You're onboarding a new AWS account that was set up by a different team

It's not a replacement for understanding what you're importing. You still need to decide on module structure, naming, and how resources relate to each other. Claude Code handles the mechanical part. You handle the architecture decisions.

Wrapping Up

Importing hand-built infrastructure is never going to be fun. But Claude Code takes it from a multi-day grind to something you can knock out in an afternoon. The key is the agentic loop. Instead of you being the one running the plan, reading diffs, and editing files, Claude Code does all of that and you just review the results.

Start with a small batch. Maybe one VPC and its subnets. Get comfortable with the flow before you point it at an entire account. And always review the final HCL before you apply.