Three programs read the variables here, and they do not read the same ones: the
API and its migration (through compose.yaml), the hatch binary, and the
container runner's entrypoint. So look at the Read by column first.
Nothing here is secret-bearing by default: every default below is empty, a
public value or a plain setting. The few variables that carry a secret are
named as such, and the value belongs in your shell or a .env beside
compose.yaml, never in a file you commit. The configuration keys these
variables land on inside the API (Auth__*, Apps__*, Hatch__* and
ConnectionStrings__*) belong to Deployment overview,
not to this page.
Every variable#
One table, grouped by the bold label in the first column. "Settings file" says
whether the hatch binary will take the variable from scripts/.env or from
the per-user file hatch config writes, as well as from the environment; those
three layers are explained in the runner. A file
line naming a variable that says no is skipped, with a line on stderr
saying so; those are read from the environment alone.
| Variable | Read by | Default | What it does |
|---|---|---|---|
| The stack's, which you set | |||
HATCH_PORT |
compose.yaml, for the api service |
8080 |
The port on this machine the API is published at. |
HATCH_AUTH |
compose.yaml, for migrate and api (as Auth__Enabled) |
false |
Whether the wall is up. Turning it on is putting a front door on it. |
HATCH_GOOGLE_CLIENT_ID |
compose.yaml, for migrate and api |
empty | The Google sign-in client's id, for a Hatch with its wall up. |
HATCH_GOOGLE_CLIENT_SECRET |
compose.yaml, for migrate and api |
empty | A secret. The Google sign-in client's secret. |
HATCH_GOOGLE_REDIRECT_URI |
compose.yaml, for migrate and api |
empty: derived from the request | Where Google sends a person back to. Set it behind a TLS proxy, where the scheme and host the API sees are not the ones Google has registered. |
HATCH_PUBLIC_URL |
compose.yaml, for api (as Apps__PublicBaseUrl) |
empty: the address the runner itself reaches Hatch at | The address a browser opens this Hatch at, so a pull request's link back to its ticket is one a reviewer can open. |
HATCH_ANDROID_PACKAGE |
compose.yaml, for api |
empty: no statements are served | The package name of one phone's installed app, read off the phone (Hatch on your phone). |
HATCH_ANDROID_CERT_FINGERPRINT |
compose.yaml, for api |
empty: no statements are served | The signing certificate's fingerprint for that same app. |
| The stack's own, which nobody changes | |||
HATCH_MIGRATE |
the API (migrate sets it to 1) |
unset | Runs the API image as the migration, which exits when it is done, instead of serving. |
The runner service in the stack, from your shell or .env |
|||
HATCH_CHECKOUT |
compose.yaml, for runner |
.: the directory compose.yaml was reached from |
The repository mounted at /checkout. Right by default only inside Hatch's own checkout. |
HATCH_RUNNER_NAME |
compose.yaml, for runner (becomes HATCH_RUNNER) |
hatch-runner |
What Agents → Runners calls the container. |
HATCH_TAGS |
compose.yaml, for runner; then hatch |
empty: the container advertises no tags | The tags this container advertises, comma-separated (the runner). |
HATCH_GIT_NAME |
compose.yaml, for runner (becomes GIT_AUTHOR_NAME) |
empty; the container refuses to start without it | The name on the commits it makes. |
HATCH_GIT_EMAIL |
compose.yaml, for runner (becomes GIT_AUTHOR_EMAIL) |
empty; the container refuses to start without it | The email on the commits it makes. |
HATCH_GIT_TOKEN |
compose.yaml, for runner; then the entrypoint |
empty | A secret. An HTTPS token, answered to git through GIT_ASKPASS. |
HATCH_GH_TOKEN |
compose.yaml, for runner (becomes GH_TOKEN) |
empty: build checks and merges are off | A secret. The token gh reads to check builds and merge pull requests. |
Set for the container by compose.yaml or the image |
|||
HATCH_BASE |
compose.yaml, for runner; then hatch |
http://api:8080 |
The API over Compose's own network. Nothing about this crosses the machine. |
HATCH_ROOT |
the image; compose.yaml; then hatch and the entrypoint |
/checkout |
Where the checkout is mounted. The entrypoint unsets it when nothing is there and a workspace is. |
HATCH_WORKSPACE |
the image; compose.yaml; then hatch and the entrypoint |
/workspace |
Where the container clones what the board binds that it has no checkout of. |
The hatch binary |
|||
HATCH_BASE |
hatch |
none; hatch refuses to run without it |
The origin of your Hatch, as <your-hatch-origin>. A trailing / is trimmed. Settings file: yes, exported into every spawned session. |
HATCH_KEY |
hatch |
empty | A secret. The API key, shaped hatch_ak_.... Optional against a Hatch with its wall off. Settings file: yes, exported into every spawned session. |
HATCH_AGENT |
hatch; the container's entrypoint |
claude; blank also means claude |
Which agent a session spawns: claude, codex, grok or ollama. An unknown id is refused. Settings file: yes. |
HATCH_CLAUDE_BIN |
hatch |
unset: found on PATH |
The claude CLI, if it is not on PATH. Settings file: yes. |
HATCH_CODEX_BIN |
hatch |
unset: found on PATH |
The codex CLI, if it is not on PATH. Settings file: yes. |
HATCH_GROK_BIN |
hatch |
unset: found on PATH |
The grok CLI, if it is not on PATH. Settings file: yes. |
HATCH_OLLAMA_HOST |
hatch, through OllamaHost.Resolve |
unset: falls back to Ollama's own OLLAMA_HOST, then http://127.0.0.1:11434 |
Hatch's own override for where an ollama agent's server is. CanSpawn asks it once for GET /api/tags, and names it in the refusal when the host is not answering. Settings file: yes (OLLAMA_HOST itself is read only from the process environment, never from a settings file). |
HATCH_OLLAMA_TIERS |
hatch, through OllamaAdapter.ParseTiers |
empty | Which model id each alias (haiku, sonnet, opus, fable) means to an ollama agent, as comma-separated alias=id entries. An entry that is not alias=id, names an unknown alias or repeats one, or whose id is not an Ollama model id refuses every command. It has no hatch config flag. Settings file: yes. |
HATCH_BASE_BRANCH |
hatch |
unset: the branch origin calls its default | The trunk go-to-work resets to between increments. It has no hatch config flag. Settings file: yes. |
HATCH_RUNNER |
hatch |
unset: a cast-list name, chosen once per checkout | What the board calls this runner (the runner). Settings file: yes. |
HATCH_REPOS |
hatch |
empty | The checkouts a loop with no checkout of its own serves, joined on the platform's path separator (: on Unix, ; on Windows). Blanks are dropped. Settings file: yes. |
HATCH_TAGS |
hatch |
empty | The tags this runner advertises, comma-separated; trimmed, lowercased. A tag that breaks the rule (the runner) refuses every command. Settings file: yes. |
HATCH_WORKSPACE |
hatch |
unset: a per-user hatch/workspace under the OS application-data directory, created only when a clone needs it |
A directory the runner owns entirely, where it clones what the board binds that it has no checkout of. off, in any case, means never clone. Settings file: yes. |
HATCH_HEARTBEAT |
hatch |
20 |
Seconds of silence before the readout says what it is waiting on. 0 turns the pulse off; a value that is not a whole number, or is negative, falls back to 20. Settings file: no. |
HATCH_RETRY_SECONDS |
hatch |
90 |
Seconds a call keeps retrying Hatch. 0 means exactly one attempt; a value that is not a whole number, or is negative, falls back to 90. Settings file: no. |
HATCH_ROOT |
hatch |
unset: the nearest ancestor of the working directory that has a .git |
The checkout to work in. Set to a directory that does not exist, there is no fallback: hatch has no checkout. Settings file: no. |
HATCH_NIGHT_STATE |
hatch |
unset | Where a night's totals are handed to the loop that restarts into. Set only by scripts/hatch.sh and scripts/hatch.ps1, which is how a hand-started hatch knows nothing will restart it. Settings file: no. |
HATCH_RTK |
hatch |
unset | off, in any case, keeps RTK's Bash hook out of a session. Anything else uses it when rtk is on PATH. Settings file: no. |
| The wrapper scripts | |||
HATCH_RUNNER_BIN |
scripts/hatch.sh, scripts/hatch.ps1 |
unset: the script finds or builds the binary | The path of a hatch binary you already have, for a machine with no SDK. It must be an executable file. With it set there is nothing to rebuild. |
| The container's entrypoint | |||
HATCH_ROOT |
the entrypoint | /checkout, from the image |
If it holds a .git, it is added to git's safe.directory. If not, and HATCH_WORKSPACE is set, HATCH_ROOT is unset and the loop clones into the workspace. If neither, the entrypoint exits 1. |
HATCH_WORKSPACE |
the entrypoint | /workspace, from the image |
The fallback above. |
HATCH_GIT_TOKEN |
the entrypoint | empty | When set, the entrypoint exports GIT_ASKPASS. |
HATCH_AGENT |
the entrypoint | claude |
Exits 1 for anything but claude, codex, grok or ollama. |
HATCH_GIT_NAME |
the entrypoint, in its refusal only | It reads GIT_AUTHOR_NAME, which compose.yaml fills from this; its message names this variable. |
|
HATCH_GIT_EMAIL |
the entrypoint, in its refusal only | The same, for GIT_AUTHOR_EMAIL. |
|
HATCH_GH_TOKEN |
the entrypoint, in its message only | It checks whether gh is signed in, and names this variable when it is not. gh reads GH_TOKEN. |
|
HATCH_CHECKOUT |
the entrypoint, in its refusal only | It names this variable when there is no checkout to work in. |
The container's variables, with their defaults and what to put in them, are the container runner's table; the rows above are here so that every name has one home.
What the container sets from them#
When you are debugging a container you will look for these, and they come from three different places.
| Variable | Set by | Value |
|---|---|---|
GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL |
compose.yaml |
From HATCH_GIT_NAME and HATCH_GIT_EMAIL. |
GH_TOKEN |
compose.yaml |
From HATCH_GH_TOKEN. |
GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL |
the entrypoint | Copies of the author's. |
GIT_ASKPASS |
the entrypoint | /usr/local/bin/git-askpass.sh, only when HATCH_GIT_TOKEN is set. |
GIT_SSH_COMMAND |
the entrypoint | ssh -o StrictHostKeyChecking=accept-new, only when neither it nor ~/.ssh/known_hosts already exists. |
IS_SANDBOX |
the image | 1, because the claude CLI refuses to bypass permission prompts as root unless it is told it is in a sandbox. |
The agent's own credential is not a variable you set. The entrypoint fetches it
from your Hatch with hatch runner-credential and exports it before the loop
starts (the container runner).
HATCH_REVISION is a build argument in containers/hatch-runner/Dockerfile,
not a runtime variable: it stamps the revision into the binary when the image
is built, and nothing reads it once the image exists.
Not Hatch's own#
The hatch binary reads these and does not own them.
| Variable | What the binary does with it |
|---|---|
NO_COLOR |
Set to anything, even empty, it turns the readout's colour off. |
TERM |
dumb turns the readout off. |
PATH |
Where the agent CLIs and rtk are found when their HATCH_*_BIN variable is not set. |
CODEX_HOME |
Read to find the operator's Codex home. A codex session is spawned with its own overlay of it. |