From 996cc5f0eed0908552beb942f538addde1eeea56 Mon Sep 17 00:00:00 2001 From: George Tsiolis Date: Thu, 6 Aug 2026 22:13:38 +0300 Subject: [PATCH] Package LocalStack skills as a portable agent plugin --- .github/workflows/validate.yml | 25 +++ README.md | 117 +++++++++----- plugin.json | 24 +++ scripts/validate.sh | 38 +++++ skills/iac-deployment/SKILL.md | 193 ----------------------- skills/iam-policy-analyzer/SKILL.md | 168 -------------------- skills/localstack-deploy/SKILL.md | 172 +++++++++++++++++++++ skills/localstack-extensions/SKILL.md | 142 ++++++++--------- skills/localstack-iam/SKILL.md | 155 +++++++++++++++++++ skills/localstack-lifecycle/SKILL.md | 193 ----------------------- skills/localstack-logs/SKILL.md | 142 +++++++++++++++++ skills/localstack-state/SKILL.md | 154 +++++++++++++++++++ skills/localstack/SKILL.md | 148 ++++++++++++++++++ skills/logs-analysis/SKILL.md | 164 -------------------- skills/lstk-extensions/SKILL.md | 102 +++++++++++++ skills/state-management/SKILL.md | 211 -------------------------- 16 files changed, 1109 insertions(+), 1039 deletions(-) create mode 100644 .github/workflows/validate.yml create mode 100644 plugin.json create mode 100755 scripts/validate.sh delete mode 100644 skills/iac-deployment/SKILL.md delete mode 100644 skills/iam-policy-analyzer/SKILL.md create mode 100644 skills/localstack-deploy/SKILL.md create mode 100644 skills/localstack-iam/SKILL.md delete mode 100644 skills/localstack-lifecycle/SKILL.md create mode 100644 skills/localstack-logs/SKILL.md create mode 100644 skills/localstack-state/SKILL.md create mode 100644 skills/localstack/SKILL.md delete mode 100644 skills/logs-analysis/SKILL.md create mode 100644 skills/lstk-extensions/SKILL.md delete mode 100644 skills/state-management/SKILL.md diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..a0322f1 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,25 @@ +name: Validate Agent Plugin + +on: + pull_request: + push: + branches: + - main + +permissions: + contents: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + version: "0.11.16" + + - name: Validate portable plugin and skills + run: ./scripts/validate.sh diff --git a/README.md b/README.md index 4761810..d36d2c6 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,45 @@ -# LocalStack AI Skills +# LocalStack Agent Skills -AI Agent Skills for developing and testing cloud applications against [LocalStack](https://localstack.cloud) - the local cloud development platform. +Portable [Agent Skills](https://agentskills.io/) for developing and testing cloud applications with [LocalStack](https://localstack.cloud) through the [`lstk`](https://github.com/localstack/lstk) CLI. -## Overview +This repository is a skills-only [Agent Plugin](https://agent-plugins.org/) targeting the Agent Plugins v1.0.0 specification. It intentionally does not include `mcp.json`; LocalStack MCP integration is separate follow-up work. -This repository contains a collection of AI skills designed to help developers work more efficiently with LocalStack. These skills enable AI assistants to help with common LocalStack workflows, from managing the local environment to deploying infrastructure and analyzing logs. - -## Available Skills +## Available skills | Skill | Description | -|-------|-------------| -| [localstack-lifecycle](skills/localstack-lifecycle/) | Manage the emulator lifecycle with `lstk` (start, stop, status, restart, reset) | -| [iac-deployment](skills/iac-deployment/) | Deploy infrastructure using Terraform, CDK, CloudFormation, SAM, and Pulumi | -| [state-management](skills/state-management/) | Save, load, and manage LocalStack state with snapshots and Cloud Pods | -| [logs-analysis](skills/logs-analysis/) | Analyze LocalStack logs, identify errors, and debug issues | -| [iam-policy-analyzer](skills/iam-policy-analyzer/) | Analyze IAM policies and auto-generate least-privilege permissions | -| [localstack-extensions](skills/localstack-extensions/) | Manage LocalStack extensions and plugins (legacy CLI) | +| --- | --- | +| [localstack](skills/localstack/) | Start, stop, configure, and troubleshoot LocalStack emulators with `lstk` | +| [localstack-deploy](skills/localstack-deploy/) | Deploy and verify infrastructure through the `lstk` Terraform, CDK, SAM, and AWS CLI proxies | +| [localstack-state](skills/localstack-state/) | Save, load, inspect, and manage LocalStack snapshots and persistent state | +| [localstack-logs](skills/localstack-logs/) | Inspect emulator logs and diagnose AWS API or Lambda failures | +| [localstack-iam](skills/localstack-iam/) | Test IAM enforcement and derive least-privilege policies from observed behavior | +| [localstack-extensions](skills/localstack-extensions/) | Install, configure, and author in-emulator LocalStack Extensions | +| [lstk-extensions](skills/lstk-extensions/) | Use and author Git-style `lstk-` CLI extensions | + +## Use as an Agent Plugin + +Clone the repository and point a compatible client's local-plugin workflow at the repository root: + +```bash +git clone https://github.com/localstack/skills.git +``` + +The client discovers the root `plugin.json` and each immediate child of `skills/`. Agent Plugins v1 standardizes the package, but intentionally leaves installation and distribution commands to each client. See the [compatible clients](https://agent-plugins.org/compatible-clients) page for client-specific instructions. + +This step only prepares a locally loadable skills package. Marketplace publication and bundled MCP configuration are deliberately out of scope. + +## Install individual Agent Skills + +Clients supported by the Agent Skills CLI can install the collection or select individual skills: + +```bash +npx skills add https://github.com/localstack/skills +npx skills add https://github.com/localstack/skills --skill localstack-deploy +``` -## Installation +## Install with Claude Code -### Via the LocalStack standalone marketplace +The existing Claude marketplace compatibility layer remains available: ```bash claude plugin marketplace add localstack/skills @@ -28,45 +48,58 @@ claude plugin install localstack@localstack-dev ## Prerequisites -- Docker running on your machine -- A [LocalStack account](https://app.localstack.cloud/) and auth token -- The [`lstk` CLI](https://docs.localstack.cloud/aws/developer-tools/running-localstack/lstk/), the current LocalStack CLI: +- [`lstk`](https://github.com/localstack/lstk#installation) +- A Docker-API-compatible container runtime supported by `lstk` +- A LocalStack account and `LOCALSTACK_AUTH_TOKEN` for workflows that require authentication +- The standard AWS, Terraform, CDK, or SAM CLI when using the corresponding proxy skill - ```bash - # Homebrew (macOS/Linux) - brew install localstack/tap/lstk +### Optional extra CLIs - # npm - npm install -g @localstack/lstk +`lstk` does not cover every workflow yet. Install these only for the gaps they close: - # Authenticate - lstk login - ``` +| Tool | Install | Needed for | +| --- | --- | --- | +| `pulumilocal` | `pip install pulumi-local` | Pulumi deployments; `lstk` has no Pulumi proxy | +| `samlocal` | `pip install aws-sam-cli-local` | Image and container-based Lambda (ECR) deploys and nested CloudFormation stacks, which `lstk sam` does not support | +| legacy `localstack` CLI | `pip install localstack` | In-emulator LocalStack Extensions, and the `localstack aws iam stream` and `summary` policy generators | -- The tools you want `lstk` to proxy, on your `PATH`: [AWS CLI](https://aws.amazon.com/cli/), `terraform`, `cdk`, or `sam`. `lstk aws`, `lstk terraform`, `lstk cdk`, and `lstk sam` point them at LocalStack for you, replacing the `awslocal`, `tflocal`, `cdklocal`, and `samlocal` wrappers. +The legacy `localstack` CLI is deprecated and will be removed in a future version; use it only for the gaps above. It manages its own container, so stop one CLI's emulator before starting the other's. -### Optional extra CLIs +## Validate locally -The `lstk` CLI does not cover every workflow yet. Install these only if you need them: +Validation requires [`uv`](https://docs.astral.sh/uv/), Git, and network access to PyPI, GitHub, and `agent-plugins.org`. The script validates `plugin.json` against the canonical Agent Plugins schema and validates every skill with a pinned revision of the official `skills-ref` implementation: -| Tool | Install | Needed for | -|------|---------|-----------| -| `pulumilocal` | `pip install pulumi-local` | Pulumi deployments — `lstk` has no Pulumi proxy | -| `samlocal` | `pip install aws-sam-cli-local` | Image/container-based Lambda (ECR) deploys and nested CloudFormation stacks, which `lstk sam` does not support | -| legacy `localstack` CLI | `pip install localstack` | LocalStack Extensions, and the `localstack aws iam stream` / `summary` policy generators | +```bash +./scripts/validate.sh +``` -The legacy `localstack` CLI is deprecated and will be removed in a future version — use it only for the gaps listed above. It manages its own container, so stop one CLI's emulator before starting the other's. +If Claude Code is installed, also validate the compatibility package: -## Usage +```bash +claude plugin validate --strict . +``` -These skills are designed to be used with AI coding assistants that support the skills/commands interface. Each skill provides contextual guidance and commands for specific LocalStack workflows. +## Package layout + +```text +. +├── plugin.json +├── skills/ +│ └── / +│ └── SKILL.md +├── .claude-plugin/ +│ ├── plugin.json +│ └── marketplace.json +└── scripts/ + └── validate.sh +``` -## Related Projects +## Related projects -- [LocalStack](https://github.com/localstack/localstack) - The core LocalStack platform -- [LocalStack MCP Server](https://github.com/localstack/localstack-mcp-server) - Model Context Protocol server for LocalStack -- [LocalStack Documentation](https://docs.localstack.cloud/) +- [lstk](https://github.com/localstack/lstk) +- [LocalStack MCP Server](https://github.com/localstack/localstack-mcp-server) +- [LocalStack documentation](https://docs.localstack.cloud/) ## License -Apache License 2.0 - see [LICENSE](LICENSE) for details. +Apache License 2.0 — see [LICENSE](LICENSE). diff --git a/plugin.json b/plugin.json new file mode 100644 index 0000000..1d85df0 --- /dev/null +++ b/plugin.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "localstack", + "version": "1.0.0", + "description": "Portable agent skills for developing and testing cloud applications with LocalStack through lstk.", + "author": { + "name": "LocalStack" + }, + "homepage": "https://github.com/localstack/skills", + "repository": "https://github.com/localstack/skills", + "license": "Apache-2.0", + "keywords": [ + "localstack", + "cloud", + "aws", + "azure", + "snowflake", + "iac", + "terraform", + "cdk", + "testing", + "local-development" + ] +} diff --git a/scripts/validate.sh b/scripts/validate.sh new file mode 100755 index 0000000..1bda919 --- /dev/null +++ b/scripts/validate.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +plugin_schema="https://agent-plugins.org/schemas/1.0.0/plugin.schema.json" +check_jsonschema_version="0.37.4" +skills_ref_revision="217be548739f21d6008915c29aefe320ea1a90af" +skills_ref_source="git+https://github.com/agentskills/agentskills.git@${skills_ref_revision}#subdirectory=skills-ref" + +if ! command -v uvx >/dev/null 2>&1; then + echo "uvx is required; install uv from https://docs.astral.sh/uv/" >&2 + exit 1 +fi + +echo "Validating plugin.json" +uvx --from "check-jsonschema==${check_jsonschema_version}" check-jsonschema \ + --schemafile "$plugin_schema" \ + "$repo_root/plugin.json" + +skill_count=0 +for skill_dir in "$repo_root"/skills/*; do + [[ -d "$skill_dir" ]] || continue + if [[ ! -f "$skill_dir/SKILL.md" ]]; then + echo "missing SKILL.md in $skill_dir" >&2 + exit 1 + fi + + echo "Validating ${skill_dir#"$repo_root/"}" + uvx --from "$skills_ref_source" skills-ref validate "$skill_dir" + ((skill_count += 1)) +done + +if (( skill_count == 0 )); then + echo "no skills found under $repo_root/skills" >&2 + exit 1 +fi + +echo "Validated plugin.json and $skill_count skills" diff --git a/skills/iac-deployment/SKILL.md b/skills/iac-deployment/SKILL.md deleted file mode 100644 index fcce781..0000000 --- a/skills/iac-deployment/SKILL.md +++ /dev/null @@ -1,193 +0,0 @@ ---- -name: localstack-deploy -description: Deploy infrastructure to LocalStack using IaC tools. Use when users want to deploy Terraform, CDK, CloudFormation, SAM, or Pulumi to LocalStack, or need help with the lstk proxy commands (lstk terraform, lstk cdk, lstk sam, lstk aws) or the pulumilocal wrapper. ---- - -# Infrastructure as Code Deployment - -Deploy AWS infrastructure to LocalStack using popular IaC tools including Terraform, AWS CDK, CloudFormation, SAM, and Pulumi. - -## Capabilities - -- Deploy Terraform configurations to LocalStack -- Run AWS CDK deployments locally -- Deploy CloudFormation stacks -- Build and deploy AWS SAM applications -- Execute Pulumi programs against LocalStack -- Validate infrastructure before deployment - -## Prerequisites - -- The `lstk` CLI installed and the emulator running (`lstk start`) — see the `localstack` skill -- The underlying tool on your `PATH`: `terraform`, `cdk`, `sam`, or `aws`. `lstk` proxies them; it does not bundle them. - -`lstk` replaces the old `awslocal` / `tflocal` / `cdklocal` / `samlocal` wrappers — you no longer need to `pip install`/`npm install` them. Pulumi is the exception; see [Pulumi](#pulumi). - -## Terraform - -### Using `lstk terraform` (Preferred) - -`lstk terraform` (alias `lstk tf`) runs Terraform against LocalStack by generating a provider-override file, so your `.tf` files need no LocalStack-specific changes. - -```bash -lstk terraform init -lstk terraform plan -lstk terraform apply -auto-approve -lstk terraform destroy -auto-approve - -# Short alias -lstk tf apply -auto-approve -``` - -`lstk`-specific flags go **before** the Terraform subcommand: - -```bash -lstk terraform --region us-west-2 plan -lstk terraform --account 000000000000 apply -``` - -| Flag | Default | Notes | -|------|---------|-------| -| `--region ` | `us-east-1` | Falls back to `AWS_REGION` | -| `--account ` | `test` | 12 digits; falls back to `AWS_ACCESS_KEY_ID` | - -Useful environment variables: `AWS_ENDPOINT_URL`, `LSTK_TF_CMD` (binary name, default `terraform`), `LSTK_TF_OVERRIDE_FILE_NAME` (default `localstack_providers_override.tf`), `LSTK_TF_DRY_RUN`. - -`lstk terraform` targets the AWS emulator only. - -### Manual Provider Configuration (Fallback) - -Only use manual provider configuration if `lstk` cannot be used (for example, a CI image that only has `terraform`). This approach requires modifying your Terraform files: - -```hcl -# In your provider configuration: -provider "aws" { - access_key = "test" - secret_key = "test" - region = "us-east-1" - - endpoints { - s3 = "http://localhost:4566" - dynamodb = "http://localhost:4566" - lambda = "http://localhost:4566" - # Add other services as needed - } - - skip_credentials_validation = true - skip_metadata_api_check = true - skip_requesting_account_id = true -} -``` - -Note: When using manual configuration, you must list endpoints for each AWS service used in your configuration. - -## AWS CDK - -Requires AWS CDK CLI `2.177.0` or newer. - -```bash -# Bootstrap (first time only) -lstk cdk bootstrap - -# Deploy all stacks -lstk cdk deploy --all --require-approval never - -# Deploy a specific stack -lstk cdk deploy MyStack - -# Synthesize -lstk cdk synth - -# Destroy -lstk cdk destroy --all --force -``` - -`lstk cdk` accepts `--region ` (default `us-east-1`) before the CDK command. There is no `--account` flag — CDK always targets the default account `000000000000`. - -Useful environment variables: `AWS_ENDPOINT_URL`, `AWS_ENDPOINT_URL_S3`, `LSTK_CDK_CMD` (default `cdk`), `AWS_REGION`. - -## CloudFormation - -Use `lstk aws`, which proxies the host `aws` CLI with the endpoint, credentials, and region pre-configured. - -```bash -# Create stack -lstk aws cloudformation create-stack \ - --stack-name my-stack \ - --template-body file://template.yaml - -# Update stack -lstk aws cloudformation update-stack \ - --stack-name my-stack \ - --template-body file://template.yaml - -# Delete stack -lstk aws cloudformation delete-stack --stack-name my-stack - -# Describe stack -lstk aws cloudformation describe-stacks --stack-name my-stack -``` - -If you would rather use the plain `aws` CLI, run `lstk setup aws` once to write a `localstack` profile into `~/.aws/config` and `~/.aws/credentials`, then use `aws --profile localstack ...`. - -## AWS SAM - -Requires AWS SAM CLI `1.95.0` or newer. - -```bash -lstk sam build -lstk sam validate -lstk sam deploy -lstk sam --region us-west-2 deploy -``` - -`lstk sam` accepts `--region ` (default `us-east-1`) and `--account ` (default `000000000000`) before the SAM command. - -**Limitation:** image/container-based Lambda (ECR) deploys and nested CloudFormation stacks are not supported by `lstk sam`. For those workflows, install the `samlocal` wrapper (`pip install aws-sam-cli-local`) and use it instead. - -## Pulumi - -`lstk` has no Pulumi proxy command, so Pulumi still needs the `pulumilocal` wrapper. - -### Using `pulumilocal` (Preferred) - -```bash -# Requires Python/pip — this is an extra install beyond lstk -pip install pulumi-local - -# Use pulumilocal instead of pulumi - no config changes needed -pulumilocal preview -pulumilocal up --yes -pulumilocal destroy --yes -``` - -### Manual Configuration (Fallback) - -Only use manual configuration if `pulumilocal` cannot be installed (e.g., Python/pip is not available in the environment): - -```bash -# Configure Pulumi for LocalStack -pulumi config set aws:accessKey test -pulumi config set aws:secretKey test -pulumi config set aws:region us-east-1 -pulumi config set aws:endpoints '[{"s3":"http://localhost:4566"}]' -``` - -```bash -# Deploy with standard pulumi commands -pulumi preview -pulumi up --yes -pulumi destroy --yes -``` - -## Endpoint Resolution - -`lstk aws`, `lstk terraform`, `lstk cdk`, and `lstk sam` probe whether `localhost.localstack.cloud` resolves to `127.0.0.1` and use it when it does; otherwise they fall back to `127.0.0.1:4566`. Override with the `LOCALSTACK_HOST` environment variable. - -## Best Practices - -- Use the `lstk` proxy commands (`lstk terraform`, `lstk cdk`, `lstk sam`, `lstk aws`) rather than editing endpoints into your IaC files -- Test infrastructure changes locally before deploying to AWS -- Use `lstk start --persist` to retain state across LocalStack restarts -- Snapshot deployed infrastructure with `lstk save` so you can restore it instantly instead of re-deploying — see the `localstack-state` skill -- In CI, add `--non-interactive` to `lstk` commands and set `LOCALSTACK_AUTH_TOKEN` diff --git a/skills/iam-policy-analyzer/SKILL.md b/skills/iam-policy-analyzer/SKILL.md deleted file mode 100644 index b9228b8..0000000 --- a/skills/iam-policy-analyzer/SKILL.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -name: localstack-iam -description: Analyze and enforce IAM policies in LocalStack. Use when users want to enable IAM enforcement, detect permission violations, auto-generate least-privilege policies, or test IAM policies locally before deploying to AWS. ---- - -# IAM Policy Analyzer - -Analyze IAM policies, detect permission violations, and automatically generate least-privilege policies based on actual usage. - -## Capabilities - -- Enforce IAM policies locally -- Detect permission violations -- Auto-generate policies from access patterns -- Analyze existing policies for issues -- Test policies before deploying to AWS - -## Prerequisites - -- The `lstk` CLI, authenticated with a LocalStack account (`lstk login`, or `LOCALSTACK_AUTH_TOKEN` in CI) — see the `localstack` skill -- Optional: the legacy `localstack` CLI (`pip install localstack`) for the IAM policy stream — see [Auto-Generate Policies](#auto-generate-policies). `lstk` has no equivalent command yet. - -## IAM Enforcement Modes - -### Enable Enforcement - -`lstk` forwards host environment variables prefixed with `LOCALSTACK_`, so `ENFORCE_IAM` is set as `LOCALSTACK_ENFORCE_IAM`: - -```bash -# Soft mode - logs violations but allows requests -LOCALSTACK_ENFORCE_IAM=soft lstk start - -# Enforced mode - denies unauthorized requests -LOCALSTACK_ENFORCE_IAM=1 lstk start -``` - -To make enforcement the default for a project, use an environment profile in `config.toml` (keys inside a profile need no prefix): - -```toml -[[containers]] -type = "aws" -env = ["iam"] - -[env.iam] -ENFORCE_IAM = "soft" -``` - -### Configuration - -| Mode | Behavior | -|------|----------| -| Disabled (default) | No IAM checks | -| `soft` | Logs violations, allows requests | -| `1` / `enforced` | Full enforcement, denies unauthorized | - -## Creating IAM Resources - -`lstk aws` proxies the host `aws` CLI with the LocalStack endpoint, credentials, and region pre-configured. - -### Create a User with Policy - -```bash -# Create user -lstk aws iam create-user --user-name dev-user - -# Create access key -lstk aws iam create-access-key --user-name dev-user - -# Attach policy -lstk aws iam attach-user-policy \ - --user-name dev-user \ - --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess -``` - -### Create Custom Policy - -```bash -# Create policy from JSON file -lstk aws iam create-policy \ - --policy-name my-custom-policy \ - --policy-document file://policy.json -``` - -```json -// Example policy.json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:GetObject", - "s3:PutObject" - ], - "Resource": "arn:aws:s3:::my-bucket/*" - } - ] -} -``` - -## Policy Analysis - -### Detect Violations - -1. Enable soft enforcement mode -2. Run your application -3. Check logs for access denied messages - -```bash -# View IAM-related log entries (-v disables lstk's default log filtering) -lstk logs -v | grep -i "access denied" -lstk logs -v | grep -i "iam" -``` - -### Auto-Generate Policies - -The legacy `localstack` CLI can print the exact policy each request would need, which is far more reliable than reading logs. There is no `lstk` equivalent yet, so install the legacy CLI alongside `lstk` for this workflow: - -```bash -pip install localstack - -# Live stream of recommended policies as requests come in -localstack aws iam stream -localstack aws iam stream --format json - -# Aggregate summary of policies for all enforced requests -localstack aws iam summary -``` - -Workflow: - -1. Start with `LOCALSTACK_ENFORCE_IAM=soft lstk start` -2. Run `localstack aws iam stream` in a second terminal -3. Exercise your application -4. Collect the recommended statements and merge them into a minimal policy - -If the legacy CLI is not available, fall back to reading `lstk logs -v` for access-denied entries and building the policy from the observed actions and resources. - -## Testing Policies - -### Simulate Policy - -```bash -# Test if action would be allowed -lstk aws iam simulate-principal-policy \ - --policy-source-arn arn:aws:iam::000000000000:user/dev-user \ - --action-names s3:GetObject \ - --resource-arns arn:aws:s3:::my-bucket/file.txt -``` - -### Validate Policy - -```bash -# Check policy syntax -lstk aws accessanalyzer validate-policy \ - --policy-document file://policy.json \ - --policy-type IDENTITY_POLICY -``` - -## Best Practices - -- Start with soft enforcement to discover required permissions -- Use `localstack aws iam stream` rather than log grepping when generating policies -- Use least-privilege principles when creating policies -- Test policies locally before deploying to AWS -- Snapshot a known-good IAM setup with `lstk save` so you can restore it after experiments -- Regularly audit and refine policies based on actual usage -- Use IAM roles instead of users where possible diff --git a/skills/localstack-deploy/SKILL.md b/skills/localstack-deploy/SKILL.md new file mode 100644 index 0000000..551a411 --- /dev/null +++ b/skills/localstack-deploy/SKILL.md @@ -0,0 +1,172 @@ +--- +name: localstack-deploy +description: Deploy and verify AWS infrastructure through lstk's Terraform, CDK, SAM, and AWS CLI proxies, including CloudFormation stacks and the Pulumi gap that still needs pulumilocal. Use when running IaC or CloudFormation against LocalStack, deploying Pulumi to LocalStack, or replacing tflocal, cdklocal, samlocal, and awslocal workflows. +--- + +# Deploy infrastructure through lstk + +Prefer a first-party `lstk` proxy whenever one exists. It injects the LocalStack endpoint, credentials, account, and region while preserving the standard tool's arguments and exit code. + +## Prepare the AWS emulator + +```bash +lstk start --type aws +lstk status +``` + +Install the standard CLI required by the workflow: + +- Terraform or OpenTofu for `lstk terraform` +- AWS CDK 2.177.0 or newer for `lstk cdk` +- AWS SAM CLI 1.95.0 or newer for `lstk sam` +- AWS CLI for `lstk aws` + +Do not install the `tflocal`, `cdklocal`, `samlocal`, or `awslocal` wrappers when `lstk` already covers the workflow. + +## Terraform and OpenTofu + +Run the normal Terraform lifecycle: + +```bash +lstk terraform init +lstk terraform plan +lstk terraform apply +lstk terraform destroy +``` + +Place `lstk`-specific flags before the Terraform action: + +```bash +lstk terraform --region us-west-2 plan +lstk terraform --account 000000000123 apply +``` + +Use OpenTofu without changing the skill workflow: + +```bash +LSTK_TF_CMD=tofu lstk terraform plan +``` + +`--region` defaults to `us-east-1` and falls back to `AWS_REGION`. `--account` takes a 12-digit id, defaults to `test`, and falls back to `AWS_ACCESS_KEY_ID`. + +The Terraform proxy also reads: + +- `LSTK_TF_CMD` — Terraform binary to invoke, default `terraform` +- `LSTK_TF_OVERRIDE_FILE_NAME` — generated override file name, default `localstack_providers_override.tf` +- `LSTK_TF_DRY_RUN` — write the override file without running Terraform + +`lstk tf` is an alias for `lstk terraform`. Prefer the explicit form in documentation and automation. + +`lstk` creates a provider override automatically. Do not add hard-coded LocalStack endpoints to the user's Terraform files unless they explicitly need a portable manual configuration. + +## AWS CDK + +```bash +lstk cdk bootstrap +lstk cdk synth +lstk cdk deploy +lstk cdk destroy +``` + +Place the region flag before the action: + +```bash +lstk cdk --region us-west-2 deploy +``` + +CDK always uses LocalStack account `000000000000`; do not invent an `--account` workflow. + +Override the CDK binary with `LSTK_CDK_CMD`, default `cdk`. + +## AWS SAM + +```bash +lstk sam build +lstk sam validate +lstk sam deploy --guided +``` + +Place LocalStack flags before the SAM action: + +```bash +lstk sam --region us-west-2 deploy +``` + +Unlike `lstk cdk`, `lstk sam` does accept `--account ` for a 12-digit account id, default `000000000000`. Override the SAM binary with `LSTK_SAM_CMD`, default `sam`. + +`lstk sam` does not support image/container-based Lambda (ECR) deploys or nested CloudFormation stacks. Use the external `samlocal` wrapper for those workflows: + +```bash +pip install aws-sam-cli-local +``` + +## CloudFormation through the AWS CLI + +```bash +lstk aws cloudformation create-stack \ + --stack-name my-stack \ + --template-body file://template.yaml + +lstk aws cloudformation describe-stacks \ + --stack-name my-stack + +lstk aws cloudformation update-stack \ + --stack-name my-stack \ + --template-body file://template.yaml + +lstk aws cloudformation delete-stack \ + --stack-name my-stack +``` + +## Configure a profile for unwrapped tools + +SDKs, test harnesses, and scripts that cannot be invoked through `lstk aws` need a profile instead: + +```bash +lstk setup aws +``` + +This writes a `localstack` profile to `~/.aws/config` and `~/.aws/credentials` for use with `aws --profile localstack ...` or `AWS_PROFILE=localstack`. Add `--force` to overwrite an existing `localstack` profile without a prompt. + +## Pulumi boundary + +`lstk` does not currently provide a Pulumi proxy. Never invent `lstk pulumi`. Pulumi still needs the external `pulumilocal` wrapper, which requires Python and pip: + +```bash +pip install pulumi-local + +pulumilocal preview +pulumilocal up --yes +pulumilocal destroy --yes +``` + +`pulumilocal` rewrites the AWS endpoints itself, so the Pulumi program needs no LocalStack-specific configuration. Label it as an external fallback, not part of `lstk`. + +## Target an external emulator + +Put the global endpoint before the proxy command: + +```bash +lstk --endpoint-url https://example.localstack.cloud terraform plan +lstk --endpoint-url https://example.localstack.cloud cdk deploy +lstk --endpoint-url https://example.localstack.cloud sam deploy +``` + +The endpoint must identify an AWS emulator for these proxies. + +Automation that cannot place a flag before every command can set the same target with `LSTK_ENDPOINT_URL`, or with `AWS_ENDPOINT_URL`, which has lower precedence when both are set. + +`lstk cdk` and `lstk sam` also read `AWS_ENDPOINT_URL_S3`, which overrides the S3 endpoint alone. Set it alongside the endpoint variable on a host where `localhost.localstack.cloud` does not resolve: `lstk cdk` warns and falls back to `127.0.0.1` there, and CDK S3 asset operations such as `bootstrap` and asset deploys can fail without a virtual-host-capable address. + +## Verify the deployment + +Do not stop at a successful IaC exit code. Query the resources that matter: + +```bash +lstk status +lstk aws cloudformation describe-stacks +lstk aws s3 ls +lstk aws lambda list-functions +``` + +Before `apply`, `deploy`, `destroy`, or delete operations, surface the expected changes and obtain any approval the user requires. diff --git a/skills/localstack-extensions/SKILL.md b/skills/localstack-extensions/SKILL.md index 084e407..bebb82d 100644 --- a/skills/localstack-extensions/SKILL.md +++ b/skills/localstack-extensions/SKILL.md @@ -1,88 +1,87 @@ --- name: localstack-extensions -description: Manage LocalStack Extensions. Use when users want to install, uninstall, list, or configure LocalStack extensions, or develop custom extensions to extend LocalStack functionality. Extensions require the legacy localstack CLI, not lstk. +description: Install, configure, and author in-emulator LocalStack Extensions. Use when adding an Extension to the emulator, browsing the Extensions Library, developing a Python Extension, or debugging one that fails to load. Extensions require the legacy localstack CLI, not lstk. --- -# LocalStack Extensions +# Manage in-emulator LocalStack Extensions -Manage LocalStack Extensions to add custom functionality, integrate third-party tools, and extend LocalStack capabilities. +Extensions are Python packages that run inside the LocalStack emulator to add endpoints, integrate third-party tools, and extend platform behavior. -> **`lstk` does not support Extensions.** There is no `lstk extensions` command suite. Extension workflows must use the legacy `localstack` CLI for both installing extensions *and* starting the emulator — `lstk` keeps its own volume directory (`lstk volume path`, e.g. `~/Library/Caches/lstk/volume/localstack-aws`), separate from the legacy volume that extensions install into, so an emulator started by `lstk` will not load them. -> -> For everything else — lifecycle, IaC, snapshots, logs — prefer `lstk`. See the `localstack` skill. +`lstk` does not manage Extensions. There is no `lstk extensions` command suite, and `lstk` keeps its own volume directory (`lstk volume path`, for example `~/Library/Caches/lstk/volume/localstack-aws`) separate from the legacy volume that Extensions install into, so an emulator started by `lstk` will not load them. Extension workflows must use the legacy `localstack` CLI for both installing Extensions and starting the emulator. -## Capabilities +Prefer `lstk` for every other workflow: lifecycle, IaC, snapshots, and logs. See the `localstack` skill. For Git-style `lstk-` CLI extensions, which are a different mechanism, see the `lstk-extensions` skill. -- Install and manage LocalStack Extensions -- Discover available extensions -- Configure extension settings -- Develop custom extensions +## Check prerequisites -## Prerequisites - -The legacy CLI and, for the examples below, the `awslocal` wrapper: +Install the legacy CLI, and the `awslocal` wrapper if you want the shorter command form: ```bash pip install localstack pip install awscli-local # optional; or use: aws --endpoint-url=http://localhost:4566 ``` -Do not run `lstk start` and `localstack start` at the same time — each manages its own container and they will conflict on port 4566. Stop one before starting the other (`lstk stop` / `localstack stop`). +`localstack extensions init`, `install`, `uninstall`, and `list` run inside a container; with Docker stopped they fail with `Docker could not be found on the system.` The `dev` subcommands run on the host and do not need a container runtime. + +Do not run `lstk start` and `localstack start` at the same time. Each manages its own container and they conflict on port 4566. Stop one before starting the other with `lstk stop` or `localstack stop`. + +The legacy `localstack` CLI is deprecated and will be removed in a future version. Use it only for the workflows on this page. -## Extension Management +## Install and remove Extensions -### List Installed Extensions +The `localstack extensions` command group is a preview feature. Its own help text warns that the feature and the API may change, so confirm the available commands with `localstack extensions --help` rather than assuming a fixed list. + +Prepare the extensions environment inside the volume: + +```bash +localstack extensions init +``` + +It installs into `lib/extensions` under the volume directory resolved from `LOCALSTACK_VOLUME_DIR`. + +List what is installed: ```bash localstack extensions list ``` -### Install Extensions +Install from PyPI, a pinned version, or a Git repository: ```bash -# Install from PyPI localstack extensions install localstack-extension-name - -# Install specific version localstack extensions install localstack-extension-name==1.0.0 - -# Install from Git repository localstack extensions install "git+https://github.com/org/extension-repo.git" ``` -### Uninstall Extensions +Remove one: ```bash localstack extensions uninstall localstack-extension-name ``` -### Enable/Disable Extensions +Extensions are enabled once installed. Disable one for a single run with its environment variable: ```bash -# Extensions are enabled by default after installation -# Disable via environment variable EXTENSION_NAME_ENABLED=0 localstack start -d ``` -## Available Extensions +## Discover available Extensions -Browse the [Official Extensions Library](https://app.localstack.cloud/extensions/library) and the [Extensions documentation](https://docs.localstack.cloud/aws/capabilities/extensions/) for available extensions. +Browse the [Extensions Library](https://app.localstack.cloud/extensions/library) and the [Extensions documentation](https://docs.localstack.cloud/aws/capabilities/extensions/). -## Using Extensions +## Run an Extension -### MailHog Extension +Install the Extension, then start the emulator with the legacy CLI so it is loaded: ```bash -# Install localstack extensions install localstack-extension-mailhog - -# Start LocalStack with the legacy CLI so the extension is loaded localstack start -d +``` + +Reach the Extension's own interface and exercise the service it hooks: -# Access MailHog UI +```bash open http://localhost:8025 -# SES emails will be captured by MailHog awslocal ses send-email \ --from sender@example.com \ --to recipient@example.com \ @@ -90,19 +89,41 @@ awslocal ses send-email \ --text "Hello" ``` -## Developing Custom Extensions +## Configure an Extension -### Extension Structure +Pass environment variables to `localstack start`: +```bash +# General pattern +EXTENSION__=value localstack start -d + +# Example +EXTENSION_MAILHOG_PORT=8025 localstack start -d ``` + +The legacy CLI takes these variables without the `LOCALSTACK_` prefix that `lstk` requires. + +## Author an Extension + +Scaffold from the official extension template: + +```bash +localstack extensions dev new +``` + +The template is rendered with cookiecutter, so install that first with `pip install cookiecutter`. The new Extension is created in the current working directory. Pass `--template` to pick a template other than the default `basic`. + +Lay the package out so the Extension class is importable: + +```text my-extension/ ├── setup.py -├── my_extension/ -│ ├── __init__.py -│ └── extension.py +└── my_extension/ + ├── __init__.py + └── extension.py ``` -### Basic Extension +Subclass `Extension` and implement the hooks you need: ```python # extension.py @@ -122,36 +143,21 @@ class MyExtension(Extension): return {"message": "Hello from extension!"} ``` -### Install Local Extension +Install from the source tree and use the developer helpers while iterating. `install` takes a positional name; a `file://` prefix installs a distribution from disk, and `file://.` treats the current directory as one: ```bash -# Install in development mode -localstack extensions install -e ./my-extension +localstack extensions install file://. -# Developer mode helpers -localstack extensions dev list localstack extensions dev enable ./my-extension +localstack extensions dev list +localstack extensions dev disable ./my-extension ``` -## Configuration - -Extensions are configured via environment variables passed to `localstack start`: - -```bash -# General pattern -EXTENSION__=value localstack start -d - -# Example -EXTENSION_MAILHOG_PORT=8025 localstack start -d -``` - -Note that the legacy CLI takes these variables **without** the `LOCALSTACK_` prefix that `lstk` requires. - -## Troubleshooting +## Diagnose a failing Extension -- **Extension not loading**: Confirm you started the emulator with `localstack start`, not `lstk start` — `lstk` uses a different volume directory and will not see installed extensions -- **Port conflict on 4566**: an `lstk`-managed container may still be running; `lstk stop` first -- **Errors on startup**: check `localstack logs` for extension stack traces -- **Conflicts**: disable conflicting extensions -- **Version issues**: ensure the extension is compatible with your LocalStack version -- **Docker Compose users**: point `LOCALSTACK_VOLUME_DIR` at the LocalStack volume on your host (`~/.cache/localstack` on Linux, `~/Library/Caches/localstack` on macOS) so the CLI installs into the right place +- **Extension not loading**: confirm you started the emulator with `localstack start`, not `lstk start`. `lstk` uses a different volume directory and will not see installed Extensions. +- **Port conflict on 4566**: an `lstk`-managed container may still be running. Run `lstk stop` first. +- **Errors on startup**: check `localstack logs` for Extension stack traces. +- **Two Extensions interfering**: disable one to isolate the failure. +- **Version mismatch**: confirm the Extension supports your LocalStack version. +- **Docker Compose setups**: point `LOCALSTACK_VOLUME_DIR` at the LocalStack volume on your host, `~/.cache/localstack/volume` on Linux or `~/Library/Caches/localstack/volume` on macOS, so the CLI installs into the volume the emulator mounts. diff --git a/skills/localstack-iam/SKILL.md b/skills/localstack-iam/SKILL.md new file mode 100644 index 0000000..6f55ba6 --- /dev/null +++ b/skills/localstack-iam/SKILL.md @@ -0,0 +1,155 @@ +--- +name: localstack-iam +description: Test IAM policies and enforcement in LocalStack with lstk. Use when reproducing access denials, enabling soft or enforced IAM evaluation, validating policies, or deriving least-privilege permissions from observed requests. +--- + +# Test IAM policies in LocalStack + +Use the AWS emulator, `lstk aws`, and verbose logs to test real policy behavior. Do not claim that logs automatically generate a complete policy; treat observed actions as evidence for a candidate least-privilege policy. + +IAM enforcement and Policy Stream availability depend on the user's LocalStack plan. + +## Configure enforcement + +Find the active config: + +```bash +lstk config path +``` + +For soft evaluation, reference a profile that enables enforcement without denying requests: + +```toml +[[containers]] +type = "aws" +env = ["iam-soft"] + +[env.iam-soft] +DEBUG = "1" +ENFORCE_IAM = "1" +IAM_SOFT_MODE = "1" +``` + +For enforced mode: + +```toml +[[containers]] +type = "aws" +env = ["iam-enforced"] + +[env.iam-enforced] +DEBUG = "1" +ENFORCE_IAM = "1" +``` + +Restart after changing the profile: + +```bash +lstk restart +``` + +For a one-off run, set the same keys as host environment variables prefixed with `LOCALSTACK_`. `lstk start` forwards host variables carrying that prefix, so an unprefixed `ENFORCE_IAM` never reaches the emulator: + +```bash +LOCALSTACK_ENFORCE_IAM=1 LOCALSTACK_IAM_SOFT_MODE=1 lstk start +``` + +Keys inside an `[env.*]` profile take no prefix. + +Use soft mode first when discovering required permissions. Use enforced mode when testing that unauthorized calls really fail. + +## Create principals and policies + +```bash +lstk aws iam create-user --user-name dev-user + +lstk aws iam create-policy \ + --policy-name app-policy \ + --policy-document file://policy.json + +lstk aws iam attach-user-policy \ + --user-name dev-user \ + --policy-arn arn:aws:iam::000000000000:policy/app-policy + +lstk aws iam create-access-key --user-name dev-user +``` + +Capture the returned access key and secret without committing them. `lstk aws` respects explicit AWS credential environment variables, so use the created principal for the request under test: + +```bash +AWS_ACCESS_KEY_ID= \ +AWS_SECRET_ACCESS_KEY= \ +lstk aws s3 ls +``` + +## Investigate a denial + +1. Reproduce the request with the intended principal. +2. Inspect the policy-engine and request lines: + +```bash +lstk logs --verbose --tail 500 | grep -i 'denied\|accessdenied\|iam' +``` + +3. Record the principal, action, resource ARN, explicit denies, and missing allows. +4. Update the smallest relevant statement. +5. Re-run the same request with the same credentials. +6. Confirm both the API result and the verbose log. + +An explicit deny always wins. Check identity policies, resource policies, permission boundaries, and service-generated calls before broadening permissions. + +## Validate and simulate policies + +```bash +lstk aws iam simulate-principal-policy \ + --policy-source-arn arn:aws:iam::000000000000:user/dev-user \ + --action-names s3:GetObject \ + --resource-arns arn:aws:s3:::my-bucket/file.txt + +lstk aws accessanalyzer validate-policy \ + --policy-document file://policy.json \ + --policy-type IDENTITY_POLICY +``` + +Treat simulator and validator results as additional evidence; still run the application request against enforced mode. + +## Derive least privilege + +1. Start with soft mode and a clean test scenario. +2. Exercise every intended application path. +3. Collect the observed actions and resource ARNs from verbose logs or the IAM Policy Stream (see [Stream recommended policies](#stream-recommended-policies)). +4. Group actions by principal and resource scope. +5. Create a candidate policy with the narrowest useful actions and resources. +6. Switch to enforced mode and run positive and negative tests. +7. Review for wildcard actions, wildcard resources, and permissions not exercised by the scenario. + +The IAM Policy Stream can help summarize observed permissions when the user's plan includes it. It is available in the LocalStack Web Application and, on the command line, through the legacy `localstack` CLI. + +## Stream recommended policies + +`lstk` has no top-level `iam` command group — `lstk aws iam` only proxies the AWS CLI — so the CLI form of the Policy Stream comes from the legacy `localstack` CLI. Install it alongside `lstk` when request-level policy recommendations are needed: + +```bash +pip install localstack +``` + +Both commands are plain reads against the emulator's normal endpoint, so they work against a container started by `lstk`: + +```bash +# Live stream of recommended policies as requests arrive +localstack aws iam stream +localstack aws iam stream --format json + +# Aggregated policies for all enforced requests +localstack aws iam summary +localstack aws iam summary --output policies.json +``` + +`stream` prints, per request, the principal or resource the policy should attach to, followed by the recommended policy. `summary` aggregates the same recommendations per principal or resource; `--follow` keeps it updating and clears the terminal on each refresh. If the emulator is not on the default endpoint, set `LOCALSTACK_HOST` for the legacy CLI. + +1. Start the emulator in soft mode. +2. Run `localstack aws iam stream` in a second terminal. +3. Exercise the application path under test. +4. Merge the reported statements into the candidate policy. + +The command group is marked preview, and both commands depend on a plan that includes the Policy Stream. These recommendations cover only the requests actually observed, so review them the same way as log-derived actions before treating the result as complete. Without the legacy CLI, derive the same evidence from `lstk logs --verbose`. diff --git a/skills/localstack-lifecycle/SKILL.md b/skills/localstack-lifecycle/SKILL.md deleted file mode 100644 index 7a61c3e..0000000 --- a/skills/localstack-lifecycle/SKILL.md +++ /dev/null @@ -1,193 +0,0 @@ ---- -name: localstack -description: Manage the LocalStack emulator lifecycle with the lstk CLI. Use when users need to start, stop, restart, reset, or check status of LocalStack, configure LocalStack environment variables, or troubleshoot LocalStack container issues. ---- - -# LocalStack Lifecycle Management - -Manage the LocalStack emulator lifecycle — starting, stopping, and monitoring the local cloud environment — using `lstk`, the current LocalStack CLI. - -## Capabilities - -- Start LocalStack with custom configuration -- Stop, restart, and reset running LocalStack instances -- Check LocalStack status and health -- Manage the emulator volume and persisted state -- Authenticate against the LocalStack platform - -## Prerequisites - -- Docker installed and running -- A LocalStack account (`lstk` pulls the `localstack/localstack-pro` image and requires a valid license) -- The `lstk` CLI: - -```bash -# Homebrew (macOS/Linux) -brew install localstack/tap/lstk - -# npm -npm install -g @localstack/lstk - -# Verify -lstk --version -``` - -> The legacy `localstack` CLI is deprecated and will be removed in a future version. Prefer `lstk`. A few features still live only in the legacy CLI — see [Legacy CLI fallbacks](#legacy-cli-fallbacks). - -## Authentication - -```bash -# Interactive browser login; stores the token in the system keyring -lstk login - -# Remove stored credentials -lstk logout -``` - -In CI or any non-TTY environment, set the auth token instead (a CI Auth Token — a personal Developer Auth Token will not work in CI): - -```bash -export LOCALSTACK_AUTH_TOKEN= -lstk --non-interactive start -``` - -Token resolution order: system keyring (from `lstk login`) → `LOCALSTACK_AUTH_TOKEN` → interactive browser login. The keyring wins over the environment variable, so run `lstk logout` first if you need to switch. - -## Common Commands - -### Start LocalStack - -```bash -# Start the emulator (bare `lstk` is equivalent to `lstk start`) -lstk start - -# Start and keep state across restarts -lstk start --persist - -# Start with debug logging (note the LOCALSTACK_ prefix) -LOCALSTACK_DEBUG=1 lstk start - -# Pick the emulator type -lstk start --type aws # also: snowflake, azure - -# Plain output for scripts/CI, with a startup deadline -lstk --non-interactive --timeout 90s start -``` - -`lstk start` runs the container in the background and returns once the emulator is ready — there is no `-d` flag. - -### Check Status - -```bash -# Emulator state plus the resources currently deployed in it -lstk status - -# Plain-text output for scripts -lstk --non-interactive status - -# Service health endpoint -curl http://localhost:4566/_localstack/health | jq -``` - -### Stop and Restart - -```bash -lstk stop -lstk restart -lstk restart --persist -``` - -### Reset State - -```bash -# Discard all in-memory resources; the emulator keeps running -lstk reset -lstk reset --force # skip the confirmation prompt -``` - -### View Logs - -```bash -lstk logs # print available logs -lstk logs -f # follow in real time -lstk logs -n 100 # last 100 lines -lstk logs -v # unfiltered output -``` - -### Manage the Volume - -```bash -lstk volume path # print the volume directory -lstk volume clear # wipe certificates, cached tools, persisted data -lstk volume clear --force -``` - -`lstk reset` clears in-memory state; `lstk volume clear` wipes the on-disk volume. Stop the emulator before clearing the volume. - -## Configuration - -### Passing environment variables - -`lstk` forwards **host environment variables prefixed with `LOCALSTACK_`** into the emulator. Any LocalStack config variable you used to pass bare must now carry that prefix: - -```bash -LOCALSTACK_DEBUG=1 lstk start -LOCALSTACK_SERVICES=s3,sqs lstk start -LOCALSTACK_ENFORCE_IAM=soft lstk start -``` - -The host `LOCALSTACK_AUTH_TOKEN` is deliberately *not* forwarded, so it cannot override the token `lstk` resolved. - -### Environment profiles in `config.toml` - -For settings you want on every run, define named profiles in `config.toml` and reference them from the container block. Keys inside a profile do **not** need the `LOCALSTACK_` prefix: - -```toml -[[containers]] -type = "aws" -tag = "latest" -port = "4566" -env = ["debug", "ci"] - -[env.debug] -DEBUG = "1" -PERSISTENCE = "1" - -[env.ci] -SERVICES = "s3,sqs" -EAGER_SERVICE_LOADING = "1" -``` - -Config file resolution order: `./.lstk/config.toml` (project-local) → `$HOME/.config/lstk/config.toml` → OS default location. Print the active path with `lstk config path`. - -### Common configuration options - -| Variable | Description | How to set | -|----------|-------------|------------| -| `DEBUG` | Enable debug logging | `LOCALSTACK_DEBUG=1 lstk start` or `[env.*]` profile | -| `PERSISTENCE` | Persist state across restarts | `lstk start --persist` (preferred) or profile | -| `SERVICES` | Limit the services started | `LOCALSTACK_SERVICES=s3,sqs lstk start` | -| `GATEWAY_LISTEN` | Bind address/ports | `GATEWAY_LISTEN = "0.0.0.0:4566"` in a profile | -| `LOCALSTACK_AUTH_TOKEN` | Platform auth token | Env var, or `lstk login` | -| `LOCALSTACK_HOST` | Override the endpoint host used by `lstk aws` and friends | Env var | - -Pin an image version with `tag` in `config.toml` (e.g. `tag = "2026.4"`), or point `image` at an internal registry for air-gapped setups. - -## Legacy CLI fallbacks - -`lstk` does not cover every legacy feature yet. Install the legacy CLI (`pip install localstack`) alongside `lstk` only if you need: - -- **Extensions** — there is no `lstk extensions` command suite; see the `localstack-extensions` skill -- **`localstack aws iam stream` / `summary`** — IAM policy stream and summary; see the `localstack-iam` skill -- **Advanced DNS configuration** (systemd-resolved integration) and ephemeral cloud instances - -`lstk` manages its own Docker container and cannot be mixed with a Docker Compose LocalStack setup, or with a container started by the legacy `localstack start`. To point `lstk` at an emulator you manage yourself, use `--endpoint-url`. - -## Troubleshooting - -- **`Error: runtime not healthy`**: Docker is not running. Start Docker Desktop or the daemon, or set `DOCKER_HOST` for a custom socket. -- **Port 443 conflict**: set `GATEWAY_LISTEN = "0.0.0.0:4566"` in an environment profile so only 4566 is bound. -- **Auth errors in CI**: set `LOCALSTACK_AUTH_TOKEN` before `lstk start`; a TTY-less environment cannot run the browser flow. -- **Stale license**: `lstk logout && lstk login`. -- **Unknown env var had no effect**: confirm it is prefixed with `LOCALSTACK_` on the host, or moved into an `[env.*]` profile. -- **Diagnostics**: `lstk` writes `lstk.log` next to the config file — find it with `lstk config path`. diff --git a/skills/localstack-logs/SKILL.md b/skills/localstack-logs/SKILL.md new file mode 100644 index 0000000..55429b7 --- /dev/null +++ b/skills/localstack-logs/SKILL.md @@ -0,0 +1,142 @@ +--- +name: localstack-logs +description: Analyze LocalStack emulator logs with lstk. Use when debugging AWS API errors, Lambda failures, startup problems, IAM denials, request patterns, or service-specific behavior. +--- + +# Analyze LocalStack logs + +Use `lstk logs` so log collection follows the configured emulator and container runtime. + +## Collect the right log view + +```bash +# Recent output +lstk logs --tail 100 + +# Stream new output +lstk logs --follow + +# Include request and provider lines filtered from the default view +lstk logs --verbose --tail 200 +``` + +Use `--verbose` for AWS request analysis; the default view removes routine request/provider noise. + +Filter a captured view when looking for a specific service, request ID, or failure: + +```bash +lstk logs --verbose --tail 500 | grep -i 's3' +lstk logs --verbose --tail 500 | grep -i 'error\|exception' +lstk logs --verbose --tail 500 | grep 'request-id-here' +``` + +Do not assume a fixed underlying container name. + +## Read the CLI's own log + +`lstk logs` shows emulator output only. The CLI writes its own timestamped diagnostic log to `lstk.log` in the configuration directory: + +```bash +lstk config path # lstk.log sits in this directory +``` + +Read it when the CLI is the problem rather than the emulator: a start that never reaches the emulator, an undetected container runtime, or a failure resolving authentication or configuration. `lstk logs` reports nothing in those cases. + +## Enable detailed emulator logging + +Find the active config: + +```bash +lstk config path +``` + +`lstk start` forwards a host environment variable to the emulator only when it carries the `LOCALSTACK_` prefix, which raises the log level for a single run without editing config: + +```bash +LOCALSTACK_DEBUG=1 lstk start +LOCALSTACK_LS_LOG=trace lstk start +``` + +A key set inside an `[env.*]` profile takes no prefix. + +Attach a debug profile to the active emulator: + +```toml +[[containers]] +type = "aws" +env = ["debug"] + +[env.debug] +DEBUG = "1" +LS_LOG = "trace" +``` + +For Lambda-specific diagnostics, add `LAMBDA_DEBUG = "1"` only when the current LocalStack documentation recommends it for the runtime under investigation. Restart after changing emulator environment: + +```bash +lstk restart +``` + +## Diagnose AWS API failures + +1. Reproduce the failing request once. +2. Capture `lstk logs --verbose --tail 500`. +3. Locate the service and operation, HTTP status, request ID, and the first causal exception. +4. Distinguish an application error from an emulator startup, configuration, or coverage issue. +5. Confirm the resource exists: check `lstk status` first, then the `lstk aws` proxy for anything it does not cover. +6. Make the smallest configuration or application change, reproduce, and compare the new logs. + +Under `--verbose`, handled AWS calls appear as request lines naming the service, operation, and HTTP status, typically in the shape `AWS . => ` (for example `AWS s3.CreateBucket => 200`). Grep the operation name or a non-2xx status to isolate the failing call. + +Common signals include: + +| Signal | Check | +| --- | --- | +| `ResourceNotFoundException` | Confirm resource name, region, and account | +| `AccessDenied` | Inspect IAM enforcement and the request credentials | +| `ValidationException` | Compare request parameters with the AWS API contract | +| Connection refusal or timeout | Check `lstk status`, ports, and readiness | +| Provider exception | Read the first stack trace and check service coverage | + +## Inspect Lambda logs + +First inspect emulator-level failures: + +```bash +lstk logs --verbose --tail 500 | grep -i 'lambda' +``` + +Then query emulated CloudWatch Logs: + +```bash +lstk aws logs describe-log-groups +lstk aws logs describe-log-streams \ + --log-group-name /aws/lambda/my-function \ + --order-by LastEventTime \ + --descending +lstk aws logs get-log-events \ + --log-group-name /aws/lambda/my-function \ + --log-stream-name +``` + +## Check health + +Prefer the configuration-aware status command: + +```bash +lstk status +``` + +`lstk status` also lists the resources currently deployed in the emulator, which answers "does this resource exist?" faster than grepping logs. Add `--non-interactive` when a script captures the output: + +```bash +lstk --non-interactive status +``` + +For a default local endpoint, inspect the raw health payload only when needed: + +```bash +curl http://localhost:4566/_localstack/health +``` + +`lstk logs` has no external-emulator mode. When using `--endpoint-url`, obtain logs from the system that owns that emulator and use `lstk --endpoint-url status` for reachability. diff --git a/skills/localstack-state/SKILL.md b/skills/localstack-state/SKILL.md new file mode 100644 index 0000000..edc1010 --- /dev/null +++ b/skills/localstack-state/SKILL.md @@ -0,0 +1,154 @@ +--- +name: localstack-state +description: Manage LocalStack state with lstk snapshots and persistent volumes. Use when saving, loading, exporting, importing, versioning, sharing, resetting, or reproducing emulator state locally, in Cloud Pods, or in S3. +--- + +# Manage LocalStack state + +Use `lstk snapshot` for explicit checkpoints and `--persist` for automatic state retention. Cloud Pod (`pod:`) operations require a LocalStack plan that includes State Management and a valid authentication token. Local-file and S3 refs carry no platform token, but the snapshot feature is itself plan-gated, so an entitled account is required for every backend. + +## Save and load local snapshots + +```bash +# Save all services to a generated .snapshot file +lstk snapshot save + +# Save to a named file +lstk snapshot save ./baseline.snapshot + +# Save selected services +lstk snapshot save ./payments.snapshot --services s3,sqs,lambda + +# Load a snapshot +lstk snapshot load ./baseline.snapshot +``` + +An omitted destination writes `./snapshot--.snapshot` in the working directory. A destination without the `.snapshot` extension gets one appended, so `lstk snapshot save /tmp/my-state` writes `/tmp/my-state.snapshot`. On load, a bare name resolves against the working directory with or without the extension: + +```bash +lstk snapshot load baseline # loads ./baseline or ./baseline.snapshot +``` + +`lstk save` and `lstk load` are aliases, but prefer the explicit `lstk snapshot` form in documentation and automation. `snapshot save` reads the state of a running emulator and fails when none is running; `snapshot load` starts the configured emulator first when needed. + +Choose the merge strategy deliberately: + +```bash +# Default: snapshot wins on overlapping service/account/region state +lstk snapshot load ./baseline.snapshot --merge=account-region-merge + +# Replace all running state +lstk snapshot load ./baseline.snapshot --merge=overwrite + +# Merge resources within each service +lstk snapshot load ./baseline.snapshot --merge=service-merge +``` + +Set `LSTK_MERGE_STRATEGY` instead of passing `--merge` when one strategy should apply to every load in an environment or CI job. + +Treat `--merge=overwrite` as destructive and obtain confirmation before running it. + +## Work with Cloud Pods + +Use the `pod:` prefix: + +```bash +lstk snapshot save pod:team-baseline +lstk snapshot list +lstk snapshot show pod:team-baseline +lstk snapshot versions pod:team-baseline +lstk snapshot load pod:team-baseline +lstk snapshot load pod:team-baseline:3 +``` + +`snapshot list` returns only snapshots created by the authenticated user. Add `--all` for every snapshot in the organisation: + +```bash +lstk snapshot list --all +``` + +Every save to an existing pod creates a new version. + +`--services` (short form `-s`) applies to every destination, not only local files: + +```bash +lstk snapshot save pod:team-baseline --services s3,sqs,lambda +``` + +Preview a pod load without changing state: + +```bash +lstk snapshot load pod:team-baseline --dry-run +``` + +`snapshot show`, `snapshot versions`, `snapshot remove`, and `--dry-run` accept only `pod:` refs. Local files and `s3://` remotes have no version history and cannot be inspected, previewed, or removed through these commands. Removal cannot be undone. + +Remove a pod only after explicit confirmation: + +```bash +lstk snapshot remove pod:team-baseline +lstk --non-interactive snapshot remove pod:team-baseline --force +``` + +Removal still contacts a running emulator even though the snapshot is stored on the LocalStack platform. + +## Store snapshots in S3 + +Credentials are read from `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`, from `--profile`, or from the profile named by `AWS_PROFILE`; never put credentials in the URL: + +```bash +lstk snapshot save team-baseline s3://my-bucket/localstack --profile my-aws-profile +``` + +Save, list, and load against the bucket: + +```bash +lstk snapshot save team-baseline s3://my-bucket/localstack +lstk snapshot list s3://my-bucket/localstack +lstk snapshot load team-baseline s3://my-bucket/localstack +``` + +S3 transfers are performed by the emulator and require one to be reachable. + +## Auto-load a baseline + +Set a Cloud Pod in the active AWS emulator config: + +```toml +[[containers]] +type = "aws" +snapshot = "pod:team-baseline" +``` + +Override or skip it for one start: + +```bash +lstk start --snapshot pod:another-baseline +lstk start --no-snapshot +``` + +## Persist state across restarts + +```bash +lstk start --persist +lstk volume path +``` + +`--persist` sets `LOCALSTACK_PERSISTENCE=1` on the emulator and writes state into the volume directory, which is reloaded on the next start. The flag applies per invocation, so pass it to `restart` as well: + +```bash +lstk restart --persist +``` + +For a persistent default, attach an environment profile with `PERSISTENCE = "1"`. Configuring a volume only chooses where state is stored; it does not enable persistence by itself. + +Treat the following as destructive and get confirmation first: + +```bash +lstk reset +lstk volume clear +``` + +`lstk reset` discards the emulator's in-memory resources and leaves it running. `lstk volume clear` wipes the on-disk volume — certificates, downloaded tools, and persistence data — and expects the emulator to be stopped first. Both accept `--force` to skip the confirmation prompt in automation. + +Use a snapshot before destructive experiments when rollback matters. diff --git a/skills/localstack/SKILL.md b/skills/localstack/SKILL.md new file mode 100644 index 0000000..8880864 --- /dev/null +++ b/skills/localstack/SKILL.md @@ -0,0 +1,148 @@ +--- +name: localstack +description: Manage LocalStack emulators with the lstk v2 CLI. Use when starting, stopping, restarting, configuring, checking, or troubleshooting a LocalStack AWS, Azure, or Snowflake emulator. +--- + +# Manage a LocalStack emulator + +Use `lstk` for emulator lifecycle and configuration. Prefer it over the legacy `localstack` CLI and direct container-runtime commands because `lstk` resolves the configured emulator, runtime, ports, authentication, and output mode. + +## Check prerequisites + +`lstk` pulls a licensed LocalStack image (`localstack/localstack-pro` for the AWS emulator), so it needs a running container runtime and a LocalStack account whose license covers the selected emulator type. + +Verify the CLI and container runtime before changing state: + +```bash +lstk --version +lstk status +``` + +If `lstk` is missing, install it from the [lstk repository](https://github.com/localstack/lstk#installation). Do not put authentication tokens in committed files; use `LOCALSTACK_AUTH_TOKEN` or the browser login flow. + +## Start an emulator + +Start interactively and let the first-run flow select an emulator: + +```bash +lstk +``` + +Start explicitly: + +```bash +lstk start +lstk start --type aws +lstk start --type azure +lstk start --type snowflake +``` + +`--type` updates the selected type in the active configuration; it is not a temporary override. For automation, select the type and disable prompts: + +```bash +LOCALSTACK_AUTH_TOKEN= lstk --non-interactive start --type aws +``` + +Enable persistent emulator state for this start: + +```bash +lstk start --persist +``` + +Use `--timeout ` when automation needs a different readiness deadline: + +```bash +lstk --non-interactive start --timeout 90s +``` + +`lstk start` runs the emulator in the background and returns once it is ready. There is no `-d` flag; the legacy `localstack start -d` form does not carry over. + +## Inspect and control the emulator + +```bash +lstk status +lstk logs --tail 100 +lstk logs --follow +lstk restart +lstk stop +``` + +`lstk status` reports emulator state and also lists the resources deployed in it, so it answers whether a resource exists without grepping logs. + +Use `lstk restart --persist` when persistence must remain enabled after the restart. + +## Configure emulator environment + +Host environment variables reach the emulator only when prefixed with `LOCALSTACK_`: + +```bash +LOCALSTACK_DEBUG=1 lstk start +LOCALSTACK_SERVICES=s3,sqs lstk start +LOCALSTACK_EAGER_SERVICE_LOADING=1 lstk start +``` + +Any config variable the legacy `localstack` CLI accepted bare must carry the prefix on the host. Keys inside an `[env.*]` profile take no prefix. + +Find the active configuration file: + +```bash +lstk config path +``` + +`lstk` reads `./.lstk/config.toml` when the current directory has one, and `$HOME/.config/lstk/config.toml` otherwise; the lookup does not walk up parent directories. A committed `.lstk/config.toml` pins the emulator type, port, and environment profiles for commands run from the repository root. + +Add named environment profiles to that TOML file and reference them from the active `[[containers]]` block: + +```toml +[[containers]] +type = "aws" +tag = "latest" +port = "4566" +env = ["debug"] + +[env.debug] +DEBUG = "1" +LS_LOG = "trace" +``` + +Preserve unrelated settings and keep only one enabled `[[containers]]` block. Restart the emulator after changing its environment. + +Set `tag` in that block to pin the emulator version instead of tracking `latest` when a run must be reproducible, for example `tag = "2026.4"`. Set `image` to pull the emulator from an internal registry mirror; if `image` carries no tag, `tag` is appended to it. + +## Target an external emulator + +Commands with a remote equivalent accept a global endpoint: + +```bash +lstk --endpoint-url https://example.localstack.cloud status +lstk --endpoint-url https://example.localstack.cloud aws s3 ls +``` + +Do not use `--endpoint-url` with `start`, `stop`, `restart`, `logs`, or `volume`; those operations require an emulator managed by the local runtime. + +## Fall back to the legacy CLI + +A few capabilities have no `lstk` equivalent. Never invent `lstk extensions`, `lstk dns`, or `lstk ephemeral`. Install the legacy CLI (`pip install localstack`) alongside `lstk` only for: + +- `localstack extensions`, which manages in-emulator LocalStack Extensions; see the `localstack-extensions` skill. Git-style `lstk-` CLI extensions are a separate mechanism, covered by the `lstk-extensions` skill. +- `localstack aws iam stream` and `localstack aws iam summary`; see the `localstack-iam` skill. +- `localstack dns` for host DNS configuration and `localstack ephemeral` for ephemeral cloud instances. + +Use `lstk` for everything it already covers. + +## Troubleshoot startup + +1. Run `lstk status`. +2. Inspect `lstk logs --tail 200`, adding `--verbose` when request/provider lines matter. +3. Confirm the configured host port is available. +4. Confirm the detected container runtime is running. +5. Run `lstk config path` and inspect the active emulator type, image, port, environment profiles, and mounts. +6. For authentication failures, run `lstk login` or provide a valid `LOCALSTACK_AUTH_TOKEN`. +7. Read `lstk.log`, which `lstk` writes next to the configuration file; `lstk config path` locates the directory. It records CLI-side events such as license and token resolution that never reach `lstk logs`. + +The checklist above misses two cases: + +- The emulator gateway listens on `:4566,:443` by default, so startup can fail on port 443 while the configured port is free. Set `GATEWAY_LISTEN = ":4566"` in an environment profile to bind only 4566. +- `lstk` probes the default container-runtime socket, not the one a `docker` context may be using. Set `DOCKER_HOST` when the runtime listens elsewhere. + +Use direct container-runtime commands only as a last-resort diagnostic, not as the normal lifecycle workflow. diff --git a/skills/logs-analysis/SKILL.md b/skills/logs-analysis/SKILL.md deleted file mode 100644 index a0ec50d..0000000 --- a/skills/logs-analysis/SKILL.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -name: localstack-logs -description: Analyze LocalStack logs and debug issues with lstk. Use when users need to view LocalStack logs, debug AWS API errors, troubleshoot Lambda functions, identify error patterns, or enable debug mode. ---- - -# LocalStack Logs Analysis - -Analyze LocalStack logs to debug issues, identify errors, and understand AWS API interactions. - -## Capabilities - -- View and filter LocalStack logs -- Identify error patterns and failures -- Analyze AWS API request/response cycles -- Track service-specific operations -- Debug Lambda function executions - -## Prerequisites - -- The `lstk` CLI with a running emulator — see the `localstack` skill - -## Viewing Logs - -### Basic Log Commands - -```bash -# Print available logs -lstk logs - -# Follow logs in real time -lstk logs -f - -# Last N lines -lstk logs -n 100 - -# Unfiltered output (lstk filters noise by default) -lstk logs -v -``` - -Reach for `lstk logs -v` whenever a log line you expect is missing — the default view drops low-signal output. - -### Filtering Logs - -```bash -# Filter by service -lstk logs | grep -i s3 -lstk logs | grep -i lambda -lstk logs | grep -i dynamodb - -# Filter errors only -lstk logs | grep -i error -lstk logs | grep -i exception - -# Filter by request ID (use -v so nothing is filtered out first) -lstk logs -v | grep "request-id-here" -``` - -### Diagnostic Logs - -`lstk` writes its own diagnostic log to `lstk.log` in the config directory — useful when the CLI itself misbehaves rather than the emulator: - -```bash -lstk config path # the lstk.log sits alongside this file -``` - -## Debug Mode - -`lstk` forwards host environment variables **prefixed with `LOCALSTACK_`** into the emulator, so LocalStack config variables need that prefix: - -```bash -# Start with debug mode -LOCALSTACK_DEBUG=1 lstk start - -# Trace-level logging -LOCALSTACK_LS_LOG=trace lstk start -``` - -To make debug logging the default for a project, use an environment profile in `config.toml`: - -```toml -[[containers]] -type = "aws" -env = ["debug"] - -[env.debug] -DEBUG = "1" -``` - -Keys inside an `[env.*]` profile do not need the `LOCALSTACK_` prefix. - -## Analyzing API Requests - -### Request/Response Tracking - -LocalStack logs include AWS API requests. Look for patterns like: - -``` -AWS . => -``` - -Example log entries: -``` -AWS s3.CreateBucket => 200 -AWS dynamodb.PutItem => 200 -AWS lambda.Invoke => 200 -``` - -### Deployed Resources - -`lstk status` lists the resources currently deployed in the emulator, which is often faster than grepping logs to answer "does this resource exist?": - -```bash -lstk status -lstk --non-interactive status -``` - -### Common Error Patterns - -| Error | Possible Cause | Solution | -|-------|---------------|----------| -| `ResourceNotFoundException` | Resource doesn't exist | Create the resource first; confirm with `lstk status` | -| `AccessDeniedException` | IAM policy issue | Check IAM enforcement mode | -| `ValidationException` | Invalid parameters | Verify request parameters | -| `ServiceException` | Internal error | Check LocalStack logs for details | - -## Lambda Debugging - -### View Lambda Logs - -```bash -# Lambda function logs appear in the emulator logs -lstk logs -v | grep -A 10 "Lambda" - -# Or use CloudWatch Logs locally -lstk aws logs describe-log-groups -lstk aws logs get-log-events \ - --log-group-name /aws/lambda/my-function \ - --log-stream-name -``` - -### Enable Lambda Debug Mode - -```bash -LOCALSTACK_LAMBDA_DEBUG=1 lstk start -``` - -## Health Check - -```bash -# Check overall health -curl http://localhost:4566/_localstack/health | jq - -# Check specific service -curl http://localhost:4566/_localstack/health | jq '.services.s3' -``` - -## Troubleshooting Tips - -- **No logs appearing**: Ensure the emulator is running (`lstk status`) -- **Expected line missing**: Re-run with `lstk logs -v` — the default view is filtered -- **Missing debug info**: Start with `LOCALSTACK_DEBUG=1` for verbose logging -- **Lambda issues**: Check both the emulator logs and CloudWatch Logs -- **Intermittent errors**: Look for resource limits or timing issues -- **CLI-level problems**: Check `lstk.log` in the directory reported by `lstk config path` diff --git a/skills/lstk-extensions/SKILL.md b/skills/lstk-extensions/SKILL.md new file mode 100644 index 0000000..e74fd59 --- /dev/null +++ b/skills/lstk-extensions/SKILL.md @@ -0,0 +1,102 @@ +--- +name: lstk-extensions +description: Use and author Git-style lstk CLI extensions. Use when invoking, discovering, or building an executable whose name starts with lstk-, handling LSTK_EXT_CONTEXT, or distinguishing CLI extensions from in-emulator LocalStack Extensions. +--- + +# Use and author lstk CLI extensions + +`lstk` supports Git-style extensions. An executable named `lstk-` on `PATH` becomes `lstk `. There is no manifest, registry, install command, or registration step. + +This mechanism is different from Python-based LocalStack Extensions that run inside the emulator. + +## Discover and invoke extensions + +List built-in commands and discovered extensions: + +```bash +lstk --help +``` + +Locate an extension directly: + +```bash +command -v lstk-example +``` + +Invoke it through `lstk`: + +```bash +lstk example --flag value +``` + +Built-in commands and aliases always win. Arguments after the extension name are forwarded verbatim, and the extension's exit code and standard streams pass through. + +## Install an extension executable + +1. Obtain or build a trusted executable named `lstk-`. +2. Put it in a directory on `PATH`. +3. Mark it executable on Unix-like systems. +4. Confirm it appears in `lstk --help`. +5. Run a harmless help or version command before allowing state changes. + +`lstk` does not sandbox or verify third-party extensions. Do not install or execute an untrusted binary. + +## Read runtime context + +`lstk` supplies: + +- `LSTK_EXT_API_VERSION`: breaking-version number for the context contract. +- `LSTK_EXT_CONTEXT`: JSON containing the resolved config directory, optional auth token, output mode, optional telemetry session ID, and running emulators. + +A shell extension can read the AWS endpoint with `jq`: + +```sh +context=${LSTK_EXT_CONTEXT:-} +aws_endpoint=$( + printf '%s' "$context" | + jq -r '.emulators[]? | select(.type == "aws") | .endpoint' | + head -n 1 +) + +if [ -z "$aws_endpoint" ]; then + printf '%s\n' "an AWS emulator is required; run 'lstk start --type aws'" >&2 + exit 1 +fi +``` + +Treat the context as runtime input: + +- Check a field's presence instead of inferring it from the API version. +- Use `LSTK_EXT_API_VERSION` only to reject a breaking contract generation. +- Handle an empty `emulators` array. +- Select an emulator by `type`; do not assume only one entry. +- Never print or persist `authToken`. +- Do not prompt when `nonInteractive` is true. +- Emit machine-readable output when choosing to honor `json`. + +## Author an extension + +Name the executable `lstk-` and parse only the arguments it owns. A minimal POSIX shell extension: + +```sh +#!/usr/bin/env sh +set -eu + +if [ "${LSTK_EXT_API_VERSION:-0}" -gt 1 ]; then + printf '%s\n' "unsupported lstk extension API version" >&2 + exit 1 +fi + +if [ -z "${LSTK_EXT_CONTEXT:-}" ]; then + printf '%s\n' "this command must be run through lstk" >&2 + exit 1 +fi + +printf '%s\n' "extension is ready" +``` + +Keep failures actionable and preserve meaningful exit codes. If the extension performs paid or protected work, authorize server-side with the supplied token; a client-side check is not a security boundary. + +## Distinguish emulator extensions + +When the user means a Python extension running inside the LocalStack emulator, do not invent commands such as `lstk extensions install`. `lstk` does not manage that system. Use the `localstack-extensions` skill, which covers installing and authoring in-emulator Extensions with the legacy `localstack` CLI. diff --git a/skills/state-management/SKILL.md b/skills/state-management/SKILL.md deleted file mode 100644 index c3b0dc4..0000000 --- a/skills/state-management/SKILL.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -name: localstack-state -description: Manage LocalStack state and snapshots with lstk. Use when users want to save, load, export, or import LocalStack state, work with Cloud Pods or S3-backed snapshots, or enable persistence across restarts. ---- - -# State Management - -Save, load, and manage LocalStack state for reproducible development environments and state snapshots, using `lstk snapshot` and its `lstk save` / `lstk load` aliases. - -## Capabilities - -- Save and restore state as local snapshot files -- Save and load state to/from Cloud Pods (LocalStack platform storage) -- Save and load state to/from your own S3 bucket -- Share state across teams via Cloud Pods -- Auto-load a snapshot every time the emulator starts -- Enable persistent state across container restarts - -## Prerequisites - -- `lstk` installed and authenticated (`lstk login`, or `LOCALSTACK_AUTH_TOKEN` in CI) — see the `localstack` skill -- A running emulator for `save` (`lstk load` will start one for you if needed) - -`lstk save` / `lstk load` replace the legacy `localstack state export/import` and `localstack pod save/load` commands with a single snapshot interface. The destination REF decides where the state goes. - -## Snapshot References (REF) - -| REF form | Destination | -|----------|-------------| -| *(omitted)* | Auto-named local file `./snapshot--.snapshot` | -| `./my-snapshot.snapshot` | Explicit local path | -| `pod:my-baseline` | Cloud Pod on the LocalStack platform | -| `pod:my-baseline:3` | Version 3 of that Cloud Pod | -| `my-pod s3://my-bucket/prefix` | Your own S3 bucket | - -## Local Snapshots - -### Save - -```bash -# Save to an auto-named file in the current directory -lstk save - -# Save to a specific path (the .snapshot extension is added if omitted) -lstk save ./my-snapshot.snapshot -lstk save /tmp/my-state - -# Limit the snapshot to a subset of services -lstk save --services s3,lambda -``` - -### Load - -```bash -# Loads ./my-baseline or ./my-baseline.snapshot -lstk load my-baseline - -# Load from an explicit path -lstk load ./checkpoint.snapshot -``` - -### Use Cases for Local Snapshots - -- **Backup/restore**: Save state before destructive operations -- **CI/CD pipelines**: Commit snapshot files to version control for reproducible tests -- **Offline workflows**: Work with snapshot files without cloud connectivity -- **Quick snapshots**: Fast local save/restore during development - -## Cloud Pods - -Cloud Pods store state on the LocalStack platform, enabling team collaboration and remote state management. They require authentication (`lstk login` or `LOCALSTACK_AUTH_TOKEN`). - -### Save to a Cloud Pod - -```bash -lstk save pod:my-baseline - -# Only part of the state -lstk save pod:my-baseline --services s3,lambda -``` - -Every save to an existing pod name creates a new version. - -### Load from a Cloud Pod - -```bash -lstk load pod:my-baseline - -# A specific version -lstk load pod:my-baseline:3 - -# Preview the changes without applying them (Cloud Pod refs only) -lstk load pod:my-baseline --dry-run -``` - -### List, Inspect, and Remove - -```bash -# Your Cloud Pods -lstk snapshot list - -# Everything in your organisation -lstk snapshot list --all - -# Metadata: created date, size, LocalStack version, per-service resource counts -lstk snapshot show pod:my-baseline -lstk snapshot show pod:my-baseline:3 - -# Version history -lstk snapshot versions pod:my-baseline - -# Delete (cloud snapshots only, cannot be undone) -lstk snapshot remove pod:my-baseline -lstk snapshot remove pod:my-baseline --force -``` - -### Use Cases for Cloud Pods - -- **Team collaboration**: Share consistent development environments across team members -- **Demo environments**: Prepare and share demo-ready states -- **Cross-machine development**: Access the same state from different machines - -## S3-Backed Snapshots - -Store snapshots in a bucket you own. Credentials are read from `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`, from `--profile`, or from the profile named by `AWS_PROFILE` — never put credentials in the URL. - -```bash -lstk save my-pod s3://my-bucket/prefix -lstk save my-pod s3://my-bucket/prefix --profile my-aws-profile - -lstk load my-pod s3://my-bucket/prefix - -lstk snapshot list s3://my-bucket/prefix -``` - -## Merge Strategies - -`lstk load` controls how snapshot state combines with state already in the emulator: - -| Strategy | Behavior | -|----------|----------| -| `account-region-merge` *(default)* | Snapshot wins on overlapping (service, account, region) | -| `overwrite` | Wipe running state, then load | -| `service-merge` | Snapshot wins per resource; non-overlapping resources are combined | - -```bash -lstk load pod:my-baseline --merge=overwrite -``` - -You can also set `LSTK_MERGE_STRATEGY` instead of passing the flag. - -## Auto-Loading a Snapshot on Start - -For the AWS emulator, set the `snapshot` field on the container block so a snapshot loads on every start: - -```toml -[[containers]] -type = "aws" -snapshot = "pod:my-baseline" -``` - -Override or skip it for a single run: - -```bash -lstk start --snapshot pod:other-baseline -lstk start --no-snapshot -``` - -## Local Persistence - -For automatic persistence across restarts without explicit save/load: - -```bash -lstk start --persist -lstk restart --persist -``` - -`--persist` injects `LOCALSTACK_PERSISTENCE=1` and writes state to the mounted volume, which is reloaded on the next start. Find that directory with `lstk volume path`; wipe it with `lstk volume clear`. - -You can also set `PERSISTENCE = "1"` in an `[env.*]` profile in `config.toml` to make it the default for every run. - -## Clearing State - -```bash -# Discard in-memory resources, keep the emulator running -lstk reset - -# Wipe the on-disk volume (stop the emulator first) -lstk volume clear -``` - -## Comparison - -| Feature | Local snapshot files | Cloud Pods (`pod:`) | Your S3 bucket (`s3://`) | -|---------|----------------------|---------------------|--------------------------| -| Storage | Local files | LocalStack platform | Your AWS account | -| Extra auth | None beyond `lstk` | LocalStack auth token | AWS credentials | -| Team sharing | Manual file sharing | Built-in | Via bucket permissions | -| Versioning | Manual | Built-in (`snapshot versions`) | Manual | -| Offline use | Yes | No | No | - -Note that `lstk` itself always requires a LocalStack account and license, regardless of which snapshot backend you use. - -## Best Practices - -- Use local snapshot files for development checkpoints and CI/CD pipelines -- Use Cloud Pods for team collaboration and shared environments -- Use descriptive names that indicate the state contents -- Use `--services` to keep snapshots small when you only care about part of the stack -- Use `--dry-run` before loading an unfamiliar Cloud Pod into a populated emulator -- Use `lstk start --persist` for simple state retention across restarts