chant emulator
Synopsis
Section titled “Synopsis”chant emulator up [--lexicon <name>] [--port <container-port>=<host-port>] [--image <ref>] [--network <name>] [--setting <KEY>=<VALUE>] [--loopback] [--json]chant emulator down [--lexicon <name>] [--json]chant emulator status [--lexicon <name>] [--json]chant emulator --helpchant emulator --help prints this command’s usage. It also lists each
emulator the project’s lexicons declare, with the port and sign-in a client
needs.
Description
Section titled “Description”chant emulator manages the local emulators of the lexicons your project
configures, and reports the endpoint and environment that redirect tooling at
them.
The Local Testing pages boot an emulator
inside an Op, which tears it down again when the Op finishes. This command is
the other shape: up leaves the emulator running so you can deploy to it,
observe it with chant lifecycle diff --live, graph it
with chant graph --live, and come back to it across
several commands.
Every action is idempotent. up on an already-running emulator reports the
existing endpoint rather than starting a second container.
Subcommands
Section titled “Subcommands”emulator up
Section titled “emulator up”Boots each configured lexicon’s emulator container and waits for it to report healthy, then prints the endpoint.
chant emulator up✓ aws: chant-floci up on http://localhost:4566✓ azure: chant-floci-az up on http://localhost:4577✓ gcp: chant-floci-gcp up on http://localhost:4588✓ fly: chant-mudflaps up on http://localhost:4280✓ fly: chant-spritzer up on http://localhost:4290✓ sql: chant-clickhouse up on http://localhost:8123✓ sql: chant-postgres up on postgres://localhost:5432/postgresOne line per emulator, not per lexicon: fly and sql ship two each, and
--lexicon fly acts on both of fly’s.
Before it starts a container, up checks that nothing else listens on
127.0.0.1:<port>. On macOS, Docker publishes 0.0.0.0:5432 even while a
native Postgres holds 127.0.0.1:5432. Connections to localhost:5432 then
reach the native server. up refuses in that case and names the port, and
--port publishes the emulator elsewhere:
chant emulator up --lexicon sql --port 5432=15432When up reuses a running container, it reads the address that container
publishes from Docker (docker port) and prints that address.
For an emulator with an identity check (Postgres, ClickHouse) it also checks
that the address reaches the container’s server. If localhost reaches
another server but the container’s IPv6 or other published address works,
up says so and prints that address:
emulator "chant-postgres": localhost:5432 reaches another Postgres (PostgreSQL 16.14), not the emulator. The emulator answers on postgres://[::1]:5432/postgres; use that address.✓ sql: chant-postgres up on postgres://[::1]:5432/postgresup fails when no published address reaches the emulator. It also fails when
the container publishes no host port. Both errors say how to republish it.
Four more flags change the container up starts (chant #3952). The command
below starts another Floci tag on the loom-local Docker network with one Floci
setting. --loopback publishes it on 127.0.0.1:4566 only:
chant emulator up --lexicon aws --image floci/floci:<tag> --network loom-local \ --setting FLOCI_<NAME>=<value> --loopback--setting passes -e KEY=VALUE to docker run. The key has to start with
the emulator’s settings prefix, FLOCI_ for aws. Any other key is refused
before a container starts, so the flag can’t put arbitrary environment into
the container. A lexicon’s emulator that declares no prefix takes no settings.
With several emulators selected, each setting goes to the emulators whose
prefix it matches.
These four flags take effect when a container starts. up on a running
container reuses it as it is and prints a note saying so; run down first to
restart it with them.
emulator down
Section titled “emulator down”Stops and removes the containers.
chant emulator downemulator status
Section titled “emulator status”Reports whether each emulator is running, without starting or stopping
anything. A container that is not running reports down with an empty
endpoint. The endpoint uses the host port Docker published, so it follows a
--port given to up.
For the sql lexicon’s emulators, status also checks that the printed
endpoint reaches the container: it compares the server’s identity read inside
the container (Postgres’s system identifier, ClickHouse’s serverUUID())
with the one read through the endpoint. When they differ, the line names the
server that answered and the command exits 1. In the JSON report, that
emulator has a conflict message in place of its endpoint and env, which are empty:
✗ sql: chant-postgres runs, but localhost:5432 answers as PostgreSQL 16.14, not the emulator; another Postgres holds 127.0.0.1:5432. Run `chant emulator down --lexicon sql`, then `chant emulator up --lexicon sql --port 5432=<free port>`.chant emulator statusaws: chant-floci — up on http://localhost:4566| Flag | Description |
|---|---|
--lexicon <name> | Act on one lexicon’s emulator instead of all of them. A lexicon with no emulator, or one this project does not configure, warns and exits 0. |
--port <container-port>=<host-port> | up only. Publish that container port on another host port. Repeatable; a bare <host-port> works when one emulator is selected. |
--image <ref> | up only. Start this image instead of the pinned default. Needs exactly one emulator selected (use --lexicon). |
--network <name> | up only. Join each started container to this Docker network (docker run --network). |
--setting <KEY>=<VALUE> | up only. Pass an emulator setting as -e KEY=VALUE. Repeatable. The key must start with the emulator’s prefix (FLOCI_ for aws); other keys are refused. |
--loopback | up only. Publish ports on 127.0.0.1 only, instead of on every host interface. |
--json | Emit the machine-readable report on stdout instead of the human summary. |
--json
Section titled “--json”Other tools read this report. behold’s
serve --local uses it to point itself at a running emulator.
chant emulator up --json{ "emulators": [ { "lexicon": "aws", "name": "chant-floci", "endpoint": "http://localhost:4566", "env": { "AWS_ENDPOINT_URL": "http://localhost:4566", "AWS_ACCESS_KEY_ID": "test", "AWS_SECRET_ACCESS_KEY": "test", "AWS_REGION": "us-east-1" } } ]}Export the env variables to make the AWS SDK, chant lifecycle --live, and a
triggered Op talk to the emulator rather than the real account.
eval "$(chant emulator up --json | jq -r '.emulators[].env | to_entries[] | "export \(.key)=\(.value)"')"chant lifecycle diff local --livedown and a stopped status report an empty endpoint and an empty env, so
a consumer can tell “not running” from “running here” without parsing prose.
With --json, a project whose lexicons have no emulator reports
{"emulators":[]}.
The emulators
Section titled “The emulators”| Lexicon | Container | Image | Port | Health check | Endpoint var |
|---|---|---|---|---|---|
| aws | chant-floci | floci/floci:1.5.34 | 4566 | /_localstack/health, waiting on cloudformation | AWS_ENDPOINT_URL |
| azure | chant-floci-az | floci/floci-az:0.10.0 | 4577 | /_floci/health | AZURE_ENDPOINT_URL |
| gcp | chant-floci-gcp | floci/floci-gcp:0.5.0 | 4588 | /_floci-gcp/health | — |
| fly | chant-mudflaps | ghcr.io/intentius/mudflaps:0.4.1 | 4280 | /_mudflaps/health | FLY_FLAPS_BASE_URL |
| fly | chant-spritzer | ghcr.io/intentius/spritzer:0.4.1 | 4290 | /_spritzer/health | SPRITES_BASE_URL |
| sql | chant-clickhouse | clickhouse/clickhouse-server:26.8.15.10, by digest | 8123 | /ping | CLICKHOUSE_URL |
| sql | chant-postgres | postgres:18.6, by digest | 5432 | pg_isready in the container, over TCP | POSTGRES_URL (with POSTGRES_USER and POSTGRES_PASSWORD) |
The ClickHouse emulator signs in as default with no password; the Postgres
one as postgres with password chant.
gcp has no endpoint variable because gcpApply takes the endpoint as an
explicit argument rather than reading one. chant emulator up --json still
reports the endpoint, with nothing to export.
Every image is pinned rather than tracking :latest, so a local suite that
passes today does not fail tomorrow because an image moved. A weekly workflow
reports how far behind each pin is; the bump is a human decision, made when a
consuming test needs the newer emulator.
Requires Docker. When docker is not on PATH, status prints
docker not found on PATH; cannot check the emulator and exits 1. A daemon
that does not answer is reported the same way.
Exit Codes
Section titled “Exit Codes”| Code | Meaning |
|---|---|
| 0 | The action completed, including the case where no configured lexicon has an emulator |
| 1 | No subcommand, or one that is not up, down, or status; a bad --port, --image or --setting, or an up-only flag on another subcommand; up failed (for example, the host port is held by another process); or status could not ask Docker, or found an endpoint that reaches another server |
See Also
Section titled “See Also”- Local Testing — deploying chant’s real output to an emulator, per cloud
chant lifecycle— observing a running emulator with--live- Config File — binding an endpoint to a named environment