Skip to content

Make LocalStack lifecycle CLI-agnostic (support lstk; Docker-API stop)#50

Open
maximkasy wants to merge 1 commit into
mainfrom
gap-3-lifecycle-cli-agnostic
Open

Make LocalStack lifecycle CLI-agnostic (support lstk; Docker-API stop)#50
maximkasy wants to merge 1 commit into
mainfrom
gap-3-lifecycle-cli-agnostic

Conversation

@maximkasy

@maximkasy maximkasy commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Make LocalStack lifecycle CLI-agnostic (support lstk; Docker-API stop)

Follow-up to #49. After #49, detection and status are provenance-agnostic (gateway-based), but lifecycle still hardcoded the Python localstack binary and the management tool's preflight hard-required it. So a host that started LocalStack with lstk (the newer Go CLI) and doesn't have the Python localstack CLI installed couldn't start/stop/restart through the MCP — even though its LocalStack was up and reachable.

Changes

  • stop → Docker API. Stop the already-detected container (findLocalStackContainer) via the Docker API. Provenance-agnostic and CLI-free — works whether LocalStack was started by localstack, lstk, docker-compose, or docker run. It also fixes a mixed-CLI mismatch: localstack stop only targets localstack-main, so it silently misses an lstk-started localstack-aws. (LocalStack containers run with --rm, so stopping also removes them, matching localstack stop.)
  • start → detect the CLI. Use whichever lifecycle CLI is present — localstack, else lstk (which also forwards LOCALSTACK_* env). Clear error when neither is installed, instead of an opaque spawn localstack ENOENT.
  • restart → Docker-API stop + start (still applies new envVars).
  • Preflight: dropped requireLocalStackCli from the management tool — status/stop/restart don't need a CLI, and start detects one itself. Snowflake start still requires localstack (--stack snowflake is localstack-only).
  • Windows UTF-8: set PYTHONIOENCODING=utf-8 / PYTHONUTF8=1 on the start subprocess so the Python CLI's emoji output can't throw UnicodeEncodeError under the Windows cp1252 code page.

Why it's better

Previously the only supported lifecycle path was the Python localstack CLI, and the preflight rejected anything else — which broke the documented lstk quickstart and gave confusing errors on mixed-CLI machines. Now lifecycle is driven by the Docker API + gateway and shells out to a CLI only for start (detecting whichever is installed), so it works for localstack, lstk, and externally-managed containers alike.

Tests

  • DockerApiClient.stopContainer + detectLifecycleCli unit tests.
  • Lifecycle tool-boundary tests: start-with-no-CLI error, stop via Docker API, stop-when-not-running.
  • npx jest → 19 suites / 120 tests; tsc --noEmit clean; xmcp build registers 14 tools and the server starts clean.
  • Ran a full live start → status → aws-client → restart → stop cycle on Windows against a real Pro/Enterprise token; the CI smoke job covers the same on Linux.

Notes

  • This makes the lifecycle start spawn UTF-8-safe. logs / extensions / ephemeral and the optional status CLI-enrichment still shell out to localstack without forcing UTF-8 — a centralized UTF-8 fix for all localstack subprocess calls would be a sensible follow-up.
  • Also restores a management tool test that was present in Provenance-agnostic LocalStack detection + Windows/cross-platform fixes #49's branch but dropped from main during the squash merge.

🤖 Generated with Claude Code

… stop)

Follow-up to #49 (gap #3). start/stop/restart hardcoded the Python `localstack`
binary and the management preflight hard-required it, so an `lstk`-only host (no
Python CLI) couldn't start/stop/restart through the MCP even though its LocalStack
was running.

- stop: stop the already-detected container via the Docker API — provenance-
  agnostic and CLI-free (works for localstack / lstk / compose / raw `docker run`).
- start: detect whichever lifecycle CLI is present (`localstack`, else `lstk`)
  rather than hardcoding `localstack`; clear error if neither is installed.
- restart: Docker-API stop + start (still applies new envVars).
- drop `requireLocalStackCli` from the management preflight (status/stop/restart no
  longer need it; start detects a CLI itself). Snowflake start still requires
  `localstack` — `--stack snowflake` is localstack-only.

Also (gap #6, for the lifecycle spawn): set PYTHONIOENCODING=utf-8 / PYTHONUTF8=1 on
the start subprocess so the Python CLI's emoji output doesn't crash under the Windows
cp1252 code page.

Adds DockerApiClient.stopContainer and detectLifecycleCli with unit tests, plus
lifecycle tool-boundary tests. Also restores the management status tests that were
dropped from main during the #49 squash merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maximkasy maximkasy requested a review from HarshCasper June 25, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant