Generated banner for Launch With AWS
Generated logo for Launch With AWS

Launch With AWS

AWSOfficialPublished by AWS

  • Skill
  • Workflow
  • Cloud and DevOps
  • Apache-2.0
  • Medium risk
  • Has scripts

From the author

Migrates vibe-coded web applications to AWS. Handles the full workflow from analysis through migration to deployment, producing deployable AWS Blocks infrastructure code. Supports full-stack apps built with vibe-coding platforms (Lovable, Bolt.new, Replit) and frontend web applications and websites: React, Vue, Angular, Next.js, Nuxt, Astro, SvelteKit, Gatsby, Vite, Svelte, Solid, Docusaurus, and others (static sites, SPAs, and SSR frameworks with static export). Triggers on: launch with AWS, launch on AWS, deploy to AWS, migrate to AWS, host my app on AWS, move my app to AWS, transfer my app to AWS. Activates when the user wants to migrate a vibe-coded app or frontend web app to AWS, even if they don't say 'migrate' explicitly.
— the description by AWS

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

Launch with AWS provides a structured, automated workflow to migrate full-stack web applications and frontend projects to AWS. It analyzes the source code, generates a migration plan with cost estimates, and produces deployable AWS Blocks infrastructure code. The process includes secure authentication, source code analysis, and a guided execution phase that results in a migration snapshot ready for local application and deployment via generated instructions.

What it does

  • Analyzes web application source code to determine migration requirements.
  • Generates detailed migration plans and AWS cost estimates.
  • Produces AWS Blocks infrastructure code for target applications.
  • Handles secure authentication and session management for AWS migration services.
  • Provides a guided 3-way merge process to integrate migrated code into existing repositories.
  • Generates project-specific deployment instructions via DEPLOY.md.

When to use it

  • When you need to move a vibe-coded or frontend web application to AWS.
  • When you want to transition from platforms like Lovable, Bolt.new, or Replit to AWS-native infrastructure.
  • When you require a structured, step-by-step migration path for static sites, SPAs, or SSR frameworks.
  • When you need to estimate the AWS infrastructure costs for hosting your existing web application.

Advantages

  • Automates the complex process of infrastructure definition and migration planning.
  • Provides clear cost visibility before committing to a migration.
  • Maintains security by using encrypted data handling and avoiding AI training on user code.
  • Supports a wide range of modern web frameworks and platforms.
  • Ensures a clean integration process through git-based migration branches.

Usage examples

“Migrate my Replit web app to AWS.”
The agent initiates the authentication flow, analyzes the Replit project structure, and prepares a migration plan for AWS Lambda and Aurora Serverless.
“How much would it cost to host my Next.js site on AWS?”
The agent analyzes the project, calculates the estimated monthly AWS costs, and presents a breakdown of the required services.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/aws/launch-with-aws/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip launch-with-aws.zip -d .agents/skills

Documentation by AWS

Launch with AWS

Drives an AWS migration end-to-end using CLI scripts. Takes a user's web application, analyzes it, generates a migration plan with cost estimate, and delivers deployable AWS Blocks infrastructure code.

The AWS MCP server is recommended but is not required. This skill works standalone via its CLI scripts in any agent environment.

Script Invocation

All commands are run via:

python3 scripts/launch_with_aws.py <command> [args...]

where scripts/ is relative to this skill directory. The agent MUST set the working directory to the skill root before invoking commands.

Required files: launch_with_aws.py, launch_config.py, auth.py, auth_callback_server.py, launch_api_client.py, archive.py, service model. When loaded via MCP, fetch all and write to a temp directory preserving structure before invoking.

Each command outputs JSON to stdout on success, or exits non-zero with a JSON error on stderr.

Two global flags may be added to any command: --region <region> selects the region the service runs the migration in, and --aws-mcp-url <url> passes the URL of the AWS MCP server the agent is connected to. See step 2.

Dependencies: Python 3.10+ and boto3. The script checks both on startup and exits with a clear error if either is missing.

Supported Application Types

Full-stack apps built with vibe-coding platforms, and frontend web applications and websites (static sites, SPAs, and SSR frameworks with static export).

Origin PlatformWhat it covers
LovableLovable-generated full-stack apps (React + Supabase)
Bolt.newBolt.new-generated full-stack apps (React + Supabase)
ReplitReplit-hosted full-stack apps (React + Express.js + PostgreSQL)
FrameworkExamples
React ecosystemReact, CRA, Vite + React, Gatsby, Docusaurus
Vue ecosystemVue, Nuxt (static export), VitePress
AngularAngular
Svelte ecosystemSvelte, SvelteKit (static export)
SSR with static exportNext.js, Nuxt, Astro, SvelteKit
Other modern frameworksAstro, Solid, Preact, Lit, Eleventy
Vite (generic)Any Vite-based app

Other frameworks may also work. If the user's app doesn't match these, see Unsupported Application Handling below.

What Gets Migrated vs. What Stays

Lovable / Bolt.new apps (Supabase-backed):

ComponentWhat happens
Frontend & hostingMigrated to AWS (S3 + CloudFront + Lambda)
Edge functions / server functionsMigrated to AWS Lambda
AI calls (e.g. Lovable AI Gateway)Migrated to Amazon Bedrock
Database (Supabase DB)Stays on Supabase — not migrated
Auth (Supabase Auth)Stays on Supabase — not migrated
Storage & RealtimeStays on Supabase — not migrated

The app continues to call Supabase for database, auth, storage, and realtime from the AWS-hosted application.

Replit apps (Express.js + PostgreSQL):

ComponentWhat happens
Frontend & hostingMigrated to AWS (S3 + CloudFront + Lambda)
Server logic (Express.js)Migrated to AWS Lambda (API Gateway)
Database (PostgreSQL)Schema and code migrated to AWS (Aurora Serverless / DynamoDB). Existing data is NOT migrated — customers must export and import their data separately.
Auth (Replit Auth)Code migrated to AWS (Cognito). Existing user accounts are NOT migrated — customers must re-create or invite users in Cognito.
Realtime (WebSockets)Migrated to AWS (API Gateway WebSocket)
File storageMigrated to AWS (S3). Existing files are NOT migrated.

Replit app infrastructure and code are migrated to AWS-native services, but existing data, user accounts, and files must be migrated separately by the customer.

Input Resolution

Resolve the user's input to a local directory path:

  • If the user provides a local path: pass that path directly.

  • If the user provides a GitHub URL: clone the repository locally and use that directory.

  • If neither is provided: use the current working directory. If it doesn't look like an app directory, ask the user for the path.

Flow

Run the script commands in order, surfacing results to the user at each step:

1. Authentication
python3 scripts/launch_with_aws.py auth-start

Always run first. Returns immediately with JSON:

  • If already authenticated: {"authenticated": true, "reusedCachedSession": true, "baseUrl": "..."}

  • If silent refresh succeeded: {"authenticated": true, "reusedCachedSession": false, "baseUrl": "..."}

  • If interactive sign-in is needed: {"authenticated": false, "signInUrl": "https://...", "pid": 12345, "port": 54321, "baseUrl": "..."}

When authenticated is false, immediately display the signInUrl to the user (so they can open it in their browser) and call auth-wait in the same response:

python3 scripts/launch_with_aws.py auth-wait <pid>

where <pid> is the pid value from the auth-start response. This blocks until the user completes browser sign-in (or times out after 600s). Returns {"authenticated": true, "baseUrl": "..."} on success.

Sessions are capped at 90 days even if the identity provider does not set an expiration; after that the interactive flow is required again.

To check the current session without authenticating, or to sign out:

python3 scripts/launch_with_aws.py session-status
python3 scripts/launch_with_aws.py sign-out

