Skip to content
Get Started for Free

lstk Migration Guide

lstk is the new command-line interface for LocalStack. It is a single, self-contained binary that starts and manages the emulator and runs the Azure CLI against it. For LocalStack for Azure, it replaces two tools: the Python-based localstack CLI, which you pointed at the Azure image with IMAGE_NAME, and the azlocal wrapper, which redirected the Azure CLI to the emulator.

There are three good reasons to start using lstk:

  1. Installation is simpler, because there is no Python environment to manage and no separate wrapper to install.
  2. lstk knows the Azure emulator. Setting type = "azure" in its configuration selects the right image, so there is no IMAGE_NAME to remember.
  3. lstk is the place for new CLI functionality to be added from now on. The localstack CLI is deprecated and no longer receives updates.

What does not change is LocalStack itself. The emulator is the same localstack/localstack-azure image, with the same behavior and the same configuration variables (LS_AZURE_PORTAL, MSSQL_ACCEPT_EULA, DEBUG, and the rest). You are changing the tool you drive the emulator with, not the emulator itself.

lstk is distributed through the LocalStack Homebrew tap and the @localstack/lstk npm package. Pre-built binaries for Linux, macOS, and Windows are published on GitHub Releases. Pick whichever fits your environment.

Terminal window
brew install localstack/tap/lstk

Check for correct installation by invoking lstk --version. Docker must be installed and running, exactly as before, and so must the Azure CLI if you run az commands. There is no need to uninstall the localstack CLI or azlocal, as they can exist side by side with lstk.

Both CLIs need a LocalStack license to run the emulator, but they ask for it in different ways. With the localstack CLI you copied an auth token out of the web application and stored it with localstack auth set-token, or exported LOCALSTACK_AUTH_TOKEN yourself.

lstk replaces that with a browser-based login triggered automatically: simply running lstk or lstk start takes you through the login flow the first time, opening a browser window for you to approve the request. The credential is then stored securely on your machine.

Run lstk login directly if you want to authenticate ahead of time, and lstk logout to remove the auth token from your machine. To switch accounts, run lstk logout and then lstk login: while a token is stored, or LOCALSTACK_AUTH_TOKEN is set, lstk login only reports that you’re already logged in.

Continuous integration has no browser, so auth tokens remain the right approach there. Set LOCALSTACK_AUTH_TOKEN as a secret in your pipeline, and lstk will use it without any login step. Use a CI Auth Token rather than a personal developer token, as described in CI Environments.

lstk keeps its settings in a TOML file named config.toml. It describes the LocalStack container you want to run: which emulator to start, which image tag to use, which port to publish, and which environment variables to pass through. Where the localstack CLI took all of this as flags and environment variables at start-up, lstk reads it from this file on every run.

You do not need to write the file by hand. lstk creates a default config.toml the first time you run it; choose z when it asks which emulator to run. lstk config path prints the location of the file currently in effect:

Terminal window
lstk config path

A bare-bones file for the Azure emulator looks like this:

[[containers]]
type = "azure" # aws, snowflake, or azure
tag = "latest" # image tag to run
port = "4566" # host port to publish

lstk looks for .lstk/config.toml in the current directory first, and falls back to a user-level file in your home directory (such as ~/.config/lstk/config.toml). A project can therefore carry its own settings in version control, while your personal defaults apply outside of that project. To use a file somewhere else entirely, pass lstk --config <path>. See Configuration for everything else you can put in it.

Starting, stopping, restarting, and upgrading

Section titled “Starting, stopping, restarting, and upgrading”

Day-to-day lifecycle management is where the two CLIs line up most closely. The most noticeable difference is that lstk start completes only once the emulator is ready to serve requests, so the pattern of starting in the background and then waiting is no longer necessary. Running lstk with no arguments does the same thing as lstk start.

With localstack With lstk
IMAGE_NAME=localstack/localstack-azure:latest localstack start -d lstk start, or simply lstk, with type = "azure" in config.toml
localstack wait No equivalent is needed, because lstk start returns only once the emulator is ready.
localstack stop lstk stop
localstack restart lstk restart
localstack status docker lstk status
localstack logs -f -n 100 lstk logs --follow --tail 100
localstack update localstack-cli lstk update

The two restarts differ. localstack restart restarts LocalStack inside the running container, and the Azure emulator keeps the resources you created. lstk restart stops the container and starts a new one, so the Azure emulator starts without any of your resources.

Upgrading now involves two separate things. First, lstk update upgrades the CLI itself, using whichever method you installed it with, and it also offers the upgrade when you start the emulator. Second, the emulator image is upgraded independently: with tag = "latest", lstk start pulls the newest image.

The emulator’s own configuration variables are unchanged. What changes is how you get them into the container.

For a one-off run, pass the variable on the command line with a LOCALSTACK_ prefix, so that lstk knows to forward it to the emulator:

Terminal window
LOCALSTACK_LS_AZURE_PORTAL=1 lstk start

For anything you use more than once, put it in the config.toml file instead. The file groups environment variables into named profiles that you can switch on and off:

[[containers]]
type = "azure"
tag = "latest"
port = "4566"
env = ["portal", "mssql"]
[env.portal]
LS_AZURE_PORTAL = "1"
[env.mssql]
MSSQL_ACCEPT_EULA = "Y"

With that in place, lstk start is the whole command.

