/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
.envif any value is invalid. APP_CODE_AGENTis 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
.envis missing or empty (zero bytes or only whitespace/comments): enter the First-Time Initialization flow below. - If
.envexists 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.
AskUserQuestionaccepts 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 withInputValidationErrorbefore anything renders, so the agent is left to fill.envin 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_PROFILEfrom.enventirely (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.
- Question: "Choose a project namespace. All CloudFormation stacks start with
APP_ENV (header: "Env", multiSelect: false)
- Question: "Which environment?"
- Options:
- "dev" (Recommended) — "Development environment"
- "stage" — "Staging environment"
- "prod" — "Production environment"
- Other (built-in): builder types a custom 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
cloudformationorterraform)
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:
- If ALL values pass: continue to account detection.
- If any value from "Other" fails validation: display error messages for ALL failing values at once, then re-prompt ONLY the failing value(s) using a simple text prompt (not AskUserQuestion). Do NOT re-ask values that passed. Example:
Validation failed: APP_NAMESPACE: "my--project" — Invalid: cannot contain consecutive hyphens Re-enter APP_NAMESPACE (1-12 chars, lowercase letters/digits/hyphens, starts with letter):
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.
- If profile was skipped: run
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 valuedefault— builder accepted the defaultskipped— 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_IDwas 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-identityfailed earlier). After configuring credentials, runmake -f scripts/prepare.mk prepare-tfstateonce/ipa-composehas generatedprepare.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.ymlexists. 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
.envfile 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_BUCKETandTF_STATE_LOCK_TABLEare written by Step 4.5 whenAPP_IAC=terraform. They are NOT prompted in any flow — preserve them in re-init exactly as found.- IPA-managed variables:
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_AGENTis 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_NAMESPACEand/orAPP_ENV. These values are baked into Makefiles by/ipa-compose. You MUST re-run/ipa-composeafter 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-destroyagainst the old stacksRecommended path: Run
/ipa-destroy(and any manual prepare-stack teardowns) BEFORE switchingAPP_IAC. Then run/ipa-initto switch, followed by/ipa-composeand/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
.envpreserving all extra (non-IPA) variables in their original positions. IPA variables are written as a group with the standard header comment. Then:- If
APP_IACwas changed toterraform: run Step 4.5 (Bootstrap Terraform State Backend). - If
APP_IACwas changed tocloudformation: leave existingTF_STATE_BUCKET/TF_STATE_LOCK_TABLElines in.env(they are harmless when unused; the builder may switch back later). - Otherwise proceed directly to Step 5: Next Step Guidance.
- If
- If the builder confirms no changes: leave
.envuntouched. 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 '' 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.