lstk Automation & CI
Global options
Section titled “Global options”These options are available for all commands:
| Option | Description |
|---|---|
--config <path> |
Path to a specific TOML config file |
--endpoint-url <url> |
Target an existing, externally-managed emulator at this URL instead of discovering one via local Docker. See Targeting an external emulator. |
--non-interactive |
Disable the interactive TUI, use plain output |
--json |
Emit a single machine-readable JSON envelope on stdout instead of human-oriented output. Supported by stop, reset, and update; any other command rejects it. See Structured output. |
--persist |
Persist emulator state across restarts (on start/bare lstk and restart) |
--type <type>, -t <type> |
Emulator type to start: aws, snowflake, or azure (on start/bare lstk; records the choice in config). See Selecting the emulator with --type. |
--snapshot <REF> |
Snapshot REF to auto-load after start (on start/bare lstk; overrides config for one run) |
--no-snapshot |
Skip auto-loading the configured snapshot (on start/bare lstk) |
--timeout <duration> |
Startup readiness deadline for start/bare lstk, as a Go duration; overrides LSTK_STARTUP_TIMEOUT for one run. See start. |
-v, --version |
Print the version and exit |
-h, --help |
Print help and exit |
Interactive and non-interactive mode
Section titled “Interactive and non-interactive mode”lstk automatically selects its output mode:
- Interactive mode (TUI): used when both stdin and stdout are connected to a terminal.
Commands like
start,stop,restart,status,login,update, and the confirmation prompts ofreset/volume cleardisplay a Bubble Tea-powered terminal UI. - Non-interactive mode (plain text): used when the output is piped, redirected, or running in CI.
Force this in a TTY with
--non-interactive.
# Force plain output even in an interactive terminallstk --non-interactive startTargeting an external emulator
Section titled “Targeting an external emulator”By default lstk discovers the emulator it manages through local Docker.
The --endpoint-url <url> global flag (or the LSTK_ENDPOINT_URL environment variable) instead points a command at an emulator lstk did not start — a Docker Compose or host-network deployment, one running in CI or on another machine, or a LocalStack cloud-hosted ephemeral instance.
# Run against an emulator reachable at a custom URLlstk aws --endpoint-url http://localhost:4566 s3 ls
# Equivalent via the environmentLSTK_ENDPOINT_URL=https://my-ephemeral-instance.localstack.cloud lstk statusThe endpoint is resolved from, in order of precedence: the --endpoint-url flag, LSTK_ENDPOINT_URL, then AWS_ENDPOINT_URL (a full synonym for LSTK_ENDPOINT_URL, one tier lower).
Both http:// and https:// URLs are accepted (any other scheme is rejected), and the scheme is preserved end-to-end, so https:// ephemeral instances work.
The commands that accept an external endpoint are the ones that only talk to an already-running emulator: aws, az, terraform/tf, cdk, sam, status, reset, and the snapshot save/load/remove subcommands (including the lstk save/lstk load aliases) and list s3://….
Commands that manage the emulator’s lifecycle or on-disk state have no remote equivalent and reject any endpoint source: start, the bare lstk, stop, restart, logs, and volume.
The emulator’s type (AWS, Azure, or Snowflake) is auto-detected by probing the endpoint’s health API — there is no override flag or config setting, and an inconclusive probe is a hard failure. The AWS-only tools (terraform, cdk, sam) reject an endpoint whose detected type is not AWS.
Structured output
Section titled “Structured output”The global --json flag makes a command emit a single, machine-readable JSON object on stdout instead of human-oriented text, for scripting and CI.
JSON support is available per command: stop, reset, and update accept --json.
Any other command rejects it with an error envelope (error.code: NOT_JSON_CAPABLE) rather than silently printing plain text.
Every JSON-capable command writes exactly one JSON object with the following envelope shape:
{ "schemaVersion": 1, "command": "stop", "status": "ok", "data": { "emulators": [ { "type": "aws", "name": "localstack-aws", "wasRunning": true } ] }, "warnings": [], "error": null}| Field | Type | Description |
|---|---|---|
schemaVersion |
integer | Wire-format version of the envelope, always 1 for this schema. Check it once before parsing. |
command |
string | The command that produced the envelope (e.g. "stop", "reset"). |
status |
string | "ok" or "error" — branch on this first. |
data |
object or null |
Command-specific result. Non-null when status is "ok", null when it is "error". |
warnings |
array | Non-fatal notices, always present (empty array when there are none). Each entry is { "code", "message" }. |
error |
object or null |
The machine-readable failure. Non-null when status is "error", null otherwise. |
When status is "error", the error object carries a stable code (e.g. EMULATOR_NOT_RUNNING, CONFIRMATION_REQUIRED, RUNTIME_UNAVAILABLE), a coarse category, a human-readable message (informational only — branch on code, not message), and a retryable boolean:
{ "schemaVersion": 1, "command": "reset", "status": "error", "data": null, "warnings": [], "error": { "code": "CONFIRMATION_REQUIRED", "category": "USAGE", "message": "reset requires confirmation; use --force to skip in non-interactive mode", "retryable": false }}Exit codes
Section titled “Exit codes”For a full enumeration, read error.code from the envelope; the process exit code carries only the two most common, mechanically-remediable failures:
| Exit code | Meaning |
|---|---|
0 |
status: "ok". |
1 |
status: "error" for any code other than the two below. |
2 |
A Cobra-level usage error that occurred before --json could be recognized (plain-text error on stderr, not an envelope). |
3 |
error.code == "CONFIRMATION_REQUIRED" (re-run with --force). |
4 |
error.code == "AUTH_REQUIRED" (run lstk login or set LOCALSTACK_AUTH_TOKEN). |
Environment variables
Section titled “Environment variables”The following environment variables configure lstk itself (not the LocalStack container):
| Variable | Description |
|---|---|
LOCALSTACK_AUTH_TOKEN |
Auth token for non-interactive runs or to skip browser login. Takes precedence over a token stored in the keyring. |
LSTK_ENDPOINT_URL |
Target an existing, externally-managed emulator at this URL (equivalent to --endpoint-url). AWS_ENDPOINT_URL is a lower-precedence synonym. See Targeting an external emulator. |
LOCALSTACK_HOST |
Override the host (and optional port) used when resolving and printing the emulator endpoint, and when writing the AWS CLI profile. Bypasses the localhost.localstack.cloud DNS probe. |
LOCALSTACK_DISABLE_EVENTS |
Set to 1 to disable anonymous telemetry event reporting. |
DOCKER_HOST |
Override the Docker daemon socket (e.g. unix:///home/user/.colima/default/docker.sock). |
LSTK_KEYRING |
Set to file to force file-based token storage instead of the system keyring. |
LSTK_STARTUP_TIMEOUT |
Startup readiness deadline for lstk start, as a Go duration (e.g. 90s, 2m). Zero/unset uses the per-mode default (20s interactive, 60s non-interactive). See start. |
LSTK_MERGE_STRATEGY |
Default merge strategy for snapshot load / load (account-region-merge, overwrite, or service-merge) when --merge is not passed. An explicit --merge always wins. |
LSTK_OTEL |
Set to 1 to enable OpenTelemetry trace export (disabled by default). See OpenTelemetry tracing. |
LSTK_GITHUB_TOKEN |
Optional GitHub token used when checking for or downloading lstk updates (raises GitHub API rate limits). |
LSTK_API_ENDPOINT |
Override the LocalStack platform API base URL. Default: https://api.localstack.cloud. |
LSTK_WEB_APP_URL |
Override the LocalStack Web Application URL used for browser login. Default: https://app.localstack.cloud. |
When LSTK_OTEL is enabled, the standard OTEL_EXPORTER_OTLP_* environment variables are honored by the OpenTelemetry SDK.
Container runtime discovery
Section titled “Container runtime discovery”lstk talks to a Docker-compatible runtime and works with Docker Desktop, Rancher Desktop, Colima, OrbStack, Lima, and Podman. When DOCKER_HOST is not set, it resolves the daemon endpoint in this order:
DOCKER_HOST, if set, always wins.DOCKER_CONTEXTor the active Docker CLI context, when it is non-default and reachable (a stale or unreachable context is skipped rather than failing).- On Linux, a live
/var/run/docker.sock— a running Docker daemon is preferred over a co-installed runtime such as Podman. - A probe of known runtime sockets (Docker Desktop, Rancher Desktop, Colima, OrbStack, Podman, Lima). Each candidate is dialed, not just checked for existence, so a leftover socket file never shadows a live daemon.
- The Docker SDK’s own default.
If no runtime is reachable, the error tailors its suggested start command (rdctl start, colima start, podman machine start, …) to the runtime it detects. Set DOCKER_HOST to point at a specific socket to bypass discovery entirely.
Container-injected variables
Section titled “Container-injected variables”lstk injects several environment variables into the LocalStack container on every start, in addition to any profiles you configure:
| Variable | Default value | Description |
|---|---|---|
LOCALSTACK_AUTH_TOKEN |
(your resolved token) | Passed from the CLI to activate the license. |
GATEWAY_LISTEN |
:4566,:443 |
Ports the emulator binds inside the container. |
MAIN_CONTAINER_NAME |
localstack-aws |
Container name for internal references. |
LOCALSTACK_HOST |
localhost.localstack.cloud:<host port> |
Hostname/port the emulator advertises. |
LOCALSTACK_PERSISTENCE |
1 (only with --persist) |
Enables state persistence across restarts. |
LOCALSTACK_CLIENT_NAME |
lstk |
Identifies the client that started the emulator. |
LOCALSTACK_CLIENT_VERSION |
(the lstk version) |
Version of the client that started the emulator. |
When a Docker socket is detected it is bind-mounted into the container and DOCKER_HOST=unix:///var/run/docker.sock is injected so the emulator can spawn its own containers.
lstk also forwards host environment variables matching CI and LOCALSTACK_* (the host LOCALSTACK_AUTH_TOKEN is dropped so it cannot override the token resolved by lstk).
The container also gets port mappings for 4566, 443, and the service port range 4510-4559.
OpenTelemetry tracing
Section titled “OpenTelemetry tracing”lstk can export traces of its own command execution over OTLP/HTTP.
Tracing is disabled by default.
Enable it with:
LSTK_OTEL=1 lstk startWhen enabled, every command is wrapped in a span (e.g. lstk.start) recording the exit code and any error.
lstk does not hardcode an export target, so the OpenTelemetry Go SDK reads the standard OTEL_EXPORTER_OTLP_* environment variables automatically (default target: OTLP/HTTP at localhost:4318).
You need an OTLP-compatible backend running to receive the traces.
Logging
Section titled “Logging”lstk writes its own diagnostic logs to lstk.log in the same directory as the active config file.
This is separate from the LocalStack container logs (which you view with lstk logs).
- The log file is created automatically and appended to across runs.
- When the file exceeds 1 MB, it is cleared on the next run.
- Use
lstk config pathto find the config directory;lstk.logsits alongsideconfig.toml.