Skip to content
Get Started for Free

lstk Automation & CI

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 prompt of volume clear display a Bubble Tea-powered terminal UI.
  • Non-interactive mode (plain text): used when stdin or stdout isn’t a terminal, for example when you pipe or redirect the output, or in a typical CI job. Force this in a terminal with --non-interactive.
Terminal window
# Force plain output even in an interactive terminal
lstk --non-interactive start

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, or one running in CI or on another machine.

Terminal window
# Run against an emulator reachable at a custom URL
lstk --endpoint-url http://localhost:4566 az group list
# Equivalent via the environment
LSTK_ENDPOINT_URL=http://localhost:4566 lstk status

Put --endpoint-url before az; anything after az goes to the Azure CLI, which doesn’t know the flag.

The 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 lstk --endpoint-url https://localhost.localstack.cloud:4566 status talks to the emulator over HTTPS.

The commands that accept an external endpoint are the ones that only talk to an already-running emulator: az and status. doctor also uses it, to check the host names derived from the endpoint.

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. For example, lstk --endpoint-url http://localhost:4566 start fails with start does not support --endpoint-url.

lstk detects the emulator’s type (AWS, Azure, or Snowflake) by probing the endpoint’s health API. There is no flag or config setting to override the detected type, and a failed probe stops the command, for example with could not reach LocalStack emulator at <url> when the endpoint isn’t a LocalStack emulator. The AWS-only tools (aws, terraform, cdk, sam) reject an endpoint whose detected type is not AWS.

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: the bare lstk, start, stop, status, update, and doctor accept --json. Commands without JSON support, such as logs and config path, reject 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": "azure", "name": "localstack-azure", "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", "status").
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, AUTH_REQUIRED, RUNTIME_UNAVAILABLE), a coarse category, a human-readable message (informational only — branch on code, not message), and a retryable boolean:

{
"schemaVersion": 1,
"command": "status",
"status": "error",
"data": null,
"warnings": [],
"error": {
"code": "EMULATOR_NOT_RUNNING",
"category": "EMULATOR",
"message": "LocalStack Azure Emulator is not running",
"retryable": false
}
}

With --json, the process exit code tells you whether the command succeeded and flags a missing auth token. For every other failure, read error.code from the envelope:

Exit code Meaning
0 status: "ok".
1 status: "error" for any code other than AUTH_REQUIRED. Usage errors, such as an unknown flag, also exit with 1.
4 error.code == "AUTH_REQUIRED": no auth token was found (run lstk login or set LOCALSTACK_AUTH_TOKEN).

lstk also has exit code 3 for CONFIRMATION_REQUIRED, but only the AWS-only reset command returns it.

Without --json, lstk exits with 0 on success and 1 on any failure, including a missing auth token. A proxied tool passes its own exit code through: when lstk az group show fails because the resource group doesn’t exist, lstk exits with the Azure CLI’s code 3.

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. Bypasses the localhost.localstack.cloud DNS probe. lstk setup azure and lstk az start-interception register https://azure.<host> as the Azure CLI endpoint, so for Azure the value must be a host name whose azure. subdomain resolves to the emulator.
LOCALSTACK_DISABLE_EVENTS Set to 1 to stop lstk, and extensions such as doctor, from sending usage events.
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_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_CHECK_FOR_UPDATE_ON_STARTUP Set to false to skip the update check when the emulator starts, or true to force it. Overrides the check_for_update_on_startup key under [cli] in config.toml.
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.

lstk talks to a Docker-compatible runtime and works with Docker Desktop, Rancher Desktop, Colima, OrbStack, Lima, and Podman. It resolves the daemon endpoint in this order:

  1. DOCKER_HOST, if set, always wins.
  2. DOCKER_CONTEXT or the active Docker CLI context, when it isn’t default and its local socket (or named pipe, on Windows) is reachable. A stale or unreachable context is skipped rather than failing.
  3. On Linux, a live /var/run/docker.sock: a running Docker daemon is preferred over a co-installed runtime such as Podman.
  4. 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.
  5. 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.

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-azure Container name for internal references.
LOCALSTACK_HOST localhost.localstack.cloud:<host port> Hostname/port the emulator advertises.
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). It skips, with a warning, any LOCALSTACK_* variable whose value spans several lines or that would replace a critical variable inside the emulator, such as LOCALSTACK_PATH or LOCALSTACK_HOME. LOCALSTACK_* variables keep their prefix, and the Azure emulator reads them as if it weren’t there: LOCALSTACK_LS_AZURE_PORTAL=1 works like LS_AZURE_PORTAL=1.

The container also gets port mappings for 4566, 443, and the service port range 4510-4559.

lstk can export traces of its own command execution over OTLP/HTTP. Tracing is disabled by default. Enable it with:

Terminal window
LSTK_OTEL=1 lstk start

When 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.

lstk writes its own diagnostic logs to lstk.log in its config directory: the directory of the config.toml found through the search order. 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.
  • Run lstk config path (without --config) to find the config directory; lstk.log sits alongside that config.toml.
  • --config doesn’t move the log: with --config ./other.toml, lstk still writes to the lstk.log in its config directory.
Was this page helpful?