session-status reports whether a session exists and how long until the token and overall session expire. sign-out best-effort revokes the refresh token and deletes the local ~/.launch-with-aws/session.json. On shared or untrusted workstations, run sign-out when finished.

2. Create Launch

For a local directory, present this data-handling confirmation verbatim and wait for explicit approval:

Your source code will be uploaded to the Launch with AWS service in [regionName], [region] ([sourceLabel]) to analyze your application and generate a migration plan. If you later approve execution, an AWS-hosted agent will modify a copy of your source code according to the plan and produce a migrated snapshot for you to download. Your uploaded source code and associated launch data are encrypted in transit and at rest and retained for up to 48 hours for recovery. Your data is never used to train AI models. We exclude Git history, Git-ignored files, and files matching common sensitive-file patterns. Sensitive-file filtering is best effort; review your project for secrets. Continue? Or reply with [otherRegions regionName] to run the migration there instead.

Fill in the region fields from resolve-region, verbatim, and offer each otherRegions entry as an alternative. If the agent is connected to an AWS MCP server, pass that server's URL verbatim. The script reads the region from it and decides whether it counts as a signal.

python3 scripts/launch_with_aws.py resolve-region [--aws-mcp-url https://aws-mcp.<region>.api.aws/mcp]

Returns {"region": ..., "regionName": ..., "source": ..., "sourceLabel": ..., "baseUrl": ..., "otherRegions": [{"region": ..., "regionName": ...}]}.

Do NOT call create-launch until the user explicitly confirms; a missing or ambiguous response means no. Naming one of otherRegions is both a region choice and approval — pass its region as --region and do not ask again.

python3 scripts/launch_with_aws.py create-launch <app-directory> [name] --region <region>

Zips the directory, uploads it, then creates the launch. Returns the full launch object including launch.launchId and the region it was created in, which becomes the user's saved default. A launch exists only in its own region — pass its --region on every later command.

The launch starts in analyzing status and automatically progresses through analysis and planning.

3. Poll Launch Status
python3 scripts/launch_with_aws.py get-launch-status <launch-id> --region <region>

Poll until status is planned (ready for execution) or failed; report any other status to the user. Key status progression:

  • analyzing → detecting app type and dependencies

  • planning → generating migration plan

  • planned → ready for execution

  • executing → deployment in progress

  • completed → done

  • failed → check failureReason

4. Get Full Launch Details & Confirm
python3 scripts/launch_with_aws.py get-launch <launch-id> plan,cost_estimate --region <region>

Get full launch details. Optional second argument is a comma-separated include list: analysis, plan, execution, cost_estimate, download_url.

Present the cost estimate and plan to the user. The costEstimate field in the response contains estimatedMonthlyCost, region, and a services breakdown with per-service costs.

Confirmation Gate — present and wait for explicit approval:

Migration Summary

  • App type: [detected type from analysis]

  • Architecture: [target architecture from plan]

  • Estimated monthly cost: $X.XX/month ([costEstimate.region] pricing)

  • Migration runs in: [regionName], [region]

Ready to proceed? This will execute the migration in an AWS-managed environment (no cost to you) and produce the migrated snapshot for you to download.

Do NOT call start-launch-execution until the user explicitly confirms.

5. Start Execution
python3 scripts/launch_with_aws.py start-launch-execution <launch-id> --region <region>

Starts deployment. Then poll with get-launch-status until status is completed or failed. Sleep at least 30 seconds between polls.

6. Download
python3 scripts/launch_with_aws.py get-launch-download-url <launch-id> --region <region>

Always present the full download URL to the user — they may need it to download the migrated snapshot directly or for reference.

7. List or Delete Launches
python3 scripts/launch_with_aws.py list-launches
python3 scripts/launch_with_aws.py delete-launch <launch-id> --region <region>

list-launches queries both regions and returns items with a region on each launch; add --region to query one. A region that cannot be reached is reported under errors instead of failing the command, unless every queried region fails, in which case the command exits with that error.

8. Post-Migration: Apply Migrated Code Locally

After obtaining the download URL (adapt commands for the user's platform if not POSIX):

Step A: Download and unpack
curl -L -o /tmp/migration-snapshot.zip "<download_url>"
mkdir -p /tmp/migration-output
unzip -o /tmp/migration-snapshot.zip -d /tmp/migration-output
Step B: Prepare the local workspace

Ensure the user's working directory is clean:

cd <user-app-directory>
git status

If there are uncommitted changes, ask the user to commit or stash first. Do NOT proceed with a dirty working tree.

Step C: Apply migration (3-way merge)

Create a migration branch and overlay the migrated files:

cd <user-app-directory>
git checkout -b aws-migration
rsync -a /tmp/migration-output/ .
git status
git diff --stat

Review the changes with the user. Key additions to highlight:

  • aws-blocks/ — AWS Blocks infrastructure definition

  • DEPLOY.md — deployment instructions

  • Any modified config files

If there are conflicts with the user's existing files, present them and ask how to resolve.

Step D: Follow DEPLOY.md

Read the DEPLOY.md file in the project root and follow its instructions to deploy the app to the user's AWS account. Typical steps:

  1. AWS authentication (aws login --profile aws-migrate --region us-east-1)

  2. CDK bootstrap (first-time only): npm install && npx cdk bootstrap

  3. Deploy: npx cdk deploy --all --progress events

  4. Verify the CloudFront URL that CDK prints on completion.

Important: Always read DEPLOY.md from the migrated output — it is generated specifically for this app and architecture. Do not assume deployment steps from memory.

Unsupported Application Handling

If a launch fails during analysis with a failureReason indicating an unsupported app type (or the user's stack doesn't match the supported list):

  1. Tell the user: "This app type isn't directly supported by Launch with AWS yet. Let me search for other skills that can help deploy this kind of application."

  2. Search for relevant skills based on the app type (e.g. aws-serverless, aws-containers, aws-database, aws-deployment, aws-cdk, aws-ai-ml).

Files

scripts/launch_config.py

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

"""Configuration, constants, and models for launch-with-aws scripts."""

import ipaddress
import json
import logging
import os
import re
import socket
import stat
import tempfile
from dataclasses import asdict, dataclass
from typing import List, Optional
from urllib.parse import urlparse

# ── Constants ────────────────────────────────────────────────────────────

DEFAULT_REGION = "us-east-1"
EU_REGION = "eu-central-1"

# Regions the service runs migrations in, with the names shown to the customer.
SUPPORTED_REGIONS = {
    DEFAULT_REGION: "US East (N. Virginia)",
    EU_REGION: "Europe (Frankfurt)",
}

DEFAULT_BASE_URL = f"https://launch-with-aws.{DEFAULT_REGION}.api.aws"

ENV_BASE_URL = "LAUNCH_WITH_AWS_BASE_URL"
ENV_IDC_ISSUER_URL = "LAUNCH_WITH_AWS_IDC_ISSUER_URL"
ENV_SCOPES = "LAUNCH_WITH_AWS_SCOPES"
ENV_REGION = "LAUNCH_WITH_AWS_REGION"

# How each region signal is described to the customer in the upload confirmation.
REGION_SOURCE_LABELS = {
    "explicit": "the region you asked for",
    "environment": f"your {ENV_REGION} setting",
    "saved": "your saved choice",
    "aws-mcp": "your AWS MCP server configuration",
    "aws-profile": "your AWS profile region",
    "default": "the default",
}

SSO_OIDC_REGION = "us-east-1"
IDC_ISSUER_URL = "https://view.awsapps.com/start"

CLIENT_NAME = "Launch with AWS Agent Skill"
SCOPES = ["launch:access"]
TOKEN_EXPIRY_BUFFER_SECS = 300
CALLBACK_TIMEOUT_SECS = 600.0
DEFAULT_TOKEN_LIFETIME_SECS = 28800

# Maximum local session lifetime; re-authentication is required after this.
MAX_SESSION_LIFETIME_SECS = 90 * 24 * 3600  # 90 days

SESSION_DIR = "~/.launch-with-aws"
SESSION_FILE_NAME = "session.json"
# The region the customer confirmed, kept out of the session file so signing out
# does not reset a data-residency choice.
CONFIG_FILE_NAME = "config.json"

AUTH_WAIT_POLL_INTERVAL_SECS = 1.0

REQUEST_TIMEOUT_SECS = 120.0
UPLOAD_TIMEOUT_SECS = 300.0
GITHUB_ZIPBALL_TIMEOUT_SECS = 120.0

DEFAULT_COST_ESTIMATE_REGION = "us-east-1"

# Archive limits, checked against ZIP central-directory metadata (no
# decompression) plus a streamed compressed-size cap.
MAX_ARCHIVE_BYTES = 500 * 1024 * 1024  # 500 MiB compressed
MAX_ARCHIVE_ENTRIES = 100_000
MAX_UNCOMPRESSED_BYTES = 2 * 1024 * 1024 * 1024  # 2 GiB total decompressed
MAX_ENTRY_UNCOMPRESSED_BYTES = 100 * 1024 * 1024  # 100 MiB per entry
MAX_COMPRESSION_RATIO = 100  # decompressed/compressed per entry

# ── Models ───────────────────────────────────────────────────────────────


@dataclass
class ClientCredentials:
    """OIDC client registration plus the derived authorize/token endpoints."""

    client_id: str
    client_secret: str
    client_expires_at: int
    authorize_endpoint: str
    token_endpoint: str
    scopes: List[str]


@dataclass
class StoredSession(ClientCredentials):
    """A persisted session: client registration plus the current token pair."""

    access_token: str = ""
    refresh_token: str = ""
    token_expires_at: int = 0

    def to_json(self, indent: int = 2) -> str:
        return json.dumps(asdict(self), indent=indent)

    @classmethod
    def from_json(cls, text: str) -> "StoredSession":
        return cls(**json.loads(text))


# ── Runtime config ───────────────────────────────────────────────────────

logger = logging.getLogger(__name__)

_ALLOWED_HOST_SUFFIXES = (".api.aws", ".amazonaws.com")


class ConfigError(Exception):
    """Raised when configuration is invalid or unsafe."""


def _validate_base_url(url: str) -> str:
    """Validate and return a sanitized base URL.

    Rejects non-HTTPS schemes, hosts outside the AWS domain allowlist,
    and hosts that resolve to private/loopback/link-local addresses.
    """
    parsed = urlparse(url)

    if parsed.scheme != "https":
        raise ConfigError(
            f"Invalid {ENV_BASE_URL}: scheme must be https, got {parsed.scheme!r}. "
            "Refusing to send credentials over a non-HTTPS connection."
        )

    hostname = parsed.hostname
    if not hostname:
        raise ConfigError(f"Invalid {ENV_BASE_URL}: no hostname in {url!r}.")

    if not any(
        hostname == suffix.lstrip(".") or hostname.endswith(suffix)
        for suffix in _ALLOWED_HOST_SUFFIXES
    ):
        raise ConfigError(
            f"Invalid {ENV_BASE_URL}: host {hostname!r} is not in the allowed "
            f'domains ({", ".join(_ALLOWED_HOST_SUFFIXES)}). '
            "Only official AWS endpoints are permitted."
        )

    try:
        resolved = socket.getaddrinfo(hostname, None)
    except socket.gaierror as err:
        raise ConfigError(
            f"Invalid {ENV_BASE_URL}: DNS resolution failed for {hostname!r}: {err}. "
            "Refusing to proceed with an unresolvable host."
        ) from err

    for _family, _type, _proto, _canonname, sockaddr in resolved:
        ip = ipaddress.ip_address(sockaddr[0])
        if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved:
            raise ConfigError(
                f"Invalid {ENV_BASE_URL}: host {hostname!r} resolves to "
                f"private/loopback/link-local address {ip}. "
                "Refusing to send credentials to a non-public address."
            )

    return url.rstrip("/")


# IAM Identity Center issuer hosts accepted for the issuer URL override.
_ALLOWED_ISSUER_HOST_SUFFIXES = (".amazonaws.com", ".awsapps.com")


def validate_issuer_url(url: str) -> str:
    """Validate an IdC issuer URL override, returning it unchanged if allowed.

    Only https URLs whose host is on an allowed issuer domain are accepted.
    """
    parsed = urlparse(url)

    if parsed.scheme != "https":
        raise ConfigError(
            f"Invalid {ENV_IDC_ISSUER_URL}: scheme must be https, got {parsed.scheme!r}. "
            "Refusing to anchor the authentication flow on a non-HTTPS issuer."
        )

    hostname = parsed.hostname
    if not hostname:
        raise ConfigError(f"Invalid {ENV_IDC_ISSUER_URL}: no hostname in {url!r}.")

    if not any(
        hostname == suffix.lstrip(".") or hostname.endswith(suffix)
        for suffix in _ALLOWED_ISSUER_HOST_SUFFIXES
    ):
        raise ConfigError(
            f"Invalid {ENV_IDC_ISSUER_URL}: host {hostname!r} is not in the allowed "
            f'issuer domains ({", ".join(_ALLOWED_ISSUER_HOST_SUFFIXES)}). '
            "Only official AWS IAM Identity Center endpoints are permitted."
        )

    return url


def resolve_issuer_url() -> str:
    """Return the IdC issuer URL, honoring a validated env-var override."""
    override = os.environ.get(ENV_IDC_ISSUER_URL)
    if override:
        validated = validate_issuer_url(override)
        logger.warning("Using non-default IdC issuer URL: %s", validated)
        return validated
    return IDC_ISSUER_URL


# ── Local state ──────────────────────────────────────────────────────────


def state_dir() -> str:
    return os.path.expanduser(SESSION_DIR)


def write_private_file(path: str, text: str) -> None:
    """Write text to an owner-only (0600) file in an owner-only directory.

    The write is atomic, so a crash mid-write cannot leave a truncated file.
    """
    directory = os.path.dirname(path)
    os.makedirs(directory, exist_ok=True)
    os.chmod(directory, stat.S_IRWXU)

    old_umask = os.umask(0o077)
    try:
        fd, tmp_path = tempfile.mkstemp(dir=directory, suffix=".tmp")
        with os.fdopen(fd, "w") as f:
            f.write(text)
        os.chmod(tmp_path, stat.S_IRUSR | stat.S_IWUSR)
        os.replace(tmp_path, path)
    finally:
        os.umask(old_umask)


# ── Region selection ─────────────────────────────────────────────────────


@dataclass
class ResolvedRegion:
    """A resolved region and the signal it came from, for the upload prompt."""

    region: str
    source: str

    @property
    def region_name(self) -> str:
        return SUPPORTED_REGIONS[self.region]

    @property
    def source_label(self) -> str:
        return REGION_SOURCE_LABELS[self.source]


def validate_region(region: str) -> str:
    """Return the region unchanged if the service runs migrations there."""
    if region not in SUPPORTED_REGIONS:
        raise ConfigError(
            f"Unsupported region {region!r}. Launch with AWS runs migrations in "
            f'{", ".join(SUPPORTED_REGIONS)}.'
        )
    return region


def base_url_for_region(region: str) -> str:
    """Return the regional API endpoint."""
    return f"https://launch-with-aws.{validate_region(region)}.api.aws"


def _config_file() -> str:
    return os.path.join(state_dir(), CONFIG_FILE_NAME)


def load_saved_region() -> Optional[str]:
    """Return the region confirmed on a previous run, if it is still supported."""
    try:
        with open(_config_file()) as f:
            region = json.load(f).get("region")
    except (OSError, ValueError, AttributeError):
        return None
    return region if region in SUPPORTED_REGIONS else None


def save_region(region: str) -> None:
    """Persist the customer's confirmed region for later runs."""
    validate_region(region)
    write_private_file(_config_file(), json.dumps({"region": region}, indent=2))


_AWS_MCP_HOST_RE = re.compile(r"^aws-mcp\.(?P<region>[a-z0-9-]+)\.api\.aws$")


def region_from_aws_mcp_url(url: str) -> Optional[str]:
    """Return the region an AWS MCP endpoint URL is for, or None if it is not one.

    Anchored on the whole host, so a lookalike domain cannot pass as a region.
    """
    try:
        hostname = urlparse(url).hostname or ""
    except ValueError:
        return None
    match = _AWS_MCP_HOST_RE.match(hostname)
    return match.group("region") if match else None


def _profile_region() -> Optional[str]:
    """Return the AWS region from AWS_REGION, AWS_DEFAULT_REGION, or ~/.aws/config.

    boto3 resolves the last two without credentials. A broken AWS config must not
    block a migration, so any failure just means "no signal".
    """
    # boto3 ignores AWS_REGION, though other AWS SDKs treat it as the standard.
    aws_region = os.environ.get("AWS_REGION")
    if aws_region:
        return aws_region
    try:
        import boto3

        return boto3.Session().region_name
    except Exception:
        logger.debug("Could not read the AWS profile region", exc_info=True)
        return None


def _cell_for_aws_region(aws_region: str) -> str:
    """Map any AWS region to the cell that serves it."""
    return EU_REGION if aws_region.startswith("eu-") else DEFAULT_REGION


def resolve_region(
    explicit: Optional[str] = None, aws_mcp_url: Optional[str] = None
) -> ResolvedRegion:
    """Resolve the region to run a migration in; the first signal found wins.

    The customer confirms whatever this returns before any code is uploaded.
    """
    if explicit:
        return ResolvedRegion(validate_region(explicit), "explicit")

    env_region = os.environ.get(ENV_REGION)
    if env_region:
        return ResolvedRegion(validate_region(env_region), "environment")

    saved = load_saved_region()
    if saved:
        return ResolvedRegion(saved, "saved")

    # Every AWS MCP setup path writes us-east-1, so only an EU endpoint there is a
    # deliberate customer choice; anything else says nothing about them.
    aws_mcp_region = region_from_aws_mcp_url(aws_mcp_url) if aws_mcp_url else None
    if aws_mcp_region and aws_mcp_region.startswith("eu-"):
        return ResolvedRegion(EU_REGION, "aws-mcp")

    profile_region = _profile_region()
    if profile_region:
        return ResolvedRegion(_cell_for_aws_region(profile_region), "aws-profile")

    return ResolvedRegion(DEFAULT_REGION, "default")


class Config:
    """Configuration loaded from environment variables."""

    def __init__(self, region: Optional[str] = None) -> None:
        self.region = validate_region(region) if region else resolve_region().region

        env_url = os.environ.get(ENV_BASE_URL)
        if env_url:
            self.base_url = _validate_base_url(env_url)
            logger.info("Using non-default base URL: %s", self.base_url)
        else:
            self.base_url = base_url_for_region(self.region)


def load_config(region: Optional[str] = None) -> Config:
    return Config(region)

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an MCP server, Needs a command-line tool, Needs Python, Needs Node.js

Security

What our scanner noticed· Medium risk

  • Phrasing that asks for actions without confirmation
  • References to credential files
  • Scripts that your agent may run

This skill includes scripts that your agent may run. Read them before you use it.

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
AWS
Publisher
AWS (Official)
Source
aws/agent-toolkit-for-aws · skills/core-skills/launch-with-aws · commit 0a218f8
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • NOTICE (added by AutoGineer from NOTICE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Also distributed in
aws/agent-toolkit-for-aws

AutoGineer is not affiliated with or endorsed by AWS.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download launch-with-aws.zip