| name | ipa-init |
| description | Initialize IPA project configuration |
| model | opus |
/ipa-init — Initialize IPA Project Configuration
This skill interactively configures a project's .env file with the IPA-managed variables required by all other IPA skills (/ipa-compose, /ipa-prepare, /ipa-deploy). It auto-detects the AWS account ID, provides sensible defaults, and validates all input. When the builder selects APP_IAC=terraform, the skill also bootstraps the Terraform state backend (S3 + DynamoDB via CloudFormation) so the project is deploy-ready in a single step.
Lifecycle: /ipa-init → /ipa-compose → /ipa-prepare → /ipa-deploy
Variable Schema
The .env file contains up to seven IPA-managed variables. AWS_PROFILE is optional — if the builder skips it, the line is omitted from .env. The agent MUST set all other six variables during initialization.
| Variable | Prompted | Default | Description |
|---|
AWS_PROFILE | Yes | (none) | AWS CLI profile name (optional — omit to use default credential chain) |
AWS_REGION | Yes | us-east-1 | AWS region for deployments |
AWS_ACCOUNT_ID | Auto-detect, confirm | (none) | 12-digit AWS account ID |
APP_NAMESPACE | Yes | app | Project name prefix for stack naming (max 12 chars) |
APP_ENV | Yes | dev | Environment label (e.g., dev, stage, prod) |
APP_CODE_AGENT | No (auto-set) | claude-code | AI agent platform — set automatically, do not prompt |
APP_IAC | Yes | cloudformation | Infrastructure-as-code tool (cloudformation or terraform) |
TF_STATE_BUCKET | No (derived) | (none) | S3 bucket for Terraform state — written by Step 4.5 after CFN deploy. Only when APP_IAC=terraform. |
TF_STATE_LOCK_TABLE | No (derived) | (none) | DynamoDB table for state locking — written by Step 4.5 after CFN deploy. Only when APP_IAC=terraform. |
Variable Categories
- Prompted (5):
AWS_PROFILE (optional — can be skipped), AWS_REGION, APP_NAMESPACE, APP_ENV, APP_IAC — ask the builder for a value, offer default if one exists.
- Auto-detected (1):
AWS_ACCOUNT_ID — detect via AWS CLI and auto-accept, fall back to manual prompt on failure.
- Auto-set (1):
APP_CODE_AGENT — set silently without prompting. Fixed for this iteration.
.env File Format
The .env file uses standard KEY=VALUE format:
- One variable per line
- No quotes around values
- No spaces around
=
- Comments start with
#
- IPA-managed variables are written as a group with a header comment
- Extra (non-IPA) variables may exist elsewhere in the file and MUST be preserved
Example (with profile):
# IPA Project Configuration
# Generated by /ipa-init — local only, do not commit
AWS_PROFILE=my-profile
AWS_REGION=us-east-1
AWS_ACCOUNT_ID=123456789012
APP_NAMESPACE=myproject
APP_ENV=dev
APP_CODE_AGENT=claude-code
APP_IAC=cloudformation
Example (no profile — uses default credential chain):
# IPA Project Configuration
# Generated by /ipa-init — local only, do not commit
AWS_REGION=us-east-1
AWS_ACCOUNT_ID=123456789012
APP_NAMESPACE=myproject
APP_ENV=dev
APP_CODE_AGENT=claude-code
APP_IAC=cloudformation
Validation Rules
You MUST validate every value before writing .env. If a value fails validation, reject it with the specific error message below and re-prompt the builder.
| Variable | Pattern | Error Message |
|---|
AWS_PROFILE | Non-empty string, or none to skip | "AWS_PROFILE must be a profile name or 'none' to skip" |
AWS_REGION | /^[a-z]{2}-[a-z]+-\d+$/ | "Invalid region format — expected format like us-east-1" |
AWS_ACCOUNT_ID | /^\d{12}$/ | "Invalid account ID — must be exactly 12 digits" |
APP_NAMESPACE | /^[a-z][a-z0-9-]{0,11}$/ | "Invalid namespace — must be 1-12 chars, lowercase letters/digits/hyphens, must start with a letter" |
APP_ENV | /^[a-z][a-z0-9-]{0,11}$/ | "Invalid environment — must be 1-12 chars, lowercase letters/digits/hyphens, must start with a letter" |
APP_IAC | cloudformation or terraform | "Invalid IaC tool — must be 'cloudformation' or 'terraform'" |
Validation Behavior
- Validate all prompted values together after both batched prompts return.
- If any value fails: display error messages for ALL failing values at once, then re-prompt ONLY the failing value(s). Do NOT re-ask values that passed.
- Use a simple text prompt (not AskUserQuestion) for re-prompts of failing values.
- Do NOT write
.env if any value is invalid.
APP_CODE_AGENT is auto-set to a fixed value and does not require validation.
First-Time Initialization
Step 1: Detect Init Mode
Check if .env exists at the project root:
- If
.env is missing or empty (zero bytes or only whitespace/comments): enter the First-Time Initialization flow below.
- If
.env exists and contains at least one KEY=VALUE pair: enter the Re-Initialization flow (see next section).
Step 2: Batched Configuration Prompt
Ask the five values in two AskUserQuestion calls — questions 1–4 in the first, question 5 in the second. Do NOT ask them one at a time, and do NOT put all five in one call.
Two hard limits of the tool, and breaking either means the builder is never prompted at all. AskUserQuestion accepts at most 4 questions per call, and every question needs at least 2 options — the built-in "Other" path is added by the tool and does not count toward that minimum. A call that breaks either limit is rejected with InputValidationError before anything renders, so the agent is left to fill .env in from whatever context it has. This was measured on 2026-08-18: a single five-question call whose namespace question offered only "app" was rejected on both counts at once, and the run continued with values nobody confirmed. Keep four-plus-one, and keep two options on every question.
Before the first prompt, display:
Let's configure your project. Answer the four questions below, then one more. Sensible defaults are pre-selected — accept them all for the fastest setup.
Questions 1–4 (first AskUserQuestion call):
-
AWS_PROFILE (header: "Profile", multiSelect: false)
- Question: "Which AWS CLI profile should IPA use?"
- Options:
- "Skip" (Recommended) — "Use default AWS credential chain (env vars, SSO, instance profile)"
- "default" — "Use the AWS CLI profile named 'default'"
- Other (built-in): builder types a custom profile name
- Do NOT suggest, recommend, or infer a profile name. Do not offer examples or guess a profile name based on the project, directory, or any other context.
- If the builder selects "Skip": omit
AWS_PROFILE from .env entirely (do not write the line).
- If the builder selects "default" or types a custom name via "Other": use that value.
-
AWS_REGION (header: "Region", multiSelect: false)
- Question: "Which AWS region for deployments?"
- Options:
- "us-east-1" (Recommended) — "N. Virginia — default region for most AWS services"
- "us-west-2" — "Oregon"
- "eu-west-1" — "Ireland"
- Other (built-in): builder types a custom region
-
APP_NAMESPACE (header: "Namespace", multiSelect: false)
- Question: "Choose a project namespace. All CloudFormation stacks start with
{namespace}-{env}-. Must be unique per account+environment. (1-12 chars, lowercase letters/digits/hyphens, starts with letter)"
- Options:
- "app" (Recommended) — "Default namespace — good for single-project accounts"
- "sandbox" — "Throwaway namespace — good for an account you share with other projects"
- Other (built-in): builder types a custom namespace
- Both options are fixed strings. Do NOT infer a namespace from the directory name or drop the second option to offer only
"app": a one-option question is rejected by the tool (see the limits above), and this is the question most builders override.
-
APP_ENV (header: "Env", multiSelect: false)
- Question: "Which environment?"
- Options:
- "dev" (Recommended) — "Development environment"
- "stage" — "Staging environment"
Question 5 (second AskUserQuestion call, sent as soon as the first returns — do not end your turn between the two):
- APP_IAC (header: "IaC Tool", multiSelect: false)
- Question: "Which infrastructure-as-code tool?"
- Options:
- "cloudformation" (Recommended) — "AWS-native, zero additional tooling"
- "terraform" — "HashiCorp Terraform with S3 state backend"
- Other (built-in): builder types a custom value (reject unless
cloudformation or terraform)
Step 3: Post-Batch Validation and Account Detection
After both batched prompts have returned all 5 answers:
-
Validate all values per the Validation Rules section. Check every value, then:
-
Auto-detect AWS_ACCOUNT_ID using the profile from Question 1:
- If profile was skipped: run
aws sts get-caller-identity --query Account --output text
- If profile provided: run
aws sts get-caller-identity --profile <profile> --query Account --output text
- If the command succeeds: auto-accept the 12-digit result. Do NOT ask the builder to confirm. Display: "Detected AWS Account ID:
<detected_value>"
- If the command fails (AWS CLI not installed, invalid credentials, expired session, or any error): silently skip auto-detection. Prompt the builder manually: "AWS account ID could not be auto-detected. Enter your 12-digit AWS Account ID:" — Validate:
/^\d{12}$/. This is the ONLY scenario that adds an extra interaction.
-
Auto-set (do not prompt):
APP_CODE_AGENT=claude-code
Step 4: Summary and Write
Display a summary table of all values:
┌─────────────────┬──────────────────┬───────────────┐
│ Variable │ Value │ Source │
├─────────────────┼──────────────────┼───────────────┤
│ AWS_PROFILE │ my-dev-admin │ prompted │
│ AWS_REGION │ us-east-1 │ default │
│ AWS_ACCOUNT_ID │ 123456789012 │ auto-detected │
│ APP_NAMESPACE │ myproject │ prompted │
│ APP_ENV │ dev │ default │
│ APP_CODE_AGENT │ claude-code │ auto-set │
│ APP_IAC │ cloudformation │ default │
└─────────────────┴──────────────────┴───────────────┘
The Source column MUST indicate how each value was determined:
prompted — builder typed the value
default — builder accepted the default
skipped — builder chose to omit this variable (AWS_PROFILE only)
auto-detected — detected from AWS CLI (auto-accepted, no confirmation)
auto-set — set automatically, not prompted
If AWS_PROFILE was skipped, show it as:
│ AWS_PROFILE │ (not set) │ skipped │
and do NOT write the AWS_PROFILE= line to .env.
Immediately write .env in KEY=VALUE format with the header comment block. Do NOT ask "Does this look correct?" — the builder confirmed their choices in the batched prompts.
After writing, display: "Configuration written to .env. Re-run /ipa-init to change any values."
If APP_IAC=terraform, proceed to Step 4.5: Bootstrap Terraform State Backend. Otherwise, proceed to Step 5: Next Step Guidance.
Step 4.5: Bootstrap Terraform State Backend
This step runs only when APP_IAC=terraform. Skip entirely for cloudformation.
Terraform requires a state backend (S3 bucket + DynamoDB lock table) to exist before any module can run. Bootstrapping it during /ipa-init makes the project deploy-ready in one step — /ipa-compose then generates Makefiles that work on first run, with no separate prepare step required for state.
4.5.1 Pre-flight Check
Before deploying anything:
-
Credentials available? If AWS_ACCOUNT_ID was set via manual fallback (auto-detection failed in Step 3), credentials are not usable for CFN deploy. Display:
Cannot bootstrap Terraform state backend. AWS credentials are not configured (aws sts get-caller-identity failed earlier). After configuring credentials, run make -f scripts/prepare.mk prepare-tfstate once /ipa-compose has generated prepare.mk (the prepare target is the fallback path for state-backend bootstrapping).
Skip the deploy and proceed to Step 5: Next Step Guidance. The skill does NOT fail.
-
CloudFormation template present? Verify infra/cfn/tfstate/tfstate.yml exists. If not, display an error and skip the bootstrap (same fallback messaging as above).
4.5.2 Deploy the State Backend
Display:
Bootstrapping Terraform state backend — deploying {APP_NAMESPACE}-{APP_ENV}-tfstate (S3 bucket + DynamoDB lock table). This typically takes 30-60 seconds.
Run:
aws cloudformation deploy \
--stack-name {APP_NAMESPACE}-{APP_ENV}-tfstate \
--template-file infra/cfn/tfstate/tfstate.yml \
--parameter-overrides Namespace={APP_NAMESPACE} Environment={APP_ENV} \
--no-fail-on-empty-changeset \
$(if AWS_PROFILE,--profile AWS_PROFILE,) \
--region {AWS_REGION}
The --no-fail-on-empty-changeset flag makes re-runs safe — if the stack already exists with the same parameters, the command is a no-op.
4.5.3 Capture Outputs
Query the stack for StateBucketName and LockTableName:
aws cloudformation describe-stacks \
--stack-name {APP_NAMESPACE}-{APP_ENV}-tfstate \
--query 'Stacks[0].Outputs[?OutputKey==`StateBucketName`].OutputValue' \
--output text \
$(if AWS_PROFILE,--profile AWS_PROFILE,) \
--region {AWS_REGION}
Repeat for LockTableName.
4.5.4 Write Outputs to .env
Append (or replace, if already present) two lines under a # Terraform State Backend header:
# Terraform State Backend (written by /ipa-init after tfstate deploy)
TF_STATE_BUCKET=<StateBucketName>
TF_STATE_LOCK_TABLE=<LockTableName>
Use the same grep -v strip-then-append idiom that env.mk uses, so re-runs converge to the same content.
4.5.5 Failure Handling
If the deploy or describe-stacks call fails:
- Network or credential error: display the error and the same fallback message from 4.5.1. The skill does NOT fail — the rest of init has already succeeded.
- CFN deploy error (e.g., name collision): display the CFN error message and instruct the builder to investigate. Do NOT roll back automatically.
After 4.5 completes (success or fallback), proceed to Step 5: Next Step Guidance.
Re-Initialization
This flow runs when .env already exists and contains at least one KEY=VALUE pair.
Step 1: Read and Parse Existing .env
-
Read the .env file line by line.
-
Separate lines into two groups:
- IPA-managed variables:
AWS_PROFILE, AWS_REGION, AWS_ACCOUNT_ID, APP_NAMESPACE, APP_ENV, APP_CODE_AGENT, APP_IAC, TF_STATE_BUCKET, TF_STATE_LOCK_TABLE
- Extra lines: all other lines (other variables, comments, blank lines) — these belong to other tooling and MUST be preserved exactly as-is.
TF_STATE_BUCKET and TF_STATE_LOCK_TABLE are written by Step 4.5 when APP_IAC=terraform. They are NOT prompted in any flow — preserve them in re-init exactly as found.
-
If the file is malformed (e.g., lines with no = delimiter that aren't comments or blank), warn the builder: "Some lines in .env appear malformed. Would you like to repair them or keep them as-is?" Offer to fix or preserve.
Step 2: Display Current Values
Show the builder their current IPA configuration:
Current IPA Configuration:
┌─────────────────┬──────────────────┐
│ Variable │ Current Value │
├─────────────────┼──────────────────┤
│ AWS_PROFILE │ my-dev-admin │
│ AWS_REGION │ us-east-1 │
│ AWS_ACCOUNT_ID │ 123456789012 │
│ APP_NAMESPACE │ myproject │
│ APP_ENV │ dev │
│ APP_CODE_AGENT │ claude-code │
│ APP_IAC │ cloudformation │
└─────────────────┴──────────────────┘
If extra (non-IPA) variables exist, note: "Your .env also contains N additional variable(s) not managed by IPA. These will be preserved."
Step 3: Selective Update
Ask: "Which values would you like to change? (enter variable names separated by commas, or 'none' to keep all):"
- Only prompt for the variables the builder selects.
- For each selected variable, show the current value and prompt for a new one.
- Validate each new value per the Validation Rules section.
APP_CODE_AGENT is auto-set and cannot be changed by the builder.
Special case — AWS_PROFILE changed: If the builder changes AWS_PROFILE, re-run AWS_ACCOUNT_ID auto-detection using the new profile. Present the new detected value for confirmation. If detection fails, ask if they want to update AWS_ACCOUNT_ID manually.
Step 4: Re-Compose Warning
If the builder changed APP_NAMESPACE or APP_ENV, display this warning BEFORE confirmation:
Warning: You changed APP_NAMESPACE and/or APP_ENV. These values are baked into Makefiles by /ipa-compose. You MUST re-run /ipa-compose after this update to regenerate Makefiles with the new values.
IaC Engine Switch Guardrail
If the builder changed APP_IAC (e.g., cloudformation → terraform or vice versa), this is a major change that breaks state continuity. Stacks deployed by the previous engine are invisible to the new one.
Before confirmation, display:
DANGER: Switching IaC engine from {old} to {new}.
Resources deployed by {old} are NOT visible to {new} and will not be managed, updated, or torn down by the new engine. Switching engines on a project with deployed infrastructure typically results in:
- Orphaned resources you must clean up manually
- Duplicate resource creation if you redeploy with the new engine (name collisions)
- Lost ability to use
/ipa-destroy against the old stacks
Recommended path: Run /ipa-destroy (and any manual prepare-stack teardowns) BEFORE switching APP_IAC. Then run /ipa-init to switch, followed by /ipa-compose and /ipa-prepare.
If you have NOT yet deployed any stacks, switching is safe.
Use AskUserQuestion to require explicit confirmation:
- "I have not deployed any stacks yet — proceed with switch"
- "Cancel — keep
APP_IAC={old}" (Recommended)
- "I understand the risks — proceed anyway"
If the builder cancels, leave APP_IAC unchanged and continue with any other selected updates. If the builder proceeds and the new value is terraform, the post-write flow MUST run Step 4.5: Bootstrap Terraform State Backend (same as first-time init) so TF_STATE_BUCKET and TF_STATE_LOCK_TABLE are populated.
Step 5: Confirm and Write
Display a summary of changes only (unchanged values marked as "unchanged"):
┌─────────────────┬──────────────────┬──────────────────┬───────────┐
│ Variable │ Old Value │ New Value │ Status │
├─────────────────┼──────────────────┼──────────────────┼───────────┤
│ AWS_PROFILE │ my-dev-admin │ my-prod-admin │ changed │
│ AWS_REGION │ us-east-1 │ us-east-1 │ unchanged │
│ AWS_ACCOUNT_ID │ 123456789012 │ 987654321098 │ changed │
│ APP_NAMESPACE │ myproject │ myproject │ unchanged │
│ APP_ENV │ dev │ dev │ unchanged │
│ APP_CODE_AGENT │ claude-code │ claude-code │ auto-set │
│ APP_IAC │ cloudformation │ cloudformation │ unchanged │
└─────────────────┴──────────────────┴──────────────────┴───────────┘
Ask: "Does this look correct? (yes to write, no to start over):"
- If confirmed: rewrite
.env preserving all extra (non-IPA) variables in their original positions. IPA variables are written as a group with the standard header comment. Then:
- If
APP_IAC was changed to terraform: run Step 4.5 (Bootstrap Terraform State Backend).
- If
APP_IAC was changed to cloudformation: leave existing TF_STATE_BUCKET / TF_STATE_LOCK_TABLE lines in .env (they are harmless when unused; the builder may switch back later).
- Otherwise proceed directly to Step 5: Next Step Guidance.
- If the builder confirms no changes: leave
.env untouched. Proceed to Step 5: Next Step Guidance.
- If rejected: restart from Step 3.
Extra Variable Preservation
When rewriting .env:
- Collect all non-IPA lines (comments, blank lines, extra variables) and their original line positions.
- Write the IPA variable block (with header comment) at the top of the file.
- Append all non-IPA lines after the IPA block, preserving their original relative order.
- Never delete, modify, or reorder extra variables.
Step 5: Next Step Guidance
If /ipa-compose invoked this skill through its Phase 0.5 auto-init gate, display one line —
Initialization complete: .env written.
— and then continue /ipa-compose from its Phase 0 in the same turn. Do not display the next-step block below and do not end your turn: compose delegated by loading this skill's instructions into its own turn, so nothing resumes it except you carrying on. Writing .env is a step in that composition, not the end of a task.
If the builder invoked this skill directly, display:
Initialization complete.
Next: Run `/ipa-compose` to compose infrastructure and generate Makefiles.
Security configuration is handled automatically on first compose.
Then stop. Do NOT invoke any other skill — the builder runs /ipa-compose next.
Edge Cases
Malformed .env File
If .env exists but contains lines that are not valid KEY=VALUE pairs, comments, or blank lines:
- Warn the builder: "Your .env file contains malformed lines (lines without a
= delimiter that aren't comments). These lines may cause issues."
- List the malformed lines.
- Ask: "Would you like to (a) repair these lines, (b) remove them, or (c) keep them as-is?"
- Proceed with the chosen action, then continue with the re-init flow.
AWS_PROFILE Not Found Locally
After the builder provides AWS_PROFILE (skip this check if the builder chose to omit the profile), check if it exists in ~/.aws/config or ~/.aws/credentials:
- Run:
aws configure list-profiles (or check the config files directly).
- If the profile is NOT found: display a non-blocking warning: "Note: Profile '<profile_name>' was not found in your local AWS configuration (~/.aws/config). This is OK if the profile exists on another machine or will be configured later."
- Do NOT reject the value — accept it and continue.
Invalid CloudFormation Stack Name
APP_NAMESPACE is used in stack names via {namespace}-{env}-{service}. The validation regex (/^[a-z][a-z0-9-]{0,11}$/) already prevents most invalid names, but additionally:
- Reject namespaces that start or end with a hyphen.
- Reject namespaces that contain consecutive hyphens (
--).
- If rejected, explain: "This namespace would produce an invalid CloudFormation stack name. Stack names must contain only alphanumeric characters and hyphens, and cannot start/end with a hyphen or contain consecutive hyphens."
AWS STS Failure During Auto-Detection
If aws sts get-caller-identity fails for any reason:
- Do NOT display the error output to the builder.
- Do NOT treat this as a failure state.
- Simply fall back to manual prompting for
AWS_ACCOUNT_ID.
- The skill MUST work on machines without AWS CLI installed.
Empty or Whitespace-Only .env
If .env exists but contains only whitespace, blank lines, or comments (no KEY=VALUE pairs):
- Treat this as a first-time initialization (same as missing
.env).
- Do NOT attempt to parse or preserve the empty content.