Skip to content

chant emulator

llms.txt lists every page for an agent
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 --help

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

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.

Boots each configured lexicon’s emulator container and waits for it to report healthy, then prints the endpoint.

Terminal window
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/postgres

One 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:

Terminal window
chant emulator up --lexicon sql --port 5432=15432

When 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/postgres

up 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:

Terminal window
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.

Stops and removes the containers.

Terminal window
chant emulator down

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>`.
Terminal window
chant emulator status
aws: chant-floci — up on http://localhost:4566
FlagDescription
--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.
--loopbackup only. Publish ports on 127.0.0.1 only, instead of on every host interface.
--jsonEmit the machine-readable report on stdout instead of the human summary.

Other tools read this report. behold’s serve --local uses it to point itself at a running emulator.

Terminal window
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.

Terminal window
eval "$(chant emulator up --json | jq -r '.emulators[].env | to_entries[] | "export \(.key)=\(.value)"')"
chant lifecycle diff local --live

down 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":[]}.

LexiconContainerImagePortHealth checkEndpoint var
awschant-flocifloci/floci:1.5.344566/_localstack/health, waiting on cloudformationAWS_ENDPOINT_URL
azurechant-floci-azfloci/floci-az:0.10.04577/_floci/healthAZURE_ENDPOINT_URL
gcpchant-floci-gcpfloci/floci-gcp:0.5.04588/_floci-gcp/health—
flychant-mudflapsghcr.io/intentius/mudflaps:0.4.14280/_mudflaps/healthFLY_FLAPS_BASE_URL
flychant-spritzerghcr.io/intentius/spritzer:0.4.14290/_spritzer/healthSPRITES_BASE_URL
sqlchant-clickhouseclickhouse/clickhouse-server:26.8.15.10, by digest8123/pingCLICKHOUSE_URL
sqlchant-postgrespostgres:18.6, by digest5432pg_isready in the container, over TCPPOSTGRES_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.

CodeMeaning
0The action completed, including the case where no configured lexicon has an emulator
1No 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
  • 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

chant