From aws-iac
Manages AWS resources as code using SST v4 (Ion) with Pulumi. Use for writing sst.config.ts, building infra modules, linking resources, and deploying stacks.
How this skill is triggered — by the user, by Claude, or both
Slash command
/aws-iac:aws-sst-developmentThis skill is limited to the following tools:
Bash(npx sst deploy*)The summary Claude sees in its skill listing — used to decide when to auto-load this skill
SST v4 (the "Ion" engine) is a Pulumi-backed IaC framework: you describe AWS
SST v4 (the "Ion" engine) is a Pulumi-backed IaC framework: you describe AWS
resources in TypeScript and SST/Pulumi reconciles them into your account. It
gives you high-level sst.aws.* components (Function, Bucket, Dynamo, Cron,
Service, …) that expand into many underlying resources, plus an escape hatch to
any raw Pulumi aws.* resource for the long tail. This skill encodes a
production-proven way to author, link, test, deploy, and troubleshoot SST
stacks on AWS — distilled from real multi-stack projects that have paid for
each lesson with a prod incident.
SST and Pulumi are third-party — verify current syntax with Context7
(resolve-library-id → query-docs for sst or pulumi-aws) when you're
unsure about a component's options. Verify AWS-side facts (service limits,
model IDs, IAM action names, region availability) with the AWS docs MCP, never
from memory. The patterns here are the how; the docs are the what.
Figure out which mode you're in and jump to the right reference:
| Situation | Go to |
|---|---|
| New project, or adding a resource/module to an existing SST app | Author → references/authoring.md |
| Wiring one module's output into another (links, SSM, IAM scope) | Author → references/authoring.md § Sharing |
| Writing tests for infra so changes don't silently break | Test → references/testing.md |
| Running a deploy, or a deploy just failed | Deploy/Operate → references/deploy-and-troubleshoot.md |
| Migrating a resource between Pulumi types, renaming a physical name | Deploy/Operate → references/deploy-and-troubleshoot.md § Migrations |
Always read the relevant reference before editing — they carry the why behind each rule, which matters more than the rule itself.
SST projects are conventional but not identical. Before editing, build a quick map so your change matches the house style instead of fighting it:
sst.config.ts — the app name, home, providers/region, defaultTags,
any global $transform (Node runtime pin, bundle fixups), and the order in
which run() imports infra/ modules. The import order is the dependency
order; respect it.infra/ — one file per domain (storage, functions, api, observability…).
This is where resources are declared. Check for an infra/CLAUDE.md — these
projects keep IaC-specific rules there, and it's the single most valuable
file to read first.infra/tests/ — source-level Vitest assertions that pin resource
invariants. If they exist, your change must keep them green and probably
needs a new assertion.package.json / .nvmrc — package manager (npm vs pnpm), Node version,
and the sst/pulumi versions actually installed.Run npx sst version to confirm you're on v4/Ion (the $config + .sst/platform/
signature). v2/v3 ("SST Classic", CDK-based) is a different framework — these
patterns don't apply there.
The projects this skill is built from share a deliberate house style. Some of it is universal (true for any SST v4 + AWS project — apply it everywhere); some is project-specific (a sensible default these projects chose — adopt it for consistency, but recognize a project may differ).
Universal — these principles hold for any SST v4 + AWS project:
$transform(sst.aws.Function, (args) => { args.runtime ??= "nodejs24.x" }) in
run() — ??= is correct here (the transform runs before the component
applies its own default, so it fills in only when the user didn't set one).
Recent SST already defaults to a current Node runtime, so check the installed
default first (Context7); the transform is then version-independence insurance
so a future SST downgrade can't silently move your fleet. See
references/authoring.md.Output<T> into a plain JS template literal.
Use $interpolate (or pulumi.interpolate). A bare top-level
`${bucket.arn}/*` stringifies the Output to a [Output<T>] placeholder
and produces a broken ARN that only fails at deploy time (it type-checks and
sst dev runs fine). The fix is $interpolate`${bucket.arn}/*`. This
has caused prod deploy outages. See references/authoring.md § Outputs.ConflictException. Two sequential deploys (teardown, then
recreate) is the conservative default; aliases: / pulumi import / state
surgery can bridge identity in some cases but only with a reviewed plan. See
references/deploy-and-troubleshoot.md § Migrations.sst.aws.* / aws.* resources over the
aws.cloudcontrol.Resource escape hatch. CloudControl outputs are
stringly-typed and oneOf fields don't patch cleanly. Use it only when no
typed resource exists yet, and migrate off it when one ships.Project-specific defaults — adopt for consistency, but confirm per repo:
ap-northeast-1, home: "aws", and defaultTags carrying
Project / Stage / ManagedBy: "sst".removal: stage === "prod" ? "retain" : "remove"
and protect: stage === "prod" so prod resources survive a stack tear-down
and non-prod previews clean up./{app}/{stage}/{domain}/... prefix — for consumers that aren't in the
Pulumi graph (CI scripts, sibling apps, operators). For same-app Lambdas,
prefer SST link: (it wires a real dependency edge and grants IAM); don't
route same-app sharing through SSM. See references/authoring.md § Sharing.await import("./infra/<module>") inside run() so sst dev
hot-reload stays light. (For testing, a module export still runs its top-level
new sst.aws.* unless it's wrapped in a factory function — see
references/testing.md for how to test infra.)@pulumi/pulumi/runtime) for behavioral graph
tests when a module has real logic. Source assertions don't replace a
preview-deploy + smoke test. See references/testing.md.references/deploy-and-troubleshoot.md
§ Observability.When you introduce a convention, say which bucket it's in ("this is universal" vs "matching this repo's house style") so the user can override the project-specific ones deliberately.
references/authoring.md. Match the
surrounding file's commenting density and naming — these projects comment the
why heavily, and a terse one-liner in a heavily-annotated file reads as a
regression.references/testing.md) and
run npx vitest (or the repo's test script). Run npx sst diff and/or
tsc --noEmit to catch type and plan errors before deploying.references/deploy-and-troubleshoot.md. Confirm the
target account with aws sts get-caller-identity before any sst deploy./tmp or chat history.infra/ module, wired into run() in dependency order.runtime unless intentionally diverging — e.g. a Python function).link: (in-graph) and/or $interpolate-scoped
IAM; outputs other tools consume are published to SSM under the stage prefix.sst remove, a resource-type migration) was
flagged to the user with the account it targets, and migrations were planned
as two PRs, not one.npx claudepluginhub zxkane/aws-skills --plugin aws-iacManages AWS resources as code using SST v4 (Ion) with Pulumi. Helps write sst.config.ts, build infra modules, link resources, and troubleshoot deployments.
Manages Pulumi stacks for dev, staging, and prod environments with Bash commands for creation, selection, configuration, YAML files, and TypeScript config reading.
Authors, deploys, and troubleshoots AWS infrastructure using CDK with TypeScript or Python. Covers best practices, stack architecture, construct patterns, compliant refactoring, drift detection, and resource import.