If you use the Azure CLI with LocalStack, you have probably been using azlocal, either as a prefix for az commands or to redirect your global az to the emulator. lstk covers both, through lstk az:

With azlocal With lstk
azlocal group list lstk az group list
azlocal start-interception lstk az start-interception
azlocal stop-interception lstk az stop-interception

lstk az runs your own az binary in a config directory of its own, so your global ~/.azure configuration is left untouched and plain az keeps talking to real Azure. Prepare that directory once with lstk setup azure, while the emulator is running. The arguments after lstk az go to az unchanged, except for lstk’s own --non-interactive and --config flags, and the output and exit code come back unchanged. The interception commands change your global Azure CLI configuration, like the azlocal ones do. See Cloud & IaC commands for the details.

lstk also has proxies for Terraform, the AWS CDK, and the AWS SAM CLI, but they target the AWS emulator only. To use Terraform with the Azure emulator, keep using the azurerm provider as described in Terraform.

Not every LocalStack instance is started by lstk. You might instead use docker-compose.yml, or run it on a remote machine, or share a single deployment with others in your team. The global --endpoint-url option instructs lstk to communicate with an emulator that wasn’t started locally by lstk:

Terminal window
lstk --endpoint-url http://localhost:4566 status
lstk --endpoint-url http://localhost:4566 az group list

If you target the same instance repeatedly, set LSTK_ENDPOINT_URL in your environment:

Terminal window
export LSTK_ENDPOINT_URL=http://localhost:4566
lstk status
lstk az group list

Commands that manage the container itself, such as starting or stopping it or clearing its volume, do not support the --endpoint-url option. This is because lstk did not create the container and does not control its lifecycle.

The shape of a pipeline does not change when you move to lstk. You still install a CLI, start the emulator, run your tests against it, and let the job tear everything down at the end. The steps are simply shorter than they used to be.

There is no dedicated GitHub Action for lstk, so install it in a step of your own and call it directly. The npm package is a convenient option on hosted runners that include Node.js, such as the GitHub-hosted ones. A CI pipeline must supply a CI Auth Token through the LOCALSTACK_AUTH_TOKEN environment variable, normally from your CI system’s secret store, and select the emulator with --type azure, because nobody is there to answer the first-run prompt.

A GitHub Actions job then looks like this:

- name: Install lstk
run: npm install -g @localstack/lstk
- name: Start LocalStack for Azure
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
run: lstk start --type azure
- name: Set up the Azure CLI integration
run: lstk setup azure
- name: Run tests
run: |
lstk az group create --name test-rg --location westeurope
make test

lstk start returns only once the emulator is ready, so there is no need to wait for it explicitly. Output is plain text when running in CI, so commands that would normally ask for confirmation, such as lstk volume clear, require --force. To start a test suite from a clean emulator, run lstk restart.

Much of the work in a migration is not learning new commands but relocating settings. Start by gathering everything that currently configures LocalStack: flags on your localstack start command line, environment variables set in a shell profile, alias, or Makefile, any ~/.localstack profile files, and the environment section of a docker-compose.yml file if you have one. Nearly all of it maps onto fields in the lstk configuration file.

Previously In config.toml
IMAGE_NAME=localstack/localstack-azure:latest type = "azure"
IMAGE_NAME=registry.example.com/localstack/localstack-azure image = "registry.example.com/localstack/localstack-azure"
MSSQL_ACCEPT_EULA=Y, localstack start -e LS_AZURE_PORTAL=1 An [env.<name>] profile, referenced by env on the container
localstack start -v ./init.sh:/etc/localstack/init/ready.d/init.sh volumes = ["./init.sh:/etc/localstack/init/ready.d/init.sh"]
LOCALSTACK_VOLUME_DIR=./volume volume = "./volume"

To illustrate, the following before-and-after shows the mapping. Where you previously ran:

Terminal window
export IMAGE_NAME=localstack/localstack-azure:latest
MSSQL_ACCEPT_EULA=Y localstack start -d -e LS_AZURE_PORTAL=1
localstack wait
azlocal start-interception

you would now write a .lstk/config.toml in the project:

[[containers]]
type = "azure"
port = "4566"
env = ["portal", "mssql"]
[env.portal]
LS_AZURE_PORTAL = "1"
[env.mssql]
MSSQL_ACCEPT_EULA = "Y"

then start the emulator with lstk start, run lstk setup azure once, and use lstk az instead of the interception. Because the config.toml file lives in the repository, everyone on the team gets the same environment, and your CI jobs pick up the same file.

The CONFIG_PROFILE mechanism of the localstack CLI and its ~/.localstack/*.env files have no direct equivalent with lstk. The recommended replacement is a per-project .lstk/config.toml. If you need to switch between several configurations for the same project, keep them as separate files and choose between them with lstk --config <path>.

A handful of capabilities have not moved to lstk, although they may do so in a future release.

Not supported in lstk Recommended alternative
Shell access to the container (localstack ssh) Use docker exec -it localstack-azure bash.
Arbitrary Docker options, such as custom networks Use docker-compose.yml when you need full control of the container. The lstk configuration file covers the basic features: the image, tag, port, exposed ports, volumes, and environment variables.
GitHub Action There is no GitHub Action for lstk yet, and the existing setup-localstack Action installs the localstack CLI. Install lstk in a step of your own instead, as shown in Using lstk with Continuous Integration.

Snapshots and persistence aren’t on this list, because the Azure emulator doesn’t support them with either CLI.

Was this page helpful?