diff --git a/src/content/docs/aws/developer-tools/running-localstack/lstk.mdx b/src/content/docs/aws/developer-tools/running-localstack/lstk.mdx index 9eef67b1..2489db17 100644 --- a/src/content/docs/aws/developer-tools/running-localstack/lstk.mdx +++ b/src/content/docs/aws/developer-tools/running-localstack/lstk.mdx @@ -398,6 +398,8 @@ lstk stop --non-interactive `stop` fails fast if the Docker runtime is not healthy (for example, Docker is not running), or if a configured emulator is not currently running (`LocalStack is not running`). In an interactive terminal it shows an animated "Stopping LocalStack..." spinner and a styled confirmation; in non-interactive mode it prints the same progress and result as plain text. +`stop` supports [`--json`](#structured-output): the `data` payload lists each configured emulator and whether it `wasRunning`. + ### `restart` Stop and restart the LocalStack emulator. @@ -816,6 +818,8 @@ In non-interactive mode it fails unless `--force` is passed: reset requires confirmation; use --force to skip in non-interactive mode ``` +`reset` supports [`--json`](#structured-output): on success the `data` payload reports the reset emulator and `"reset": true`. + :::note `reset` clears in-memory state only. It does **not** wipe the on-disk volume (certificates, persistence data, cached tools). @@ -1052,6 +1056,7 @@ lstk update [options] |:--------------------|:-------------------------------------------------------------| | `--check` | Check for updates without installing them | | `--non-interactive` | Use plain output instead of the TUI (update logic unchanged) | +| `--json` | Emit the result as a JSON envelope (see [Structured output](#structured-output)). With `--check`, `data` reports `currentVersion`/`latestVersion`/`updateAvailable`; after an applied update, `updatedVersion`/`updated`/`method`. | Examples: @@ -1126,7 +1131,7 @@ These options are available for all commands: |:--------------------|:---------------------------------------------------------------------------| | `--config ` | Path to a specific TOML config file | | `--non-interactive` | Disable the interactive TUI, use plain output | -| `--json` | Output in JSON format (only supported by some commands, e.g. the tool proxies) | +| `--json` | Emit a single machine-readable JSON envelope on stdout instead of human-oriented output. Supported today by `stop`, `reset`, and `update`; any other command rejects it. See [Structured output](#structured-output). | | `--persist` | Persist emulator state across restarts (on `start`/bare `lstk` and `restart`) | | `--snapshot ` | 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`) | @@ -1153,6 +1158,73 @@ Commands that mutate state without prompting in CI (`reset`, `volume clear`) req `lstk setup aws` works non-interactively — it writes the profile with defaults and needs `--force` only to overwrite a conflicting `localstack` profile. ::: +## 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 being rolled out per command: today `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: + +```json +{ + "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, currently always `1`. 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: + +```json +{ + "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 + +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`). | + +:::note +`--json` implies non-interactive behavior: no TUI and no prompts. +Combining it with a destructive command that would otherwise prompt (`reset`) still requires `--force`, which surfaces as `CONFIRMATION_REQUIRED` (exit code `3`) when omitted. +::: + ## Environment variables The following environment variables configure `lstk` itself (not the LocalStack container): @@ -1169,7 +1241,7 @@ The following environment variables configure `lstk` itself (not the LocalStack | `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 `DOCKER_HOST` is not set, `lstk` tries the default Docker socket and then probes common alternatives (Colima at `~/.colima/default/docker.sock`, OrbStack at `~/.orbstack/run/docker.sock`). +When `DOCKER_HOST` is not set, `lstk` tries the default Docker socket and then probes common alternatives (Colima at `~/.colima/default/docker.sock` or `~/.config/colima/default/docker.sock`, OrbStack at `~/.orbstack/run/docker.sock`). When `LSTK_OTEL` is enabled, the standard `OTEL_EXPORTER_OTLP_*` environment variables are honored by the OpenTelemetry SDK. @@ -1225,7 +1297,7 @@ This is separate from the LocalStack container logs (which you view with `lstk l There is no `--offline` flag. Instead, `lstk` degrades gracefully when common enterprise blockers (Docker Hub unreachable, a proxy/TLS interceptor, or an unreachable license server) prevent an internet request: - **Image pull**: if the image pull fails but the image is already present locally, `lstk` warns and uses the local image instead of failing. In interactive mode you can also press Esc to abort an in-progress pull and fall back to the local image. -- **License pre-flight**: when the pinned image is already present locally, `lstk` skips its pre-flight license check so a fully offline start is not blocked; the container validates its own bundled license at startup. When a check does run, a definitive server rejection (e.g. HTTP 403/400) is still fatal, but a transport-level failure (offline, proxy, or certificate error) is treated as non-fatal and the container validates its own license instead. +- **License pre-flight**: when the pinned image is already present locally, `lstk` skips its pre-flight license check so a fully offline start is not blocked; the emulator validates the license itself once it starts. When a check does run, a definitive server rejection (e.g. HTTP 403/400) is still fatal, but a transport-level failure (offline, proxy, or certificate error) is treated as non-fatal and the emulator validates the license instead. The pre-flight is also skipped — with a warning — when the license server does not recognize the image *tag format* (for example a `dev` nightly or a custom internal-mirror tag): that is not a verdict on the license, so `lstk` defers to the emulator's own startup check rather than blocking the start. - **Telemetry and update checks** are best-effort and fail silently when offline. Pair this behavior with a custom [`image`](#custom-container-image) that points at an internal-registry mirror or a locally loaded image to run `lstk` in an air-gapped environment.