---
name: afx-iac
description: Day-to-day Terraform wrapper for the Artifex directory-per-env layout. Use this skill when the user wants to plan, apply, or destroy Terraform infrastructure in a project scaffolded by afx-iac-scaffold. Enforces the infra/environments/<env>/ layout, requires explicit confirmation for prod and destructive operations, and surfaces S3/DynamoDB state-lock errors with actionable messaging.
---

# Artifex IaC Skill

**For Claude Code AI Assistant**

This skill provides thin, opinionated wrappers around `terraform plan`, `terraform apply`, and `terraform destroy` for projects using the canonical Artifex IaC layout produced by `afx-iac-scaffold`. It enforces the directory-per-environment pattern, writes plan files to `.artifex/tmp/` (gitignored), and gates destructive operations behind explicit confirmation.

## What it does

- `plan <env>` — cd into `infra/environments/<env>/`, run `terraform init -upgrade=false` if needed, run `terraform plan -out=.artifex/tmp/<env>.tfplan`
- `apply <env>` — show the resource change summary from the plan file, require typed confirmation, then `terraform apply`
- `destroy <env>` — require `--yes-i-really-mean-it` flag plus typed env name, then `terraform destroy -auto-approve`

The skill refuses to run if the `infra/environments/<env>/` layout is not found anywhere in the directory tree from `$PWD` upward.

## Conversational Routing

| User phrasing | Subcommand |
|---------------|-----------|
| "plan dev", "run a plan for staging", "what would terraform change in prod?" | `plan <env>` |
| "apply dev", "deploy to staging", "push changes to prod" | `apply <env>` |
| "tear down the dev environment", "destroy staging infra" | `destroy <env> --yes-i-really-mean-it` |

If the user asks to destroy, always warn them explicitly before invoking the script. The `--yes-i-really-mean-it` flag is not enough on its own — the script will also prompt for typed env name confirmation at runtime.

## Confirmation rules

| Operation | Env | What user must type |
|-----------|-----|---------------------|
| `plan` | any | (no confirmation) |
| `apply` | non-prod | `yes` |
| `apply` | `prod` | `prod` (literal env name — AWS CLI pattern) |
| `destroy` | any | env name (e.g., `dev`, `staging`, `prod`) |

For `destroy`, the `--yes-i-really-mean-it` flag is also required — the typed confirmation alone is not sufficient to bypass the flag gate.

## Plan files

Plan files are stored in `.artifex/tmp/<env>.tfplan`. This directory is gitignored by the `.artifex/` selectively-tracked pattern from Phase 11. The plan file is consumed and deleted after a successful `apply` to prevent stale re-apply. If a plan file is missing when `apply` is run, the skill refuses with a clear message directing the user to run `plan` first.

## State lock errors

When `plan` or `apply` encounters an S3/DynamoDB state-lock conflict, the skill detects the error pattern in Terraform's stderr and surfaces:
- The lock holder identity (who holds the lock)
- The lock creation timestamp
- The lock ID
- The exact `terraform force-unlock <lock-id>` command to run

This is the most common pain point when multiple engineers run `plan` concurrently against shared remote state. The wrapper makes it actionable rather than a wall of red text.

## Layout requirement

The skill walks up from `$PWD` looking for a directory that contains `infra/environments/`. If it cannot find the layout anywhere in the tree, it refuses with a clear error pointing the user at `afx-iac-scaffold`. This means the skill can be invoked from anywhere inside the project — you do not need to cd to the project root first.

The `local-compose` environment is excluded from Terraform operations (it has no `.tf` files). The skill detects this and refuses with a message telling the user to use `docker-compose` instead.

## How to Run This Skill

### Planning changes (`plan`)

```bash
# Preview what would change
~/.claude/skills/afx-iac/afx-iac.sh plan dev

# Plan with a specific resource target
~/.claude/skills/afx-iac/afx-iac.sh plan staging --target=aws_ecs_service.api
```

The plan is written to `.artifex/tmp/<env>.tfplan`. Review the output, then apply.

### Applying changes (`apply`)

```bash
# Apply the plan (prompts for typed 'yes')
~/.claude/skills/afx-iac/afx-iac.sh apply dev

# For prod (prompts for typed 'prod')
~/.claude/skills/afx-iac/afx-iac.sh apply prod
```

Always run `plan` before `apply`. The apply command reads the plan file generated by `plan`, shows the change summary again, and then prompts for confirmation.

### Destroying infrastructure (`destroy`)

```bash
# Destroy dev (requires --yes-i-really-mean-it AND typing 'dev')
~/.claude/skills/afx-iac/afx-iac.sh destroy dev --yes-i-really-mean-it

# Destroy staging
~/.claude/skills/afx-iac/afx-iac.sh destroy staging --yes-i-really-mean-it
```

Always warn the user before invoking destroy. This operation is irreversible.

## Dependencies

- `terraform` on PATH (required — the skill fails fast with an install URL if missing)
- Project scaffolded with `afx-iac-scaffold` (the `infra/environments/<env>/` layout)
- `.artifex/` directory at project root (created automatically if missing)

## Version

1.0.0 (ticket 12.3)
