GitHub Copilot CLI can be a productive pair for Terraform work once you give it the right project context and a review loop. Run copilot in the repository root, keep Terraform state and backends explicit, and treat every proposed change as a plan before apply. This guide covers a practical workflow: project instructions, plan-small-verify steps, Terraform-specific pitfalls, testing, and running multiple agents with AgentVera.
Where Copilot CLI earns its keep in Terraform repos
Terraform repos are mostly HCL plus a small amount of shell for backend init and plan scripts. The structure is explicit: resources, data sources, variables, outputs, and modules. GitHub Copilot CLI works well here because most changes are localized edits with clear names and relationships. A well-scoped Terraform task is easy to verify with terraform fmt, terraform validate, and terraform plan; the agent can produce a diff and you can review it as you would a teammate’s change. The main value is not generating whole environments from scratch, but making safe, incremental module and configuration updates while preserving existing conventions.
Start with a tight .github/copilot-instructions.md contract
Create .github/copilot-instructions.md at the repository root. If an AGENTS.md exists, GitHub Copilot CLI reads that as well. Write the file as an operational contract, not a tutorial: exact commands for init, format check, validation, plan, apply policy, and test; folder conventions for environments and modules; and Terraform-specific rules around state, providers, and plan files. Keep it short enough that the agent actually follows it.
# Terraform project instructions
## Commands
- Initialize: `terraform init -backend-config=env/backend.hcl`
- Format check: `terraform fmt -check -recursive`
- Validate: `terraform validate`
- Plan: `terraform plan -out=plan.tfplan`
- Apply: only after human approval; never run apply automatically.
- Test: `terraform test`
## Layout
- `modules/<name>/` for reusable modules; each module has variables.tf, outputs.tf, main.tf.
- `environments/<env>/` for root configurations; one backend per environment.
- Shared provider configuration in `providers.tf` at the root only.
## Rules
- Never edit state files or lock files directly.
- Prefer small, typed variables and clear descriptions.
- Keep provider versions pinned in `versions.tf`.
- Use existing modules before creating new ones.
- Do not commit `.terraform/`, `*.tfplan`, or local backend files.
Update the file when you change environments, backend layout, or test commands. For a broader workflow outside Terraform specifics, see How to use GitHub Copilot CLI: a step-by-step guide.
Plan-small-verify: the Terraform loop that keeps state safe
The safest loop is: initialize the backend once, start copilot at the repository root, give it a narrow task with the expected files to touch, let it edit and run terraform fmt -check and terraform validate, then stop and show the diff. Do not ask for apply until you have reviewed the plan output. If the task needs a provider change or a state move, split that into a separate step and ask the agent to propose commands first.
Useful prompts:
- Add a new
stagingroot module underenvironments/by copyingenvironments/dev, switching the backend key, and reusing the existing network and application modules. Runterraform fmt -checkandterraform validate, then show the diff. - Refactor the
networkingmodule to accept asubnet_cidrsmap variable instead of separate list variables. Update all callers inenvironments/devandenvironments/prod, and run validation. - Create a new
aws_iam_policyresource inmodules/appfrom the inline policy inmain.tf. Add an output and wire it through the root module. Showterraform planoutput for dev. - Investigate why
terraform planinenvironments/prodshows an unexpected replacement for the database instance. Report only the changed attributes and propose a minimal fix without changing state manually. - Write a
terraform testfor thenamingmodule that verifies a valid name and rejects an invalid character.
If the Terraform change is part of a larger feature, a spec-driven approach keeps the agent aligned; see Spec-driven development with AI agents: a practical guide.
Tasks Copilot CLI handles well and Terraform pitfalls to watch
Good fits include adding resources, data sources, and locals; renaming or retyping variables with all callers; splitting an inline block into a module; updating descriptions and validation rules; and formatting. Less safe are moving resources between modules or state, backend reconfiguration, provider version upgrades, and anything that requires terraform state mv or manual lock file edits.
The agent also tends to generate working HCL but can miss Terraform-specific consequences: hard-coded regions or environment names instead of variables, missing depends_on where ordering is real, or changes that break terraform plan because of unknown values. Watch for destructive replacement plans and sensitive outputs.
| Task type | Typical Copilot CLI use | Specific Terraform risk |
|---|---|---|
| Add resources or data sources | Good: create resources, locals, and outputs in existing modules | Must use existing variables, providers, and aliases correctly |
| Refactor module variables | Good: rename or change type, update all callers | HCL type constraints can cause validate errors; check every environment |
| Split inline block into module | Good: move a resource block and wire inputs and outputs | State address changes; may need terraform state mv and import planning |
| Provider or backend changes | Risky: can generate correct syntax but wrong migration path | Lock file and backend init; never run apply or state commands without review |
Keep state, backend, and provider edits fully in the human review loop.
Verification before apply: fmt, validate, plan, and tests
Verification for Terraform is mostly command output, not unit tests. After every agent edit, run the checks in this order: terraform fmt -check -recursive, terraform validate, then terraform plan -out=plan.tfplan. The agent can execute these, but you should read the plan summary yourself. For a module change, validate every environment that uses it; a variable rename that passes in dev may fail in prod because of different provider constraints or Terraform versions.
For drift investigation, terraform plan -refresh-only is useful; ask the agent to list only resource changes and avoid state writes. If the project defines terraform test, add explicit test cases for pure functions such as name generation and CIDR allocation, and have the agent run them after changes. Before apply, review the diff with git diff and check that no sensitive values are printed in plan output or terraform output calls.
Parallel agents on one Terraform repo with AgentVera
AgentVera helps when you split Terraform work across several agents. Run one agent per environment or module in its own git worktree so changes to main.tf and variables.tf do not overwrite each other. When each agent’s turn ends, the automatic code review flags risky HCL or backend edits with file:line links, which is the right moment to catch a bad terraform state suggestion. Checkpoints let you undo a turn before it touches state or backend config. Token budgets keep plan-review loops from running away, especially when an agent repeatedly asks for approval on terraform plan output.
Keep the review loop tight
GitHub Copilot CLI fits Terraform projects best when you treat it as a careful pair programmer: put the commands and module conventions in .github/copilot-instructions.md, keep tasks small, and always verify with terraform fmt, terraform validate, and terraform plan before apply. The agent is strong for repetitive module and variable edits; state, backend, and provider migrations should stay under your review. With those guardrails, it reduces the mechanical parts of Terraform work without taking control of your infrastructure.