Environment variables
Lattice reads a small set of environment variables to decide its own
behavior, and sets a small set of its own in the environment of the commands
it spawns. This page is the exhaustive list of both, plus how a task’s
declared env names turn into resolved values and a cache-key input.
What Lattice reads
| Variable | What it does | Counts as set when |
|---|---|---|
CI |
Forces Raw output instead of the interactive TUI, the same as -l/--loquacious. |
Present, any value, including empty |
NO_COLOR |
Disables ANSI color in output. Nothing in lattice.json or on the CLI turns color back on once this is set. |
Present, any value, including empty |
LATTICE_NO_VERSION_CHECK |
Suppresses both the version-drift nag and the automatic switch-over to a pinned latticeVersion. Equivalent to --no-version-check for this invocation or settings.versionCheck: false for the whole repo — see Upgrading for how the three interact. |
Present, any value, including empty |
LATTICE_SWITCHED_FROM |
Internal. Set by Lattice on the process it hands an invocation to after a version switch, so that process doesn’t try to switch again. Not meant to be set by hand. | Present, any value |
LATTICE_THEME |
light or dark (case-insensitive), forces the teal shade used in the splash/logo art. Any other value is ignored. |
Recognized value present |
COLORFGBG |
Consulted for the splash theme only when LATTICE_THEME is unset. Read as fg;bg (or fg;...;bg); a trailing 7 or 15 is treated as a light background, anything else as dark. |
LATTICE_THEME unset and this parses |
LATTICE_RELEASE_BASE_URL |
Overrides the base URL lattice upgrade and the automatic version switch download release archives from. A file:// base makes the install path testable without a network. |
Present and not empty/whitespace-only |
LATTICE_RELEASE_LATEST_URL |
Overrides the endpoint used to resolve lattice upgrade latest’s newest stable release. |
Present and not empty/whitespace-only |
LATTICE_RELEASE_LIST_URL |
Overrides the endpoint used as a fallback when the latest-stable endpoint has nothing to name (every release so far is a pre-release). | Present and not empty/whitespace-only |
Two things worth noting about that “counts as set” column. CI,
NO_COLOR, LATTICE_NO_VERSION_CHECK, and LATTICE_SWITCHED_FROM are all
checked with presence alone — CI= (empty string) counts exactly the same as
CI=1 or CI=false. The three LATTICE_RELEASE_*_URL overrides are the one
exception: an empty or whitespace-only value is treated as unset and falls
back to the default, so LATTICE_RELEASE_BASE_URL= in an inherited
environment doesn’t silently break the default download path.
CI and -l/--loquacious are independent triggers for the same Raw
mode — neither overrides the other, and there’s no way to force interactive
mode back on from inside a CI=1 environment. See
Output and logging for the rest of how output
mode is chosen, and Upgrading for the full
precedence story of the version-check suppressions.
What Lattice sets for a spawned command
A task’s command runs through the platform shell (sh -c on Unix, cmd /C
on Windows) as a child process that inherits the full environment Lattice
itself was invoked with — nothing is cleared. On top of that inheritance,
Lattice explicitly sets:
| Variable | Shape | When |
|---|---|---|
PATH |
The resolved toolchain bin directories for that task, in order, prepended ahead of the inherited PATH. |
Every task with a provisioned engine, and every lattice setup install command |
Each name listed in a task’s env |
The value read from Lattice’s own environment at the moment the cache key was computed. | Every task that declares env |
LATTICE_TOOLCHAIN_DIR |
Absolute path to the toolchain’s install directory, both as an env var and literal-substituted into the installCmd string itself. |
Only while running an engine’s installCmd, never for the task command that follows |
PATH is scoped to that one child process — it never touches the shell
Lattice itself is running in. See Engines and provisioning
for what gets installed into LATTICE_TOOLCHAIN_DIR and how the resulting
bin directory ends up on PATH.
How a task’s env list resolves
env on a PipelineTask is a list of variable names, not NAME=value
pairs:
{
"tasks": {
"build": {
"inputs": ["src/**/*"],
"env": ["NODE_ENV", "API_BASE_URL"]
}
}
}
For each name, Lattice reads the value from its own process environment —
whatever was exported into the shell you ran lattice from. It does not load
.env files; if a variable is only defined in one, it is unset as far as
Lattice is concerned. A name with no value at all in the environment
contributes nothing — the same as if it weren’t listed. Only a variable that
is actually set changes anything.
The resolved (name, value) pairs are sorted by name and hashed into the
task’s cache key alongside its command, its input files, and its resolved
toolchain identity — see Caching for the rest of
what feeds that key. The same resolved values are also what Lattice sets on
the task’s own process, on top of the full inheritance described above.
That leaves a practical difference between listing a variable and not:
- List it, and a different value on a later run changes the cache key, so a build that behaves differently under a new value re-runs instead of restoring a result computed under the old one.
- Don’t list it, and the task’s process still sees it — inheritance
doesn’t care about
env— but the cache key doesn’t move when it changes. A command whose output actually depends on an undeclared variable can be served a stale cache hit from a run made under a different value, with no indication anything was skipped.
The rule is the same one that applies to inputs: declare what the command’s
result actually depends on, nothing more. Listing a variable that’s noisy but
irrelevant (a timestamp, a machine-specific temp path) costs you cache hits
you didn’t need to lose.