Source profileQuality 92/100

agents-inc/skills/src/skills/infra-iac-sst/SKILL.md

infra-iac-sst

SST (Ion) infrastructure-as-code — TypeScript-first serverless on AWS with Pulumi, resource linking, and live Lambda dev

Source repository stars
23
Declared platforms
0
Static risk flags
1
Last source update
2026-08-09
Source checked
2026-08-28

Decision brief

What it does: where it fits

Quick Guide: SST v3 (Ion) is TypeScript-first infrastructure-as-code for AWS, powered by Pulumi/Terraform (not CDK/CloudFormation). Define your entire app in sst.config.ts using high-level components (sst.aws.Function, sst.aws.ApiGatewayV2, sst.aws.Bucket, sst.aws.Dynamo, etc.).…

Best for

    Not for

    • Tasks that require unconfirmed production actions or broad system permissions.
    • Environments where the pinned source and install steps cannot be inspected.

    Compatibility matrix

    Platform support, with evidence labels

    PlatformStatusEvidenceWhat to check
    CodexNot declaredNo explicit evidencePortability before use
    Claude CodeNot declaredNo explicit evidencePortability before use
    CursorNot declaredNo explicit evidencePortability before use
    Gemini CLINot declaredNo explicit evidencePortability before use
    Open the compatibility checker

    Installation

    Inspect first. Install second.

    The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

    Source-detected install commandSource
    npx skills add https://github.com/agents-inc/skills --skill "src/skills/infra-iac-sst"
    Safe inspection promptEditorial

    Inspect the Agent Skill "infra-iac-sst" from https://github.com/agents-inc/skills/blob/81d43a51211aca12c85dcc16085fa99014ec548e/src/skills/infra-iac-sst/SKILL.md at commit 81d43a51211aca12c85dcc16085fa99014ec548e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

    Workflow

    What the source asks the agent to do

    1. 01

      Pattern 7: Multi-Stage Environments

      Every stage is a fully isolated deployment. Use $app.stage for conditional configuration.

      Every stage is a fully isolated deployment. Use $app.stage for conditional configuration.
    2. 02

      Personal dev stage (default)

      Review the “Personal dev stage (default)” section in the pinned source before continuing.

      Review and apply the “Personal dev stage (default)” source section.
    3. 03

      CRITICAL: Before Using This Skill

      All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

      All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)(You MUST use resource linking (link + Resource.) to connect components — NEVER hardcode ARNs, table names, or bucket names)(You MUST use $app.stage for environment isolation — NEVER share resources across stages without explicit intent)
    4. 04

      Examples

      Auto-detection: SST, sst.config.ts, sst.aws.Function, sst.aws.ApiGatewayV2, sst.aws.Bucket, sst.aws.Dynamo, sst.aws.Queue, sst.aws.Topic, sst.aws.Cron, sst.aws.Nextjs, sst.aws.Remix, sst.aws.Astro, sst.aws.StaticSite, sst.aws.Vpc, sst.aws.Cluster, sst.aws.Postgres, sst.aws.Route…

      Core Patterns — sst.config.ts structure, Function, resource linking, $app globals, secrets, multi-stageAPI & Data — ApiGatewayV2, Dynamo, Bucket, Queue, Topic, Cron, authorizationDeployment & DevOps — sst deploy, CI/CD, removal policies, transforms, Vpc, Cluster, frontend frameworks
    5. 05

      Philosophy

      SST v3 (Ion) replaces CDK/CloudFormation with Pulumi/Terraform for dramatically faster deployments and a simpler programming model. The core ideas:

      One config file — Your entire app is defined in sst.config.ts. Infrastructure, frontends, and functions all declared together in TypeScript with loops, conditionals, and functions.Components over constructs — High-level sst.aws. components encapsulate best practices (IAM, logging, monitoring). Use transform to reach into underlying resources when defaults aren't enough.Resource linking — The killer feature. link: [bucket] automatically grants IAM permissions and injects type-safe references. Access via Resource.MyBucket.name at runtime. No manual ARN passing or environment variable wi…

    Permission review

    Static risk signals and limitations

    Reads files

    low · line 231

    The documentation asks the agent to read local files, directories, or repositories.

    # Load secrets from a file

    Evidence record

    Why each signal appears

    EvidenceSourceComputedTestedEditorial
    SignalValueEvidence typeMeaning
    Quality score92/100ComputedDocumentation, specificity, maintenance, and trust rules
    Repository stars23SourceRepository attention, not individual Skill quality
    Compatibility0 platformsSourceDeclared in the catalog source record
    Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

    Pinned source

    Provenance and original SKILL.md

    Repository
    agents-inc/skills
    Skill path
    src/skills/infra-iac-sst/SKILL.md
    Commit
    81d43a51211aca12c85dcc16085fa99014ec548e
    License
    MIT
    Collected
    2026-08-28
    Default branch
    main
    View the original SKILL.md

    SST (Ion) Patterns

    Quick Guide: SST v3 (Ion) is TypeScript-first infrastructure-as-code for AWS, powered by Pulumi/Terraform (not CDK/CloudFormation). Define your entire app in sst.config.ts using high-level components (sst.aws.Function, sst.aws.ApiGatewayV2, sst.aws.Bucket, sst.aws.Dynamo, etc.). Use resource linking (link: [bucket] + Resource.MyBucket.name) for type-safe, permission-aware access between components. Use sst dev for live Lambda development with sub-10ms reloads. Use $app.stage for multi-environment isolation. Use transform to customize underlying Pulumi resources.


    <critical_requirements>

    CRITICAL: Before Using This Skill

    All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

    (You MUST use resource linking (link + Resource.*) to connect components — NEVER hardcode ARNs, table names, or bucket names)

    (You MUST use $app.stage for environment isolation — NEVER share resources across stages without explicit intent)

    (You MUST use sst dev for local development — it provides live Lambda proxying with sub-10ms reloads against real AWS resources)

    (You MUST use sst secret set for secrets — NEVER put secrets in sst.config.ts, .env files committed to git, or environment variables)

    (You MUST use transform to customize underlying resources — NEVER reach for raw Pulumi resources when an SST component exists)

    </critical_requirements>


    Examples

    • Core Patterns — sst.config.ts structure, Function, resource linking, $app globals, secrets, multi-stage
    • API & Data — ApiGatewayV2, Dynamo, Bucket, Queue, Topic, Cron, authorization
    • Deployment & DevOps — sst deploy, CI/CD, removal policies, transforms, Vpc, Cluster, frontend frameworks
    • Quick Reference — CLI commands, component cheat sheet, global helpers, named constants

    Auto-detection: SST, sst.config.ts, sst.aws.Function, sst.aws.ApiGatewayV2, sst.aws.Bucket, sst.aws.Dynamo, sst.aws.Queue, sst.aws.Topic, sst.aws.Cron, sst.aws.Nextjs, sst.aws.Remix, sst.aws.Astro, sst.aws.StaticSite, sst.aws.Vpc, sst.aws.Cluster, sst.aws.Postgres, sst.aws.Router, sst.Linkable, Resource from sst, sst dev, sst deploy, sst remove, sst secret, $app.stage, $transform, $concat, $interpolate, resource linking, live Lambda, Ion

    When to use:

    • Defining AWS infrastructure in TypeScript with high-level components
    • Deploying serverless applications (Lambda, API Gateway, DynamoDB, S3, SQS, SNS)
    • Deploying full-stack apps (Next.js, Remix, Astro, SvelteKit, SolidStart on AWS)
    • Setting up live Lambda development with real AWS resources
    • Managing multi-stage environments (dev, staging, production)
    • Connecting infrastructure components with type-safe resource linking

    When NOT to use:

    • Multi-cloud infrastructure spanning many providers (SST is AWS-focused with limited Cloudflare support)
    • Existing Terraform/Pulumi codebases where SST abstraction adds no value
    • Projects that need container-only deployments without serverless components

    Key patterns covered:

    • sst.config.ts structure (app() + run() functions)
    • Resource linking: link property + Resource.* SDK
    • Live Lambda development with sst dev
    • AWS components: Function, ApiGatewayV2, Dynamo, Bucket, Queue, Topic, Cron
    • Frontend deployments: Nextjs, Remix, Astro, StaticSite
    • Multi-stage isolation with $app.stage
    • Transforms for customizing underlying Pulumi resources
    • Secrets management with sst secret
    • Custom linkables with sst.Linkable and Linkable.wrap
    • Global helpers: $app, $dev, $concat, $interpolate, $resolve, $transform

    Philosophy

    SST v3 (Ion) replaces CDK/CloudFormation with Pulumi/Terraform for dramatically faster deployments and a simpler programming model. The core ideas:

    1. One config file — Your entire app is defined in sst.config.ts. Infrastructure, frontends, and functions all declared together in TypeScript with loops, conditionals, and functions.
    2. Components over constructs — High-level sst.aws.* components encapsulate best practices (IAM, logging, monitoring). Use transform to reach into underlying resources when defaults aren't enough.
    3. Resource linking — The killer feature. link: [bucket] automatically grants IAM permissions and injects type-safe references. Access via Resource.MyBucket.name at runtime. No manual ARN passing or environment variable wiring.
    4. Stage-based isolation — Every developer gets their own stage (sst dev creates a personal stack). $app.stage drives resource naming. Production uses sst deploy --stage production.
    5. Live dev against real AWSsst dev replaces Lambda functions with stubs that proxy to your local machine. Changes reload in under 10ms. No local emulation — your code runs against real DynamoDB, S3, SQS.

    When to use SST:

    • Serverless-first applications on AWS (Lambda, API Gateway, DynamoDB, S3, SQS, SNS)
    • Full-stack apps deploying frontend frameworks (Next.js, Remix, Astro) to AWS
    • Teams that want TypeScript infrastructure with minimal AWS boilerplate
    • Projects needing fast local development loops against real cloud resources

    When NOT to use SST:

    • Multi-cloud infrastructure beyond AWS + Cloudflare (SST's multi-cloud support is limited)
    • Container-only workloads with no serverless components (use raw Pulumi or Terraform)
    • Existing large Terraform/Pulumi codebases where SST abstraction adds migration cost

    Core Patterns

    Pattern 1: sst.config.ts Structure

    Every SST app has a single sst.config.ts with two functions: app() for metadata and run() for resources.

    /// <reference path="./.sst/platform/config.d.ts" />
    
    export default $config({
      app(input) {
        return {
          name: "my-app",
          home: "aws",
          removal: input.stage === "production" ? "retain" : "remove",
          protect: input.stage === "production",
          providers: {
            aws: { region: "us-east-1" },
          },
        };
      },
      async run() {
        const bucket = new sst.aws.Bucket("Uploads");
        const api = new sst.aws.Function("Api", {
          handler: "src/api.handler",
          link: [bucket],
        });
        return { apiUrl: api.url };
      },
    });
    

    Why good: app() handles metadata and stage-specific policies, run() defines all resources, removal: "retain" protects production data, returned values become outputs in .sst/outputs.json

    See examples/core.md for full config with multi-stage, providers, and protect patterns.


    Pattern 2: Resource Linking

    The defining SST feature. Link resources to grant permissions and type-safe access automatically.

    // In sst.config.ts
    const table = new sst.aws.Dynamo("Notes", {
      fields: { userId: "string", noteId: "string" },
      primaryIndex: { hashKey: "userId", rangeKey: "noteId" },
    });
    
    new sst.aws.Function("Api", {
      handler: "src/api.handler",
      link: [table],
    });
    
    // In src/api.ts — runtime code
    import { Resource } from "sst";
    import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
    
    const client = new DynamoDBClient({});
    // Resource.Notes.name is the table name — type-safe, auto-generated
    console.log(Resource.Notes.name);
    

    Why good: No manual ARN passing, IAM permissions granted automatically, type-safe access via generated sst-env.d.ts, works across Functions, frontends, and containers

    See examples/core.md for linking patterns including custom linkables.


    Pattern 3: Live Lambda Development

    sst dev proxies Lambda invocations to your local machine for sub-10ms reload cycles.

    # Start live dev — deploys infra, proxies Lambda to local machine
    sst dev
    
    # Opens multiplexer: deploys resources, starts frontends, tunnels VPC
    
    // Detect dev mode in handler code
    const isLocal = process.env.SST_DEV === "true";
    

    Key behavior: Functions are replaced with stubs that forward events via AppSync to your local machine. Your local code runs as Node.js Workers. Changes reload instantly — no redeploy needed.

    Gotcha: Killing sst dev leaves stubs deployed. Subsequent Lambda invocations will timeout until you run sst dev again or sst deploy to replace stubs with real code.

    See examples/core.md for dev workflow and debugging setup.


    Pattern 4: AWS Components

    SST provides high-level components for common AWS services. Each handles IAM, logging, and configuration automatically.

    ComponentAWS ServiceUse Case
    sst.aws.FunctionLambdaServerless functions
    sst.aws.ApiGatewayV2API Gateway v2HTTP APIs with routes
    sst.aws.DynamoDynamoDBNoSQL database
    sst.aws.BucketS3Object storage
    sst.aws.QueueSQSMessage queues
    sst.aws.TopicSNSPub/sub messaging
    sst.aws.CronEventBridgeScheduled tasks
    sst.aws.VpcVPCNetwork isolation
    sst.aws.ClusterECSContainer workloads
    sst.aws.PostgresRDS PostgresRelational database
    sst.aws.NextjsLambda + CloudFrontNext.js deployment
    sst.aws.RemixLambda + CloudFrontRemix deployment
    sst.aws.AstroLambda + CloudFrontAstro deployment
    sst.aws.StaticSiteS3 + CloudFrontStatic site hosting
    sst.aws.RouterCloudFrontURL routing

    See examples/api-data.md for API, database, storage, queue, and cron patterns.


    Pattern 5: Secrets Management

    Secrets are encrypted and stored in S3, injected into function bundles at deploy time.

    # Set a secret (prompts for value)
    sst secret set DATABASE_URL
    
    # Set a secret with value inline
    sst secret set STRIPE_KEY sk_live_xxx
    
    # Load secrets from a file
    sst secret load .env.production
    
    # List all secrets
    sst secret list
    
    // Access secrets via resource linking
    import { Resource } from "sst";
    const stripeKey = Resource.StripeKey.value;
    

    Gotcha: Secrets are per-stage. Set them for each stage separately. Use --fallback to set a default across all stages.

    See examples/core.md for secrets with Linkable pattern.


    Pattern 6: Transforms

    Customize underlying Pulumi resources when SST defaults aren't enough.

    // Per-component transform
    new sst.aws.Function("Api", {
      handler: "src/api.handler",
      transform: {
        function: (args) => {
          args.tracingConfig = { mode: "Active" };
        },
      },
    });
    
    // Global transform — applies to ALL components of a type
    $transform(sst.aws.Function, (args) => {
      args.environment ??= {};
      args.environment.variables ??= {};
      args.environment.variables.STAGE = $app.stage;
    });
    

    Why good: Transforms let you customize any underlying resource property without abandoning SST's abstractions. Global transforms set defaults across all components.

    See examples/deployment.md for transform patterns.


    Pattern 7: Multi-Stage Environments

    Every stage is a fully isolated deployment. Use $app.stage for conditional configuration.

    async run() {
      const isProd = $app.stage === "production";
    
      const table = new sst.aws.Dynamo("Notes", {
        fields: { userId: "string", noteId: "string" },
        primaryIndex: { hashKey: "userId", rangeKey: "noteId" },
        deletionProtection: isProd,
      });
    }
    
    # Personal dev stage (default)
    sst dev
    
    # Deploy to staging
    sst deploy --stage staging
    
    # Deploy to production
    sst deploy --stage production
    

    See examples/deployment.md for multi-stage patterns with removal policies.


    <decision_framework>

    Decision Framework

    Choosing an SST Component

    What are you building?
      |
      +-- HTTP API
      |     +-- Simple routes with Lambda handlers --> sst.aws.ApiGatewayV2
      |     +-- Need WebSocket support --> sst.aws.ApiGatewayWebSocket
      |     +-- URL routing / CDN --> sst.aws.Router
      |
      +-- Data storage
      |     +-- Key-value / document data --> sst.aws.Dynamo
      |     +-- Relational data with SQL --> sst.aws.Postgres
      |     +-- File/blob storage --> sst.aws.Bucket
      |
      +-- Async processing
      |     +-- Point-to-point messaging --> sst.aws.Queue (SQS)
      |     +-- Fan-out to multiple subscribers --> sst.aws.Topic (SNS)
      |     +-- Scheduled tasks --> sst.aws.Cron
      |
      +-- Compute
      |     +-- Serverless function --> sst.aws.Function
      |     +-- Container workload --> sst.aws.Cluster + sst.aws.Service
      |     +-- Long-running background job --> sst.aws.Function (up to 15min)
      |
      +-- Full-stack frontend
            +-- Next.js --> sst.aws.Nextjs
            +-- Remix --> sst.aws.Remix
            +-- Astro --> sst.aws.Astro
            +-- SvelteKit --> sst.aws.SvelteKit
            +-- SolidStart --> sst.aws.SolidStart
            +-- Static HTML/JS --> sst.aws.StaticSite
    

    When to Use Transforms vs Raw Pulumi

    Need to set a property on an SST component?
      |
      +-- Property exists on the SST component args --> Use the SST property directly
      |
      +-- Property exists only on the underlying AWS resource --> Use transform
      |
      +-- Need to set a default across ALL instances of a component --> Use $transform()
      |
      +-- No SST component exists for this AWS service --> Use raw Pulumi resource
            +-- Need to link it? --> Use sst.Linkable.wrap() or new sst.Linkable()
    

    </decision_framework>


    <red_flags>

    RED FLAGS

    High Priority Issues:

    • Hardcoding ARNs, table names, or bucket names instead of using resource linking (link + Resource.*) — defeats SST's type-safe wiring and breaks across stages
    • Sharing resource names across stages without $app.stage prefix — causes resource conflicts and accidental cross-stage access
    • Putting secrets in sst.config.ts or committed .env files instead of using sst secret set — secrets leak to version control
    • Using sst dev for shared environments (staging, production) — stubs proxy to a single developer's machine, breaking for everyone else
    • Creating raw Pulumi resources when an equivalent sst.aws.* component exists — loses SST's linking, permissions, and defaults

    Medium Priority Issues:

    • Not setting removal: "retain" and protect: true for production stages — accidental sst remove deletes all data
    • Missing /// <reference path="./.sst/platform/config.d.ts" /> at top of sst.config.ts — loses type checking for $app, $transform, etc.
    • Using .env files for secrets instead of sst secret.env files aren't encrypted and must be managed manually per stage
    • Not running sst deploy after finishing sst dev session — stubs remain deployed and Lambda invocations timeout

    Common Mistakes:

    • Forgetting that sst dev stubs persist after you stop the process — always redeploy or re-run sst dev
    • Using $app.stage in runtime code — it's only available in sst.config.ts, use Resource.* or env vars for runtime stage awareness
    • Trying to use SST resource linking in client-side frontend code — links are server-side only (SSR functions, API routes)
    • Expecting sst dev to emulate AWS locally — it doesn't; it proxies to real AWS resources in your account

    Gotchas & Edge Cases:

    • Pulumi Outputs cannot be used directly in string templates — use $concat() or $interpolate instead of template literals
    • sst dev multiplexer starts frontends automatically — you don't need to run next dev or vite dev separately
    • FIFO queues require .fifo suffix in names — SST handles this automatically but be aware when referencing externally
    • .env and .env.<stage> files are loaded automatically — .env takes precedence over stage-specific files
    • Frontend framework links (Next.js, Remix) only work server-side — client components cannot access Resource.*
    • Layers specified in Function config are not applied during sst dev — local execution skips layers
    • The removal setting in app() controls what happens when you run sst remove"remove" deletes resources, "retain" keeps them, "retain-all" keeps everything including logs

    </red_flags>


    <critical_reminders>

    CRITICAL REMINDERS

    All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

    (You MUST use resource linking (link + Resource.*) to connect components — NEVER hardcode ARNs, table names, or bucket names)

    (You MUST use $app.stage for environment isolation — NEVER share resources across stages without explicit intent)

    (You MUST use sst dev for local development — it provides live Lambda proxying with sub-10ms reloads against real AWS resources)

    (You MUST use sst secret set for secrets — NEVER put secrets in sst.config.ts, .env files committed to git, or environment variables)

    (You MUST use transform to customize underlying resources — NEVER reach for raw Pulumi resources when an SST component exists)

    Failure to follow these rules will cause cross-stage resource conflicts, leaked secrets, broken type safety, and unnecessary infrastructure complexity.

    </critical_reminders>

    Frequently asked questions

    What to verify before installation and use

    What does the infra-iac-sst source document cover?

    Quick Guide: SST v3 (Ion) is TypeScript-first infrastructure-as-code for AWS, powered by Pulumi/Terraform (not CDK/CloudFormation). Define your entire app in sst.config.ts using high-level components (sst.aws.Function, sst.aws.ApiGatewayV2, sst.aws.Bucket, sst.aws.Dynamo, etc.).…

    How do I install infra-iac-sst?

    The source record exposes this install command: npx skills add https://github.com/agents-inc/skills --skill "src/skills/infra-iac-sst". Inspect the command and pinned source before running it.

    Which permission-related actions were detected?

    Static rules flagged read-files in the source; the page lists the matching lines and excerpts.

    Alternatives

    Compare before choosing